@polymarbot/nuxt-layer-shadcn-ui 0.1.9 → 0.2.0-w

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/app/assets/styles/colors.css +10 -10
  2. package/app/assets/styles/globals.css +1 -0
  3. package/app/assets/styles/z-index.css +27 -0
  4. package/app/components/ui/Accordion/index.stories.ts +60 -56
  5. package/app/components/ui/Accordion/index.vue +1 -1
  6. package/app/components/ui/AdminLayout/SidebarMenus.vue +0 -2
  7. package/app/components/ui/AdminLayout/index.stories.ts +9 -8
  8. package/app/components/ui/Alert/index.stories.ts +28 -26
  9. package/app/components/ui/Alert/index.vue +6 -6
  10. package/app/components/ui/Alert/types.ts +2 -1
  11. package/app/components/ui/AlertDialog/index.stories.ts +85 -50
  12. package/app/components/ui/AsyncDataTable/index.stories.ts +53 -36
  13. package/app/components/ui/Avatar/index.stories.ts +56 -51
  14. package/app/components/ui/Avatar/index.vue +1 -1
  15. package/app/components/ui/Avatar/types.ts +5 -2
  16. package/app/components/ui/Badge/index.stories.ts +41 -41
  17. package/app/components/ui/Badge/index.vue +1 -1
  18. package/app/components/ui/Badge/types.ts +3 -1
  19. package/app/components/ui/Breadcrumb/index.stories.ts +48 -37
  20. package/app/components/ui/Breadcrumb/index.vue +1 -1
  21. package/app/components/ui/Button/index.stories.ts +94 -90
  22. package/app/components/ui/Button/index.vue +1 -1
  23. package/app/components/ui/Button/types.ts +4 -1
  24. package/app/components/ui/ButtonGroup/index.stories.ts +61 -49
  25. package/app/components/ui/Card/index.stories.ts +55 -47
  26. package/app/components/ui/Card/index.vue +1 -1
  27. package/app/components/ui/Checkbox/index.stories.ts +69 -46
  28. package/app/components/ui/Checkbox/index.vue +1 -1
  29. package/app/components/ui/CopyButton/index.stories.ts +89 -31
  30. package/app/components/ui/DataTable/index.stories.ts +218 -168
  31. package/app/components/ui/DataTable/index.vue +1 -1
  32. package/app/components/ui/DatePicker/index.stories.ts +131 -37
  33. package/app/components/ui/DateRangePicker/index.stories.ts +107 -33
  34. package/app/components/ui/Divider/index.stories.ts +46 -24
  35. package/app/components/ui/Divider/index.vue +1 -1
  36. package/app/components/ui/Drawer/index.stories.ts +131 -81
  37. package/app/components/ui/Drawer/index.vue +1 -7
  38. package/app/components/ui/Drawer/types.ts +1 -1
  39. package/app/components/ui/Dropdown/index.stories.ts +134 -89
  40. package/app/components/ui/Dropdown/index.vue +5 -1
  41. package/app/components/ui/Dropdown/types.ts +1 -1
  42. package/app/components/ui/FormItem/index.stories.ts +87 -43
  43. package/app/components/ui/FormItem/index.vue +1 -1
  44. package/app/components/ui/Help/index.stories.ts +46 -35
  45. package/app/components/ui/Icon/index.stories.ts +41 -43
  46. package/app/components/ui/Input/index.stories.ts +95 -41
  47. package/app/components/ui/Input/index.vue +1 -1
  48. package/app/components/ui/InputCurrency/index.stories.ts +89 -49
  49. package/app/components/ui/InputNumber/index.stories.ts +93 -29
  50. package/app/components/ui/InputNumber/index.vue +1 -1
  51. package/app/components/ui/InputOtp/index.stories.ts +6 -7
  52. package/app/components/ui/InputOtp/index.vue +1 -1
  53. package/app/components/ui/InputPercent/index.stories.ts +6 -7
  54. package/app/components/ui/InputRange/index.stories.ts +6 -7
  55. package/app/components/ui/Loading/index.stories.ts +19 -19
  56. package/app/components/ui/Markdown/index.stories.ts +7 -10
  57. package/app/components/ui/Modal/index.stories.ts +135 -80
  58. package/app/components/ui/Modal/index.vue +1 -6
  59. package/app/components/ui/Modal/types.ts +1 -1
  60. package/app/components/ui/ModalContent/index.stories.ts +54 -26
  61. package/app/components/ui/ModalContent/index.vue +2 -2
  62. package/app/components/ui/PageCard/index.stories.ts +177 -67
  63. package/app/components/ui/Pagination/index.stories.ts +68 -51
  64. package/app/components/ui/Pagination/index.vue +2 -2
  65. package/app/components/ui/Popover/index.stories.ts +47 -45
  66. package/app/components/ui/Popover/index.vue +1 -1
  67. package/app/components/ui/Qrcode/index.stories.ts +42 -34
  68. package/app/components/ui/RadioCardGroup/index.stories.ts +23 -32
  69. package/app/components/ui/RadioCardGroup/index.vue +1 -1
  70. package/app/components/ui/RadioGroup/index.stories.ts +123 -0
  71. package/app/components/ui/RadioGroup/index.vue +73 -0
  72. package/app/components/ui/RadioGroup/types.ts +13 -0
  73. package/app/components/ui/ScrollArea/index.stories.ts +69 -37
  74. package/app/components/ui/ScrollArea/index.vue +1 -1
  75. package/app/components/ui/SearchSelect/index.stories.ts +104 -66
  76. package/app/components/ui/Select/index.stories.ts +152 -98
  77. package/app/components/ui/Select/index.vue +3 -3
  78. package/app/components/ui/Skeleton/index.stories.ts +27 -30
  79. package/app/components/ui/Skeleton/index.vue +1 -1
  80. package/app/components/ui/Slider/index.stories.ts +73 -31
  81. package/app/components/ui/Slider/index.vue +1 -1
  82. package/app/components/ui/Surface/index.stories.ts +47 -21
  83. package/app/components/ui/Surface/index.vue +39 -28
  84. package/app/components/ui/Surface/types.ts +2 -2
  85. package/app/components/ui/Switch/index.stories.ts +6 -7
  86. package/app/components/ui/Switch/index.vue +1 -1
  87. package/app/components/ui/Tabs/index.stories.ts +103 -61
  88. package/app/components/ui/Tabs/index.vue +1 -1
  89. package/app/components/ui/Tag/index.stories.ts +42 -25
  90. package/app/components/ui/Tag/index.vue +39 -28
  91. package/app/components/ui/Tag/types.ts +2 -2
  92. package/app/components/ui/Textarea/index.stories.ts +73 -9
  93. package/app/components/ui/Textarea/index.vue +1 -1
  94. package/app/components/ui/Toast/index.stories.ts +71 -18
  95. package/app/components/ui/Toast/index.vue +1 -1
  96. package/app/components/ui/Tooltip/index.stories.ts +45 -38
  97. package/app/components/ui/Tooltip/index.vue +1 -1
  98. package/app/components/ui/WebLink/index.stories.ts +76 -41
  99. package/app/components/ui/WebLink/index.vue +1 -1
  100. package/package.json +2 -2
  101. package/app/components/ui/Radio/index.stories.ts +0 -71
  102. package/app/components/ui/Radio/index.vue +0 -10
  103. package/app/components/ui/Radio/types.ts +0 -3
@@ -12,8 +12,9 @@ const surfaceVariants = cva(
12
12
  bordered: 'border bg-transparent',
13
13
  flat: '',
14
14
  },
15
- type: {
15
+ color: {
16
16
  default: '',
17
+ primary: '',
17
18
  success: '',
18
19
  info: '',
19
20
  help: '',
@@ -23,81 +24,91 @@ const surfaceVariants = cva(
23
24
  },
24
25
  compoundVariants: [
25
26
  // solid — full color background
26
- { variant: 'solid', type: 'default', class: `
27
+ { variant: 'solid', color: 'default', class: `
27
28
  border-transparent bg-accent text-accent-foreground
28
29
  ` },
29
- { variant: 'solid', type: 'success', class: `
30
+ { variant: 'solid', color: 'primary', class: `
31
+ border-primary bg-primary text-primary-foreground
32
+ ` },
33
+ { variant: 'solid', color: 'success', class: `
30
34
  border-success bg-success text-success-foreground
31
35
  ` },
32
- { variant: 'solid', type: 'info', class: `
36
+ { variant: 'solid', color: 'info', class: `
33
37
  border-info bg-info text-info-foreground
34
38
  ` },
35
- { variant: 'solid', type: 'help', class: `
39
+ { variant: 'solid', color: 'help', class: `
36
40
  border-help bg-help text-help-foreground
37
41
  ` },
38
- { variant: 'solid', type: 'warn', class: `
42
+ { variant: 'solid', color: 'warn', class: `
39
43
  border-warn bg-warn text-warn-foreground
40
44
  ` },
41
- { variant: 'solid', type: 'danger', class: `
45
+ { variant: 'solid', color: 'danger', class: `
42
46
  border-danger bg-danger text-danger-foreground
43
47
  ` },
44
48
  // soft — tinted background + soft border
45
- { variant: 'soft', type: 'default', class: `
49
+ { variant: 'soft', color: 'default', class: `
46
50
  border-border bg-secondary text-secondary-foreground
47
51
  ` },
48
- { variant: 'soft', type: 'success', class: `
52
+ { variant: 'soft', color: 'primary', class: `
53
+ border-primary/50 bg-primary/10 text-primary
54
+ ` },
55
+ { variant: 'soft', color: 'success', class: `
49
56
  border-success/50 bg-success/10 text-success
50
57
  ` },
51
- { variant: 'soft', type: 'info', class: `
58
+ { variant: 'soft', color: 'info', class: `
52
59
  border-info/50 bg-info/10 text-info
53
60
  ` },
54
- { variant: 'soft', type: 'help', class: `
61
+ { variant: 'soft', color: 'help', class: `
55
62
  border-help/50 bg-help/10 text-help
56
63
  ` },
57
- { variant: 'soft', type: 'warn', class: `
64
+ { variant: 'soft', color: 'warn', class: `
58
65
  border-warn/50 bg-warn/10 text-warn
59
66
  ` },
60
- { variant: 'soft', type: 'danger', class: `
67
+ { variant: 'soft', color: 'danger', class: `
61
68
  border-danger/50 bg-danger/10 text-danger
62
69
  ` },
63
70
  // bordered — border only
64
- { variant: 'bordered', type: 'default', class: `
71
+ { variant: 'bordered', color: 'default', class: `
65
72
  border-border text-foreground
66
73
  ` },
67
- { variant: 'bordered', type: 'success', class: `
74
+ { variant: 'bordered', color: 'primary', class: `
75
+ border-primary/50 text-primary
76
+ ` },
77
+ { variant: 'bordered', color: 'success', class: `
68
78
  border-success/50 text-success
69
79
  ` },
70
- { variant: 'bordered', type: 'info', class: 'border-info/50 text-info' },
71
- { variant: 'bordered', type: 'help', class: 'border-help/50 text-help' },
72
- { variant: 'bordered', type: 'warn', class: 'border-warn/50 text-warn' },
73
- { variant: 'bordered', type: 'danger', class: `
80
+ { variant: 'bordered', color: 'info', class: 'border-info/50 text-info' },
81
+ { variant: 'bordered', color: 'help', class: 'border-help/50 text-help' },
82
+ { variant: 'bordered', color: 'warn', class: 'border-warn/50 text-warn' },
83
+ { variant: 'bordered', color: 'danger', class: `
74
84
  border-danger/50 text-danger
75
85
  ` },
76
86
  // flat — tinted background only
77
- { variant: 'flat', type: 'default', class: `
87
+ { variant: 'flat', color: 'default', class: `
78
88
  bg-secondary text-secondary-foreground
79
89
  ` },
80
- { variant: 'flat', type: 'success', class: 'bg-success/10 text-success' },
81
- { variant: 'flat', type: 'info', class: 'bg-info/10 text-info' },
82
- { variant: 'flat', type: 'help', class: 'bg-help/10 text-help' },
83
- { variant: 'flat', type: 'warn', class: 'bg-warn/10 text-warn' },
84
- { variant: 'flat', type: 'danger', class: 'bg-danger/10 text-danger' },
90
+ { variant: 'flat', color: 'primary', class: 'bg-primary/10 text-primary' },
91
+ { variant: 'flat', color: 'success', class: 'bg-success/10 text-success' },
92
+ { variant: 'flat', color: 'info', class: 'bg-info/10 text-info' },
93
+ { variant: 'flat', color: 'help', class: 'bg-help/10 text-help' },
94
+ { variant: 'flat', color: 'warn', class: 'bg-warn/10 text-warn' },
95
+ { variant: 'flat', color: 'danger', class: 'bg-danger/10 text-danger' },
85
96
  ],
86
97
  defaultVariants: {
87
98
  variant: 'soft',
88
- type: 'default',
99
+ color: 'default',
89
100
  },
90
101
  },
91
102
  )
92
103
 
93
104
  const props = withDefaults(defineProps<SurfaceProps>(), {
94
- type: 'default',
105
+ color: 'default',
95
106
  variant: 'soft',
96
107
  class: undefined,
97
108
  })
98
109
 
99
110
  const mergedClass = computed(() =>
100
- cn(surfaceVariants({ type: props.type, variant: props.variant }), props.class),
111
+ cn(surfaceVariants({ color: props.color, variant: props.variant }), props.class),
101
112
  )
102
113
  </script>
103
114
 
@@ -1,8 +1,8 @@
1
- export type SurfaceType = 'default' | 'success' | 'info' | 'help' | 'warn' | 'danger'
1
+ export type SurfaceColor = 'default' | 'primary' | 'success' | 'info' | 'help' | 'warn' | 'danger'
2
2
  export type SurfaceVariant = 'solid' | 'soft' | 'bordered' | 'flat'
3
3
 
4
4
  export interface SurfaceProps {
5
- type?: SurfaceType
5
+ color?: SurfaceColor
6
6
  variant?: SurfaceVariant
7
7
  class?: ClassValue
8
8
  }
@@ -10,12 +10,6 @@ const meta = {
10
10
  args: {
11
11
  disabled: false,
12
12
  },
13
- } satisfies Meta<typeof Switch>
14
-
15
- export default meta
16
- type Story = StoryObj<typeof meta>
17
-
18
- export const Default: Story = {
19
13
  render: args => ({
20
14
  components: { Switch },
21
15
  setup () {
@@ -29,4 +23,9 @@ export const Default: Story = {
29
23
  </div>
30
24
  `,
31
25
  }),
32
- }
26
+ } satisfies Meta<typeof Switch>
27
+
28
+ export default meta
29
+ type Story = StoryObj<typeof meta>
30
+
31
+ export const Default: Story = {}
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { Switch as ShadcnSwitch } from '@polymarbot/nuxt-layer-shadcn-ui/app/components/shadcn/switch'
2
+ import { Switch as ShadcnSwitch } from '../../shadcn/switch'
3
3
  import type { SwitchProps } from './types'
4
4
 
5
5
  defineProps<SwitchProps>()
@@ -21,96 +21,138 @@ const items: TabsItem[] = [
21
21
  title: 'Notifications',
22
22
  icon: 'bell',
23
23
  content: 'Control which notifications you receive and how they are delivered.',
24
- disabled: true,
25
24
  },
26
25
  ]
27
26
 
28
27
  const navItems: TabsItem[] = items.map(({ content, ...rest }) => rest)
29
28
 
29
+ const disabledItems: TabsItem[] = items.map((item, index) =>
30
+ index === 2 ? { ...item, disabled: true } : item,
31
+ )
32
+
30
33
  const meta = {
31
34
  title: 'UI/Tabs',
32
35
  component: Tabs,
33
36
  argTypes: {
37
+ items: { control: 'object' },
38
+ modelValue: { control: 'text' },
39
+ defaultValue: { control: 'text' },
34
40
  rounded: { control: 'boolean' },
35
41
  iconOnly: { control: 'boolean' },
36
42
  },
37
43
  args: {
44
+ items,
45
+ modelValue: undefined,
46
+ defaultValue: 'account',
38
47
  rounded: false,
39
48
  iconOnly: false,
40
49
  },
50
+ render: args => ({
51
+ components: { Tabs },
52
+ setup: () => ({ args }),
53
+ template: '<Tabs v-bind="args" class="max-w-md" />',
54
+ }),
41
55
  } satisfies Meta<typeof Tabs>
42
56
 
43
57
  export default meta
44
58
  type Story = StoryObj<typeof meta>
45
59
 
46
- export const Default: Story = {
47
- render: args => ({
48
- components: { Tabs, Card },
60
+ export const Default: Story = {}
61
+
62
+ export const Controlled: Story = {
63
+ render: () => ({
64
+ components: { Tabs },
49
65
  setup () {
50
66
  const value = ref<string>('account')
51
- return { args, items, navItems, value }
67
+ return { items, value }
52
68
  },
53
69
  template: `
54
- <div class="max-w-md space-y-10">
55
- <!-- Controlled -->
56
- <section>
57
- <h3 class="mb-4 text-lg font-medium">Controlled</h3>
58
- <Tabs
59
- v-model="value"
60
- v-bind="args"
61
- :items="items"
62
- />
63
- <div class="mt-3 text-sm text-muted-foreground">Active: {{ value }}</div>
64
- </section>
70
+ <div class="max-w-md space-y-3">
71
+ <Tabs v-model="value" :items="items" />
72
+ <div class="text-sm text-muted-foreground">Active: {{ value }}</div>
73
+ </div>
74
+ `,
75
+ }),
76
+ }
77
+
78
+ export const IconOnly: Story = {
79
+ render: () => ({
80
+ components: { Tabs },
81
+ setup: () => ({ items }),
82
+ template: `
83
+ <Tabs
84
+ icon-only
85
+ :items="items"
86
+ default-value="account"
87
+ class="max-w-md"
88
+ />
89
+ `,
90
+ }),
91
+ }
65
92
 
66
- <!-- Icon Only (title used as aria-label) -->
67
- <section>
68
- <h3 class="mb-4 text-lg font-medium">Icon Only</h3>
69
- <Tabs
70
- icon-only
71
- :items="items"
72
- default-value="account"
73
- />
74
- </section>
93
+ export const Rounded: Story = {
94
+ render: () => ({
95
+ components: { Tabs },
96
+ setup: () => ({ items }),
97
+ template: `
98
+ <Tabs
99
+ rounded
100
+ :items="items"
101
+ default-value="account"
102
+ class="max-w-md"
103
+ />
104
+ `,
105
+ }),
106
+ }
75
107
 
76
- <!-- Rounded -->
77
- <section>
78
- <h3 class="mb-4 text-lg font-medium">Rounded</h3>
79
- <Tabs
80
- rounded
81
- :items="items"
82
- default-value="account"
83
- />
84
- </section>
108
+ export const DisabledItem: Story = {
109
+ render: () => ({
110
+ components: { Tabs },
111
+ setup: () => ({ disabledItems }),
112
+ template: `
113
+ <Tabs
114
+ :items="disabledItems"
115
+ default-value="account"
116
+ class="max-w-md"
117
+ />
118
+ `,
119
+ }),
120
+ }
85
121
 
86
- <!-- No Content (triggers only, no gap below) -->
87
- <section>
88
- <h3 class="mb-4 text-lg font-medium">No Content</h3>
89
- <Tabs
90
- :items="navItems"
91
- default-value="account"
92
- />
93
- </section>
122
+ export const NoContent: Story = {
123
+ render: () => ({
124
+ components: { Tabs },
125
+ setup: () => ({ navItems }),
126
+ template: `
127
+ <Tabs
128
+ :items="navItems"
129
+ default-value="account"
130
+ class="max-w-md"
131
+ />
132
+ `,
133
+ }),
134
+ }
94
135
 
95
- <!-- Custom Slots -->
96
- <section>
97
- <h3 class="mb-4 text-lg font-medium">Custom Slots</h3>
98
- <Tabs
99
- :items="items"
100
- default-value="account"
101
- list-class="w-full"
102
- >
103
- <template #title="{ item, active }">
104
- <span :class="active ? 'font-semibold' : ''">{{ item.title }}</span>
105
- </template>
106
- <template #content="{ item }">
107
- <Card>
108
- <p class="text-sm text-muted-foreground">{{ item.content }}</p>
109
- </Card>
110
- </template>
111
- </Tabs>
112
- </section>
113
- </div>
136
+ export const CustomSlots: Story = {
137
+ render: () => ({
138
+ components: { Tabs, Card },
139
+ setup: () => ({ items }),
140
+ template: `
141
+ <Tabs
142
+ :items="items"
143
+ default-value="account"
144
+ list-class="w-full"
145
+ class="max-w-md"
146
+ >
147
+ <template #title="{ item, active }">
148
+ <span :class="active ? 'font-semibold' : ''">{{ item.title }}</span>
149
+ </template>
150
+ <template #content="{ item }">
151
+ <Card>
152
+ <p class="text-sm text-muted-foreground">{{ item.content }}</p>
153
+ </Card>
154
+ </template>
155
+ </Tabs>
114
156
  `,
115
157
  }),
116
158
  }
@@ -4,7 +4,7 @@ import {
4
4
  TabsContent,
5
5
  TabsList,
6
6
  TabsTrigger,
7
- } from '@polymarbot/nuxt-layer-shadcn-ui/app/components/shadcn/tabs'
7
+ } from '../../shadcn/tabs'
8
8
  import type { TabsItem, TabsProps } from './types'
9
9
 
10
10
  const props = withDefaults(defineProps<TabsProps>(), {
@@ -1,50 +1,67 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import type { TagColor, TagVariant } from './types'
2
3
  import Tag from './index.vue'
3
4
 
4
- type TagType = 'default' | 'success' | 'info' | 'help' | 'warn' | 'danger'
5
- type TagVariant = 'solid' | 'soft' | 'bordered' | 'flat'
6
-
7
- const types: TagType[] = [ 'default', 'success', 'info', 'help', 'warn', 'danger' ]
5
+ const colors: TagColor[] = [ 'default', 'primary', 'success', 'info', 'help', 'warn', 'danger' ]
8
6
  const variants: TagVariant[] = [ 'solid', 'soft', 'bordered', 'flat' ]
9
7
 
10
8
  const meta = {
11
9
  title: 'UI/Tag',
12
10
  component: Tag,
13
11
  argTypes: {
14
- type: { control: 'select', options: types },
12
+ color: { control: 'select', options: colors },
15
13
  variant: { control: 'select', options: variants },
16
14
  },
17
15
  args: {
18
- type: 'default',
16
+ color: 'default',
19
17
  variant: 'soft',
20
18
  },
19
+ render: args => ({
20
+ components: { Tag },
21
+ setup: () => ({ args }),
22
+ template: '<Tag v-bind="args">Tag</Tag>',
23
+ }),
21
24
  } satisfies Meta<typeof Tag>
22
25
 
23
26
  export default meta
24
27
  type Story = StoryObj<typeof meta>
25
28
 
26
- export const Default: Story = {
27
- render: args => ({
29
+ export const Default: Story = {}
30
+
31
+ export const Colors: Story = {
32
+ render: () => ({
28
33
  components: { Tag },
29
- setup: () => ({ args, types, variants }),
34
+ setup: () => ({ colors }),
30
35
  template: `
31
- <div class="space-y-10">
32
- <!-- Controlled -->
33
- <section>
34
- <h3 class="mb-4 text-lg font-medium">Controlled</h3>
35
- <Tag v-bind="args">Tag</Tag>
36
- </section>
36
+ <div class="flex flex-wrap items-center gap-3">
37
+ <Tag v-for="c in colors" :key="c" :color="c">{{ c }}</Tag>
38
+ </div>
39
+ `,
40
+ }),
41
+ }
37
42
 
38
- <!-- Variants × Types matrix -->
39
- <section>
40
- <h3 class="mb-4 text-lg font-medium">Variants × Types</h3>
41
- <div class="space-y-3">
42
- <div v-for="v in variants" :key="v" class="flex flex-wrap items-center gap-3">
43
- <span class="w-20 text-sm text-muted-foreground">{{ v }}</span>
44
- <Tag v-for="t in types" :key="t" :type="t" :variant="v">{{ t }}</Tag>
45
- </div>
46
- </div>
47
- </section>
43
+ export const Variants: Story = {
44
+ render: () => ({
45
+ components: { Tag },
46
+ setup: () => ({ variants }),
47
+ template: `
48
+ <div class="flex flex-wrap items-center gap-3">
49
+ <Tag v-for="v in variants" :key="v" :variant="v">{{ v }}</Tag>
50
+ </div>
51
+ `,
52
+ }),
53
+ }
54
+
55
+ export const VariantColorMatrix: Story = {
56
+ render: () => ({
57
+ components: { Tag },
58
+ setup: () => ({ colors, variants }),
59
+ template: `
60
+ <div class="space-y-3">
61
+ <div v-for="v in variants" :key="v" class="flex flex-wrap items-center gap-3">
62
+ <span class="w-20 text-sm text-muted-foreground">{{ v }}</span>
63
+ <Tag v-for="c in colors" :key="c" :color="c" :variant="v">{{ c }}</Tag>
64
+ </div>
48
65
  </div>
49
66
  `,
50
67
  }),
@@ -12,8 +12,9 @@ const tagVariants = cva(
12
12
  bordered: 'border bg-transparent',
13
13
  flat: '',
14
14
  },
15
- type: {
15
+ color: {
16
16
  default: '',
17
+ primary: '',
17
18
  success: '',
18
19
  info: '',
19
20
  help: '',
@@ -23,81 +24,91 @@ const tagVariants = cva(
23
24
  },
24
25
  compoundVariants: [
25
26
  // solid — full color background
26
- { variant: 'solid', type: 'default', class: `
27
+ { variant: 'solid', color: 'default', class: `
27
28
  border-transparent bg-accent text-accent-foreground
28
29
  ` },
29
- { variant: 'solid', type: 'success', class: `
30
+ { variant: 'solid', color: 'primary', class: `
31
+ border-primary bg-primary text-primary-foreground
32
+ ` },
33
+ { variant: 'solid', color: 'success', class: `
30
34
  border-success bg-success text-success-foreground
31
35
  ` },
32
- { variant: 'solid', type: 'info', class: `
36
+ { variant: 'solid', color: 'info', class: `
33
37
  border-info bg-info text-info-foreground
34
38
  ` },
35
- { variant: 'solid', type: 'help', class: `
39
+ { variant: 'solid', color: 'help', class: `
36
40
  border-help bg-help text-help-foreground
37
41
  ` },
38
- { variant: 'solid', type: 'warn', class: `
42
+ { variant: 'solid', color: 'warn', class: `
39
43
  border-warn bg-warn text-warn-foreground
40
44
  ` },
41
- { variant: 'solid', type: 'danger', class: `
45
+ { variant: 'solid', color: 'danger', class: `
42
46
  border-danger bg-danger text-danger-foreground
43
47
  ` },
44
48
  // soft — tinted background + soft border
45
- { variant: 'soft', type: 'default', class: `
49
+ { variant: 'soft', color: 'default', class: `
46
50
  border-border bg-secondary text-secondary-foreground
47
51
  ` },
48
- { variant: 'soft', type: 'success', class: `
52
+ { variant: 'soft', color: 'primary', class: `
53
+ border-primary/50 bg-primary/10 text-primary
54
+ ` },
55
+ { variant: 'soft', color: 'success', class: `
49
56
  border-success/50 bg-success/10 text-success
50
57
  ` },
51
- { variant: 'soft', type: 'info', class: `
58
+ { variant: 'soft', color: 'info', class: `
52
59
  border-info/50 bg-info/10 text-info
53
60
  ` },
54
- { variant: 'soft', type: 'help', class: `
61
+ { variant: 'soft', color: 'help', class: `
55
62
  border-help/50 bg-help/10 text-help
56
63
  ` },
57
- { variant: 'soft', type: 'warn', class: `
64
+ { variant: 'soft', color: 'warn', class: `
58
65
  border-warn/50 bg-warn/10 text-warn
59
66
  ` },
60
- { variant: 'soft', type: 'danger', class: `
67
+ { variant: 'soft', color: 'danger', class: `
61
68
  border-danger/50 bg-danger/10 text-danger
62
69
  ` },
63
70
  // bordered — border only
64
- { variant: 'bordered', type: 'default', class: `
71
+ { variant: 'bordered', color: 'default', class: `
65
72
  border-border text-foreground
66
73
  ` },
67
- { variant: 'bordered', type: 'success', class: `
74
+ { variant: 'bordered', color: 'primary', class: `
75
+ border-primary/50 text-primary
76
+ ` },
77
+ { variant: 'bordered', color: 'success', class: `
68
78
  border-success/50 text-success
69
79
  ` },
70
- { variant: 'bordered', type: 'info', class: 'border-info/50 text-info' },
71
- { variant: 'bordered', type: 'help', class: 'border-help/50 text-help' },
72
- { variant: 'bordered', type: 'warn', class: 'border-warn/50 text-warn' },
73
- { variant: 'bordered', type: 'danger', class: `
80
+ { variant: 'bordered', color: 'info', class: 'border-info/50 text-info' },
81
+ { variant: 'bordered', color: 'help', class: 'border-help/50 text-help' },
82
+ { variant: 'bordered', color: 'warn', class: 'border-warn/50 text-warn' },
83
+ { variant: 'bordered', color: 'danger', class: `
74
84
  border-danger/50 text-danger
75
85
  ` },
76
86
  // flat — tinted background only
77
- { variant: 'flat', type: 'default', class: `
87
+ { variant: 'flat', color: 'default', class: `
78
88
  bg-secondary text-secondary-foreground
79
89
  ` },
80
- { variant: 'flat', type: 'success', class: 'bg-success/10 text-success' },
81
- { variant: 'flat', type: 'info', class: 'bg-info/10 text-info' },
82
- { variant: 'flat', type: 'help', class: 'bg-help/10 text-help' },
83
- { variant: 'flat', type: 'warn', class: 'bg-warn/10 text-warn' },
84
- { variant: 'flat', type: 'danger', class: 'bg-danger/10 text-danger' },
90
+ { variant: 'flat', color: 'primary', class: 'bg-primary/10 text-primary' },
91
+ { variant: 'flat', color: 'success', class: 'bg-success/10 text-success' },
92
+ { variant: 'flat', color: 'info', class: 'bg-info/10 text-info' },
93
+ { variant: 'flat', color: 'help', class: 'bg-help/10 text-help' },
94
+ { variant: 'flat', color: 'warn', class: 'bg-warn/10 text-warn' },
95
+ { variant: 'flat', color: 'danger', class: 'bg-danger/10 text-danger' },
85
96
  ],
86
97
  defaultVariants: {
87
98
  variant: 'soft',
88
- type: 'default',
99
+ color: 'default',
89
100
  },
90
101
  },
91
102
  )
92
103
 
93
104
  const props = withDefaults(defineProps<TagProps>(), {
94
- type: 'default',
105
+ color: 'default',
95
106
  variant: 'soft',
96
107
  class: undefined,
97
108
  })
98
109
 
99
110
  const mergedClass = computed(() =>
100
- cn(tagVariants({ type: props.type, variant: props.variant }), props.class),
111
+ cn(tagVariants({ color: props.color, variant: props.variant }), props.class),
101
112
  )
102
113
  </script>
103
114
 
@@ -1,8 +1,8 @@
1
- export type TagType = 'default' | 'success' | 'info' | 'help' | 'warn' | 'danger'
1
+ export type TagColor = 'default' | 'primary' | 'success' | 'info' | 'help' | 'warn' | 'danger'
2
2
  export type TagVariant = 'solid' | 'soft' | 'bordered' | 'flat'
3
3
 
4
4
  export interface TagProps {
5
- type?: TagType
5
+ color?: TagColor
6
6
  variant?: TagVariant
7
7
  class?: ClassValue
8
8
  }