diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts index 70f88e5a..fd300ed5 100644 --- a/packages/ui/src/components/index.ts +++ b/packages/ui/src/components/index.ts @@ -38,6 +38,7 @@ export * from './skeleton'; export * from './slider'; export * from './switch'; export * from './tabs'; +export * from './tags-input'; export * from './textarea'; export * from './toast'; export * from './toggle'; diff --git a/packages/ui/src/components/tags-input/index.ts b/packages/ui/src/components/tags-input/index.ts new file mode 100644 index 00000000..78bbed90 --- /dev/null +++ b/packages/ui/src/components/tags-input/index.ts @@ -0,0 +1,8 @@ +import STagsInputRoot from './tags-input-root.vue'; +import STagsInputInput from './tags-input-input.vue'; +import STagsInputItem from './tags-input-item.vue'; +import STagsInputItemText from './tags-input-item-text.vue'; +import STagsInputItemDelete from './tags-input-item-delete.vue'; +import STagsInput from './tags-input.vue'; + +export { STagsInputRoot, STagsInputInput, STagsInputItem, STagsInputItemText, STagsInputItemDelete, STagsInput }; diff --git a/packages/ui/src/components/tags-input/tags-input-input.vue b/packages/ui/src/components/tags-input/tags-input-input.vue new file mode 100644 index 00000000..29c4b7bd --- /dev/null +++ b/packages/ui/src/components/tags-input/tags-input-input.vue @@ -0,0 +1,24 @@ + + + diff --git a/packages/ui/src/components/tags-input/tags-input-item-delete.vue b/packages/ui/src/components/tags-input/tags-input-item-delete.vue new file mode 100644 index 00000000..bd3f1ed1 --- /dev/null +++ b/packages/ui/src/components/tags-input/tags-input-item-delete.vue @@ -0,0 +1,32 @@ + + + diff --git a/packages/ui/src/components/tags-input/tags-input-item-text.vue b/packages/ui/src/components/tags-input/tags-input-item-text.vue new file mode 100644 index 00000000..d0a70789 --- /dev/null +++ b/packages/ui/src/components/tags-input/tags-input-item-text.vue @@ -0,0 +1,24 @@ + + + diff --git a/packages/ui/src/components/tags-input/tags-input-item.vue b/packages/ui/src/components/tags-input/tags-input-item.vue new file mode 100644 index 00000000..238a1c32 --- /dev/null +++ b/packages/ui/src/components/tags-input/tags-input-item.vue @@ -0,0 +1,24 @@ + + + diff --git a/packages/ui/src/components/tags-input/tags-input-root.vue b/packages/ui/src/components/tags-input/tags-input-root.vue new file mode 100644 index 00000000..dd368dbe --- /dev/null +++ b/packages/ui/src/components/tags-input/tags-input-root.vue @@ -0,0 +1,29 @@ + + + diff --git a/packages/ui/src/components/tags-input/tags-input.vue b/packages/ui/src/components/tags-input/tags-input.vue new file mode 100644 index 00000000..bef6bc3a --- /dev/null +++ b/packages/ui/src/components/tags-input/tags-input.vue @@ -0,0 +1,55 @@ + + + diff --git a/packages/ui/src/components/tags-input/types.ts b/packages/ui/src/components/tags-input/types.ts new file mode 100644 index 00000000..53f97fbf --- /dev/null +++ b/packages/ui/src/components/tags-input/types.ts @@ -0,0 +1,43 @@ +import type { + AcceptableInputValue, + ClassValue, + TagsInputRootEmits, + TagsInputInputProps as _TagsInputInputProps, + TagsInputItemDeleteProps as _TagsInputItemDeleteProps, + TagsInputItemProps as _TagsInputItemProps, + TagsInputItemTextProps as _TagsInputItemTextProps, + TagsInputRootProps as _TagsInputRootProps +} from '@soybean-ui/primitives'; +import type { TagsInputSlots, ThemeSize } from '@soybean-ui/variants'; + +export interface TagsInputRootProps extends _TagsInputRootProps { + size?: ThemeSize; +} + +export interface TagsInputInputProps extends _TagsInputInputProps { + size?: ThemeSize; +} + +export interface TagsInputItemProps extends _TagsInputItemProps { + size?: ThemeSize; +} + +export interface TagsInputItemTextProps extends _TagsInputItemTextProps { + size?: ThemeSize; +} + +export interface TagsInputItemDeleteProps extends _TagsInputItemDeleteProps { + size?: ThemeSize; + iconClass?: ClassValue; +} + +export type TagsInputUi = Partial>; + +export interface TagsInputProps extends TagsInputRootProps, TagsInputInputProps { + disabledValue?: T[]; + ui?: TagsInputUi; +} + +export type TagsInputEmits = TagsInputRootEmits; + +export type { TagsInputRootEmits }; diff --git a/packages/variants/src/index.ts b/packages/variants/src/index.ts index 680fc268..30952a98 100644 --- a/packages/variants/src/index.ts +++ b/packages/variants/src/index.ts @@ -36,6 +36,7 @@ export * from './variants/skeleton'; export * from './variants/slider'; export * from './variants/switch'; export * from './variants/tabs'; +export * from './variants/tags-input'; export * from './variants/textarea'; export * from './variants/toast'; export * from './variants/toggle'; diff --git a/packages/variants/src/variants/tags-input.ts b/packages/variants/src/variants/tags-input.ts new file mode 100644 index 00000000..af4b6977 --- /dev/null +++ b/packages/variants/src/variants/tags-input.ts @@ -0,0 +1,73 @@ +// @unocss-include +import { tv } from 'tailwind-variants'; + +export const tagsInputVariants = tv({ + slots: { + root: [ + `flex flex-wrap gap-2 items-center rounded-md border border-input bg-background`, + `focus-within:(ring-2 ring-offset-2 ring-primary) disabled:(cursor-not-allowed opacity-50)` + ], + input: `focus:outline-none flex-1 bg-transparent`, + item: `flex items-center rounded-md bg-accent data-[state=active]:(ring-2 ring-offset-2 ring-accent-foreground/20) ring-offset-background`, + itemText: `rounded bg-transparent`, + itemDelete: `flex rounded bg-transparent mr-1 text-foreground hover:text-foreground/80`, + itemDeleteIcon: `cursor-pointer` + }, + variants: { + size: { + xs: { + root: 'px-1.5 py-0.75 text-xs', + input: 'min-h-4 px-1.5 text-xs', + item: 'h-4', + itemText: 'py-0.75 px-1.5 text-xs', + itemDelete: 'mr-1.5', + itemDeleteIcon: 'size-3' + }, + sm: { + root: 'px-2 py-0.75 text-sm', + input: 'min-h-5 px-2 text-sm', + item: 'h-5', + itemText: 'py-0.75 px-2 text-sm', + itemDelete: 'mr-2', + itemDeleteIcon: 'size-3.5' + }, + md: { + root: 'px-2.5 py-1 text-sm', + input: 'min-h-5.5 px-2.5 text-sm', + item: 'h-5.5', + itemText: 'py-1 px-2.5 text-sm', + itemDelete: 'mr-2.5', + itemDeleteIcon: 'size-4' + }, + lg: { + root: 'px-3 py-1.25 text-base', + input: 'min-h-6 px-3 text-base', + item: 'h-6', + itemText: 'py-1.25 px-3 text-base', + itemDelete: 'mr-3', + itemDeleteIcon: 'size-4.5' + }, + xl: { + root: 'px-3.5 py-1.5 text-base', + input: 'min-h-6.5 px-3.5 text-base', + item: 'h-6.5', + itemText: 'py-1.5 px-3.5 text-base', + itemDelete: 'mr-3.5', + itemDeleteIcon: 'size-5' + }, + xxl: { + root: 'px-4 py-1.75 text-lg', + input: 'min-h-8 px-4 text-lg', + item: 'h-8', + itemText: 'py-1.75 px-4 text-lg', + itemDelete: 'mr-4', + itemDeleteIcon: 'size-5.5' + } + } + }, + defaultVariants: { + size: 'md' + } +}); + +export type TagsInputSlots = keyof typeof tagsInputVariants.slots; diff --git a/src/views/ui/index.vue b/src/views/ui/index.vue index ba715e39..3fad048d 100644 --- a/src/views/ui/index.vue +++ b/src/views/ui/index.vue @@ -45,6 +45,7 @@ import UiSlider from './modules/slider.vue'; import UiSonner from './modules/sonner.vue'; import UiSwitch from './modules/switch.vue'; import UiTabs from './modules/tabs.vue'; +import UiTagsInput from './modules/tags-input.vue'; import UiTextarea from './modules/textarea.vue'; import UiToast from './modules/toast.vue'; import UiToggle from './modules/toggle.vue'; @@ -268,6 +269,11 @@ const tabs: TabConfig[] = [ label: 'Tabs', component: UiTabs }, + { + value: 'tags-input', + label: 'TagsInput', + component: UiTagsInput + }, { value: 'textarea', label: 'Textarea', diff --git a/src/views/ui/modules/tags-input.vue b/src/views/ui/modules/tags-input.vue new file mode 100644 index 00000000..7889e7b6 --- /dev/null +++ b/src/views/ui/modules/tags-input.vue @@ -0,0 +1,25 @@ + + + + +