diff --git a/src/components/ui/AGENTS.md b/src/components/ui/AGENTS.md new file mode 100644 index 000000000..53b9979b7 --- /dev/null +++ b/src/components/ui/AGENTS.md @@ -0,0 +1,19 @@ +# UI Component Guidelines + +## Adding New Components + +```bash +pnpm dlx shadcn-vue@latest add --yes +``` + +After adding, create `ComponentName.stories.ts` with Default, Disabled, and variant stories. + +## Reka UI Wrapper Components + +- Use reactive props destructuring with rest: `const { class: className, ...restProps } = defineProps()` +- Use `useForwardProps(restProps)` for prop forwarding, or `computed()` if adding defaults +- Import siblings directly (`./Component.vue`), not from barrel (`'.'`) +- Use `cn()` for class merging with `className` +- Use Iconify icons: `` +- Use design tokens: `bg-secondary-background`, `text-muted-foreground`, `border-border-default` +- Tailwind 4 CSS variables use parentheses: `h-(--my-var)` not `h-[--my-var]` diff --git a/src/components/ui/select/Select.stories.ts b/src/components/ui/select/Select.stories.ts new file mode 100644 index 000000000..ba2a37e48 --- /dev/null +++ b/src/components/ui/select/Select.stories.ts @@ -0,0 +1,261 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' +import { ref } from 'vue' + +import Select from './Select.vue' +import SelectContent from './SelectContent.vue' +import SelectGroup from './SelectGroup.vue' +import SelectItem from './SelectItem.vue' +import SelectLabel from './SelectLabel.vue' +import SelectSeparator from './SelectSeparator.vue' +import SelectTrigger from './SelectTrigger.vue' +import SelectValue from './SelectValue.vue' + +const meta = { + title: 'Components/Select', + component: Select, + tags: ['autodocs'], + argTypes: { + modelValue: { + control: 'text', + description: 'Selected value' + }, + disabled: { + control: 'boolean', + description: 'When true, disables the select' + }, + 'onUpdate:modelValue': { action: 'update:modelValue' } + } +} satisfies Meta + +export default meta +type Story = StoryObj + +export const Default: Story = { + render: (args) => ({ + components: { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue + }, + setup() { + const value = ref(args.modelValue || '') + return { value, args } + }, + template: ` + +
+ Selected: {{ value || 'None' }} +
+ ` + }), + args: { + disabled: false + } +} + +export const WithPlaceholder: Story = { + render: (args) => ({ + components: { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue + }, + setup() { + const value = ref('') + return { value, args } + }, + template: ` + + ` + }), + args: { + disabled: false + } +} + +export const Disabled: Story = { + render: (args) => ({ + components: { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue + }, + setup() { + const value = ref('apple') + return { value, args } + }, + template: ` + + ` + }) +} + +export const WithGroups: Story = { + render: (args) => ({ + components: { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectSeparator, + SelectTrigger, + SelectValue + }, + setup() { + const value = ref('') + return { value, args } + }, + template: ` + +
+ Selected: {{ value || 'None' }} +
+ ` + }), + args: { + disabled: false + } +} + +export const Scrollable: Story = { + render: (args) => ({ + components: { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue + }, + setup() { + const value = ref('') + const items = Array.from({ length: 20 }, (_, i) => ({ + value: `item-${i + 1}`, + label: `Option ${i + 1}` + })) + return { value, items, args } + }, + template: ` + + ` + }), + args: { + disabled: false + } +} + +export const CustomWidth: Story = { + render: (args) => ({ + components: { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue + }, + setup() { + const value = ref('') + return { value, args } + }, + template: ` +
+ + + +
+ ` + }), + args: { + disabled: false + } +} diff --git a/src/components/ui/select/Select.vue b/src/components/ui/select/Select.vue new file mode 100644 index 000000000..f685b3189 --- /dev/null +++ b/src/components/ui/select/Select.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/components/ui/select/SelectContent.vue b/src/components/ui/select/SelectContent.vue new file mode 100644 index 000000000..a88e26b9f --- /dev/null +++ b/src/components/ui/select/SelectContent.vue @@ -0,0 +1,73 @@ + + + diff --git a/src/components/ui/select/SelectGroup.vue b/src/components/ui/select/SelectGroup.vue new file mode 100644 index 000000000..11f3da9f6 --- /dev/null +++ b/src/components/ui/select/SelectGroup.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/ui/select/SelectItem.vue b/src/components/ui/select/SelectItem.vue new file mode 100644 index 000000000..4edeeb3ca --- /dev/null +++ b/src/components/ui/select/SelectItem.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/components/ui/select/SelectLabel.vue b/src/components/ui/select/SelectLabel.vue new file mode 100644 index 000000000..bafe45da9 --- /dev/null +++ b/src/components/ui/select/SelectLabel.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/components/ui/select/SelectScrollDownButton.vue b/src/components/ui/select/SelectScrollDownButton.vue new file mode 100644 index 000000000..1b1dc1a27 --- /dev/null +++ b/src/components/ui/select/SelectScrollDownButton.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/components/ui/select/SelectScrollUpButton.vue b/src/components/ui/select/SelectScrollUpButton.vue new file mode 100644 index 000000000..ee1ef9263 --- /dev/null +++ b/src/components/ui/select/SelectScrollUpButton.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/components/ui/select/SelectSeparator.vue b/src/components/ui/select/SelectSeparator.vue new file mode 100644 index 000000000..37947fd0d --- /dev/null +++ b/src/components/ui/select/SelectSeparator.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/components/ui/select/SelectTrigger.vue b/src/components/ui/select/SelectTrigger.vue new file mode 100644 index 000000000..768048ab1 --- /dev/null +++ b/src/components/ui/select/SelectTrigger.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/components/ui/select/SelectValue.vue b/src/components/ui/select/SelectValue.vue new file mode 100644 index 000000000..4ffa580ca --- /dev/null +++ b/src/components/ui/select/SelectValue.vue @@ -0,0 +1,12 @@ + + +