diff --git a/src/assets/build/plus.icon.tsx b/src/assets/build/plus.icon.tsx new file mode 100644 index 00000000..a62e6db8 --- /dev/null +++ b/src/assets/build/plus.icon.tsx @@ -0,0 +1,15 @@ +export const Plus = (props: any) => ( + + + +) diff --git a/src/assets/index.ts b/src/assets/index.ts index 519bc727..b3e64d81 100644 --- a/src/assets/index.ts +++ b/src/assets/index.ts @@ -4,3 +4,4 @@ export * from './build/radio-selected.icon' export * from './build/user.icon' export * from './build/clear.icon' export * from './build/search.icon' +export * from './build/plus.icon' diff --git a/src/components/Chip/index.tsx b/src/components/Chip/index.tsx new file mode 100644 index 00000000..eb72d12b --- /dev/null +++ b/src/components/Chip/index.tsx @@ -0,0 +1,97 @@ +import React from 'react' +import { cva, VariantProps } from 'class-variance-authority' +import { cn } from '@/lib/utils' +import { Plus } from '@/assets' + +const chipVariants = cva( + [ + [ + 'inline-flex', + 'rounded-full', + 'shrink-0', + 'items-center', + 'justify-center', + 'border border-2', + 'font-semibold', + 'leading-normal', + 'text-foreground', + 'focus-visible:outline-none', + 'focus-visible:shadow-blue' + ], + [ + 'disabled:border-none', + 'disabled:text-foreground-subtle', + 'disabled:bg-background-subtle', + 'dark:disabled:bg-background-subtle-dark', + 'dark:disabled:text-foreground-subtle-dark' + ], + [ + 'data-[active]:bg-foreground', + 'data-[active]:border-none', + 'data-[active]:text-foreground-inverse', + 'dark:data-[active]:bg-foreground-dark', + 'dark:data-[active]:text-foreground-inverse-dark' + ] + ], + { + variants: { + variant: { + default: [ + 'bg-background', + 'border-border-subtle', + 'dark:bg-background-dark', + 'dark:border-border-subtle-dark', + 'dark:text-foreground-dark' + ], + warning: ['bg-yellow-50', 'border-feedback-yellow'], + success: ['bg-green-50', 'border-feedback-green'], + error: ['bg-red-50', 'border-feedback-red'], + info: ['bg-blue-50', 'border-primary-600', 'dark:border-primary-600'] + }, + size: { + default: ['text-xs', 'px-2.5', 'py-2 h-[26px]', 'gap-1'], + lg: ['text-sm', 'pl-4', 'pr-3', 'py-1.5', 'h-[33px]', 'gap-1.5'] + } + }, + defaultVariants: { + variant: 'default', + size: 'default' + } + } +) + +interface ChipProps + extends React.ComponentPropsWithRef<'button'>, + VariantProps { + active?: boolean +} + +const Chip = React.forwardRef( + ( + { className, variant, size, children, disabled, onClick, active, ...props }, + ref + ) => { + return ( + + ) + } +) + +export { Chip, ChipProps } diff --git a/src/index.ts b/src/index.ts index 3c078fa7..fe04bc93 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,3 +8,4 @@ export * from './components/ButtonGroup' export * from './components/Tooltip' export * from './components/Input' export * from './components/Switch' +export * from './components/Chip' diff --git a/stories/Chip/Chip.stories.ts b/stories/Chip/Chip.stories.ts new file mode 100644 index 00000000..b1aace2f --- /dev/null +++ b/stories/Chip/Chip.stories.ts @@ -0,0 +1,81 @@ +import type { Meta, StoryObj } from '@storybook/react' + +import { Chip } from '@/index' + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +const meta = { + title: 'Components/Chip', + component: Chip, + parameters: { + // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout + layout: 'centered' + }, + argTypes: { + size: { + options: ['default', 'lg'] + } + } + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs + // More on argTypes: https://storybook.js.org/docs/react/api/argtypes +} satisfies Meta + +export default meta +type Story = StoryObj + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args +export const Default: Story = { + args: { + children: 'Hello, this is a chip' + } +} + +export const Warning: Story = { + args: { + variant: 'warning', + children: 'Hello, this is a chip' + } +} +export const Error: Story = { + args: { + variant: 'error', + children: 'Hello, this is a chip' + } +} +export const Info: Story = { + args: { + variant: 'info', + children: 'Hello, this is a chip' + } +} +export const Success: Story = { + args: { + variant: 'success', + children: 'Hello, this is a chip' + } +} +export const Active: Story = { + args: { + active: true, + children: 'Hello, this is a chip' + } +} +export const Disabled: Story = { + args: { + disabled: true, + children: 'Hello, this is a chip' + } +} + +export const LargeDefault: Story = { + args: { + size: 'lg', + children: 'Hello, this is a chip' + } +} +export const LargeActive: Story = { + args: { + active: true, + size: 'lg', + children: 'Hello, this is a chip' + } +} diff --git a/stories/Chip/Docs.mdx b/stories/Chip/Docs.mdx new file mode 100644 index 00000000..f667ae92 --- /dev/null +++ b/stories/Chip/Docs.mdx @@ -0,0 +1,205 @@ +import { Canvas, Meta } from '@storybook/blocks' + +import * as ChipStories from './Chip.stories' + + + +# Chip + +A chip is a compact, often rectangular element that displays a piece of information, such as a label or a small icon. It's commonly used to represent a discrete piece of data or a selectable item, making it a convenient way to present and interact with individual pieces of content or actions in a user interface. + +### Default + + +### Warning + +### Error + +### Active + +### Info + +### Success + +### Disabled + + +All the default sized chips above can be enlarged as shown below: + +### Large Default + + +### Large Active + + +## Attributes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeTypeDefault
variant`"default" | "warning" | "success" | "error" | "info"``"sm"`
size`"default" | "lg"``"default"`
active`boolean`-
children`React.ReactNode`-
disabledboolean`false`
onClickfunction-
disabledboolean`false`
+ +## Data Attributes + + + + + + + + + + + + + + + +
AttributeTypeDefault
[data-active]`boolean`-
+ +## Chip + +```tsx +import React from 'react' +import { cva, VariantProps } from 'class-variance-authority' +import { cn } from '@/lib/utils' +import { Plus } from '@/assets' + +const chipVariants = cva( + [ + [ + 'inline-flex', + 'rounded-full', + 'shrink-0', + 'items-center', + 'justify-center', + 'border border-[2px]', + 'font-semibold', + 'leading-normal', + 'text-foreground' + ], + [ + 'disabled:border-none', + 'disabled:text-foreground-subtle', + 'disabled:bg-background-subtle', + 'dark:disabled:bg-background-subtle-dark', + 'dark:disabled:text-foreground-subtle-dark' + ], + [ + 'data-[active]:bg-foreground', + 'data-[active]:border-none', + 'data-[active]:text-foreground-inverse', + 'dark:data-[active]:bg-foreground-dark', + 'dark:data-[active]:text-foreground-inverse-dark' + ] + ], + { + variants: { + variant: { + default: [ + 'bg-background', + 'border-border-subtle', + 'dark:bg-background-dark', + 'dark:border-border-subtle-dark', + 'dark:text-foreground-dark' + ], + warning: ['bg-yellow-50', 'border-feedback-yellow'], + success: ['bg-green-50', 'border-feedback-green'], + error: ['bg-red-50', 'border-feedback-red'], + info: ['bg-blue-50', 'border-primary-600', 'dark:border-primary-600'] + }, + size: { + default: ['text-xs', 'px-[10px]', 'py-[8px] h-[26px]', 'gap-[4px]'], + lg: [ + 'text-sm', + 'pl-[16px]', + 'pr-[12px]', + 'py-[6px]', + 'h-[33px]', + 'gap-[6px]' + ] + } + }, + defaultVariants: { + variant: 'default', + size: 'default' + } + } +) + +interface ChipProps + extends React.ComponentPropsWithRef<'button'>, + VariantProps { + active?: boolean +} + +const Chip = React.forwardRef( + ( + { className, variant, size, children, disabled, onClick, active, ...props }, + ref + ) => { + return ( + + ) + } +) + +export { Chip, ChipProps } +```