mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
feat(chip): dot variant added, tests added
This commit is contained in:
parent
c45109c8f4
commit
417ccc8c0b
@ -1,5 +1,6 @@
|
||||
import * as React from "react";
|
||||
import {render} from "@testing-library/react";
|
||||
import {Avatar} from "@nextui-org/avatar";
|
||||
|
||||
import {Chip} from "../src";
|
||||
|
||||
@ -16,4 +17,43 @@ describe("Chip", () => {
|
||||
render(<Chip ref={ref} />);
|
||||
expect(ref.current).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should render with dot variant", () => {
|
||||
const wrapper = render(<Chip variant="dot" />);
|
||||
|
||||
expect(wrapper.container.querySelector("span")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should support avatar", () => {
|
||||
const wrapper = render(<Chip avatar={<Avatar data-testid="avatar" />} />);
|
||||
|
||||
expect(wrapper.getByTestId("avatar")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should support leftContent", () => {
|
||||
const wrapper = render(<Chip leftContent={<span data-testid="left-icon" />} />);
|
||||
|
||||
expect(wrapper.getByTestId("left-icon")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should support rightContent", () => {
|
||||
const wrapper = render(<Chip avatar={<span data-testid="close-icon" />} />);
|
||||
|
||||
expect(wrapper.getByTestId("close-icon")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should display a close button if onClose is passed", () => {
|
||||
const wrapper = render(<Chip onClose={() => {}} />);
|
||||
|
||||
expect(wrapper.getByRole("button")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should call onClose when close button is clicked", () => {
|
||||
const onClose = jest.fn();
|
||||
const {getByRole} = render(<Chip onClose={onClose} />);
|
||||
|
||||
getByRole("button").click();
|
||||
|
||||
expect(onClose).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@ -30,7 +30,7 @@ const Chip = forwardRef<ChipProps, "div">((props, ref) => {
|
||||
}
|
||||
|
||||
return leftContent;
|
||||
}, [leftContent, variant]);
|
||||
}, [slots, leftContent, variant]);
|
||||
|
||||
const right = useMemo(() => {
|
||||
if (isCloseable) {
|
||||
|
||||
@ -15,8 +15,13 @@ export interface UseChipProps extends HTMLNextUIProps<"div">, ChipVariantProps {
|
||||
* Ref to the DOM node.
|
||||
*/
|
||||
ref?: ReactRef<HTMLDivElement | null>;
|
||||
/**
|
||||
* Avatar to be rendered in the left side of the chip.
|
||||
*/
|
||||
avatar?: React.ReactNode;
|
||||
/**
|
||||
* Element to be rendered in the left side of the chip.
|
||||
* this props overrides the `avatar` prop.
|
||||
*/
|
||||
leftContent?: React.ReactNode;
|
||||
/**
|
||||
@ -33,6 +38,7 @@ export interface UseChipProps extends HTMLNextUIProps<"div">, ChipVariantProps {
|
||||
* base:"base-classes",
|
||||
* dot: "dot-classes",
|
||||
* label: "label-classes",
|
||||
* avatar: "avatar-classes",
|
||||
* closeButton: "close-button-classes",
|
||||
* }} />
|
||||
* ```
|
||||
@ -48,8 +54,18 @@ export interface UseChipProps extends HTMLNextUIProps<"div">, ChipVariantProps {
|
||||
export function useChip(originalProps: UseChipProps) {
|
||||
const [props, variantProps] = mapPropsVariants(originalProps, chip.variantKeys);
|
||||
|
||||
const {ref, as, children, leftContent, rightContent, onClose, styles, className, ...otherProps} =
|
||||
props;
|
||||
const {
|
||||
ref,
|
||||
as,
|
||||
children,
|
||||
avatar,
|
||||
leftContent,
|
||||
rightContent,
|
||||
onClose,
|
||||
styles,
|
||||
className,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const Component = as || "div";
|
||||
|
||||
@ -98,11 +114,20 @@ export function useChip(originalProps: UseChipProps) {
|
||||
};
|
||||
};
|
||||
|
||||
const getAvatarClone = (avatar: ReactNode) => {
|
||||
if (!isValidElement(avatar)) return null;
|
||||
|
||||
return cloneElement(avatar, {
|
||||
// @ts-ignore
|
||||
className: slots.avatar({class: styles?.avatar}),
|
||||
});
|
||||
};
|
||||
|
||||
const getContentClone = (content: ReactNode) =>
|
||||
isValidElement(content)
|
||||
? cloneElement(content, {
|
||||
// @ts-ignore
|
||||
className: clsx("w-full h-4/5", content.props.className),
|
||||
className: clsx("max-h-[80%]", content.props.className),
|
||||
})
|
||||
: null;
|
||||
|
||||
@ -112,7 +137,7 @@ export function useChip(originalProps: UseChipProps) {
|
||||
slots,
|
||||
styles,
|
||||
variant: originalProps.variant,
|
||||
leftContent: getContentClone(leftContent),
|
||||
leftContent: getAvatarClone(avatar) || getContentClone(leftContent),
|
||||
rightContent: getContentClone(rightContent),
|
||||
isCloseable,
|
||||
getCloseButtonProps,
|
||||
|
||||
@ -34,11 +34,6 @@ export default {
|
||||
options: ["xs", "sm", "md", "lg", "xl"],
|
||||
},
|
||||
},
|
||||
fullWidth: {
|
||||
control: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
isDisabled: {
|
||||
control: {
|
||||
type: "boolean",
|
||||
@ -79,5 +74,5 @@ WithAvatar.args = {
|
||||
...defaultProps,
|
||||
variant: "flat",
|
||||
color: "secondary",
|
||||
leftContent: <Avatar name="JW" src="https://i.pravatar.cc/300?u=a042581f4e29026709d" />,
|
||||
avatar: <Avatar name="JW" src="https://i.pravatar.cc/300?u=a042581f4e29026709d" />,
|
||||
};
|
||||
|
||||
@ -40,7 +40,7 @@ const badge = tv({
|
||||
solid: {},
|
||||
flat: {},
|
||||
faded: {
|
||||
badge: "border-2",
|
||||
badge: "border-1.5",
|
||||
},
|
||||
shadow: {},
|
||||
},
|
||||
|
||||
@ -31,12 +31,12 @@ const button = tv({
|
||||
variants: {
|
||||
variant: {
|
||||
solid: "",
|
||||
bordered: "border-2 !bg-transparent",
|
||||
bordered: "border-1.5 !bg-transparent",
|
||||
light: "!bg-transparent",
|
||||
flat: "",
|
||||
faded: "border-2",
|
||||
faded: "border-1.5",
|
||||
shadow: "",
|
||||
ghost: "border-2 !bg-transparent",
|
||||
ghost: "border-1.5 !bg-transparent",
|
||||
},
|
||||
size: {
|
||||
xs: "px-2 h-6 text-xs",
|
||||
|
||||
@ -5,21 +5,24 @@ import {ringClasses, colorVariants} from "../utils";
|
||||
/**
|
||||
* Chip wrapper **Tailwind Variants** component
|
||||
*
|
||||
* const {base, label, dot, closeButton} = chip({...})
|
||||
* const {base, label, dot, avatar, closeButton} = chip({...})
|
||||
*
|
||||
* @example
|
||||
* <div className={base())}>
|
||||
* // left content
|
||||
* <span className={avatar()}/>
|
||||
* <svg className={dot()}/>
|
||||
* <label className={label()}>Default</label>
|
||||
* <svg className={closeButton()}>close button</svg>
|
||||
* // right content
|
||||
* </div>
|
||||
*/
|
||||
const chip = tv({
|
||||
slots: {
|
||||
base: ["relative", "inline-flex", "items-center", "justify-between", "box-border"],
|
||||
label: "flex-1 text-inherit select-none font-regular",
|
||||
dot: ["w-2", "h-2", "mr-2", "rounded-full"],
|
||||
dot: ["w-2", "h-2", "mx-1", "rounded-full"],
|
||||
avatar: "flex-shrink-0",
|
||||
closeButton: [
|
||||
"z-10",
|
||||
"apparance-none",
|
||||
@ -35,36 +38,38 @@ const chip = tv({
|
||||
variant: {
|
||||
solid: {},
|
||||
bordered: {
|
||||
base: "border-2 !bg-transparent",
|
||||
base: "border-1.5 !bg-transparent",
|
||||
},
|
||||
light: {
|
||||
base: "!bg-transparent",
|
||||
},
|
||||
flat: {},
|
||||
faded: {
|
||||
base: "border-2",
|
||||
base: "border-1.5",
|
||||
},
|
||||
shadow: {},
|
||||
dot: {},
|
||||
dot: {
|
||||
base: "border-1.5 border-neutral text-foreground !bg-transparent",
|
||||
},
|
||||
},
|
||||
color: {
|
||||
neutral: {
|
||||
base: colorVariants.solid.neutral,
|
||||
dot: "bg-neutral-400",
|
||||
},
|
||||
primary: {
|
||||
base: colorVariants.solid.primary,
|
||||
dot: "bg-primary",
|
||||
},
|
||||
secondary: {
|
||||
base: colorVariants.solid.secondary,
|
||||
dot: "bg-secondary",
|
||||
},
|
||||
success: {
|
||||
base: colorVariants.solid.success,
|
||||
dot: "bg-success",
|
||||
},
|
||||
warning: {
|
||||
base: colorVariants.solid.warning,
|
||||
dot: "bg-warning",
|
||||
},
|
||||
danger: {
|
||||
base: colorVariants.solid.danger,
|
||||
dot: "bg-danger",
|
||||
},
|
||||
},
|
||||
size: {
|
||||
@ -72,26 +77,31 @@ const chip = tv({
|
||||
base: "px-0.5 h-5 text-xs",
|
||||
label: "px-0.5",
|
||||
closeButton: "text-sm",
|
||||
avatar: "w-3.5 h-3.5",
|
||||
},
|
||||
sm: {
|
||||
base: "px-1 h-6 text-sm",
|
||||
label: "px-1",
|
||||
closeButton: "text-base",
|
||||
avatar: "w-4 h-4",
|
||||
},
|
||||
md: {
|
||||
base: "px-1 h-7 text-base",
|
||||
label: "px-1",
|
||||
closeButton: "text-lg",
|
||||
avatar: "w-5 h-5",
|
||||
},
|
||||
lg: {
|
||||
base: "px-1 h-8 text-lg",
|
||||
base: "px-2 h-8 text-lg",
|
||||
label: "px-1",
|
||||
closeButton: "text-xl",
|
||||
avatar: "w-6 h-6",
|
||||
},
|
||||
xl: {
|
||||
base: "px-1 h-9 text-xl",
|
||||
base: "px-2 h-9 text-xl",
|
||||
label: "px-1",
|
||||
closeButton: "text-2xl",
|
||||
avatar: "w-7 h-7",
|
||||
},
|
||||
},
|
||||
radius: {
|
||||
@ -114,9 +124,6 @@ const chip = tv({
|
||||
isDisabled: {
|
||||
true: {base: "opacity-50 pointer-events-none"},
|
||||
},
|
||||
fullWidth: {
|
||||
true: {base: "w-full"},
|
||||
},
|
||||
isCloseButtonFocusVisible: {
|
||||
true: {
|
||||
closeButton: [...ringClasses, "ring-1", "rounded-full"],
|
||||
@ -128,10 +135,52 @@ const chip = tv({
|
||||
color: "neutral",
|
||||
size: "md",
|
||||
radius: "full",
|
||||
fullWidth: false,
|
||||
isDisabled: false,
|
||||
},
|
||||
compoundVariants: [
|
||||
// solid / color
|
||||
{
|
||||
variant: "solid",
|
||||
color: "neutral",
|
||||
class: {
|
||||
base: colorVariants.solid.neutral,
|
||||
},
|
||||
},
|
||||
{
|
||||
variant: "solid",
|
||||
color: "primary",
|
||||
class: {
|
||||
base: colorVariants.solid.primary,
|
||||
},
|
||||
},
|
||||
{
|
||||
variant: "solid",
|
||||
color: "secondary",
|
||||
class: {
|
||||
base: colorVariants.solid.secondary,
|
||||
},
|
||||
},
|
||||
{
|
||||
variant: "solid",
|
||||
color: "success",
|
||||
class: {
|
||||
base: colorVariants.solid.success,
|
||||
},
|
||||
},
|
||||
{
|
||||
variant: "solid",
|
||||
color: "warning",
|
||||
class: {
|
||||
base: colorVariants.solid.warning,
|
||||
},
|
||||
},
|
||||
{
|
||||
variant: "solid",
|
||||
color: "danger",
|
||||
class: {
|
||||
base: colorVariants.solid.danger,
|
||||
},
|
||||
},
|
||||
// shadow / color
|
||||
{
|
||||
variant: "shadow",
|
||||
|
||||
@ -29,7 +29,7 @@ const snippet = tv({
|
||||
variant: {
|
||||
flat: "",
|
||||
solid: "",
|
||||
bordered: "border-2 !bg-transparent",
|
||||
bordered: "border-1.5 !bg-transparent",
|
||||
shadow: "",
|
||||
},
|
||||
color: {
|
||||
|
||||
@ -27,9 +27,9 @@ const tooltip = tv({
|
||||
variants: {
|
||||
variant: {
|
||||
solid: "",
|
||||
bordered: "border-2 !bg-transparent",
|
||||
bordered: "border-1.5 !bg-transparent",
|
||||
light: "!bg-transparent",
|
||||
faded: "border-2",
|
||||
faded: "border-1.5",
|
||||
flat: "",
|
||||
shadow: "",
|
||||
},
|
||||
@ -253,7 +253,7 @@ const tooltip = tv({
|
||||
{
|
||||
size: "xs",
|
||||
variant: "bordered",
|
||||
class: "border-2",
|
||||
class: "border-1",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user