sonance-brand-mcp 1.2.5 → 1.3.2

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 (189) hide show
  1. package/dist/assets/api/sonance-analyze/route.ts +1116 -0
  2. package/dist/assets/api/sonance-assets/route.ts +113 -0
  3. package/dist/assets/api/sonance-components/route.ts +41 -0
  4. package/dist/assets/api/sonance-inject-id/route.ts +363 -0
  5. package/dist/assets/api/sonance-save-logo/route.ts +426 -0
  6. package/dist/assets/api/sonance-theme/route.ts +106 -0
  7. package/dist/assets/brand-system.ts +1265 -0
  8. package/dist/assets/components/accordion.stories.tsx +26 -26
  9. package/dist/assets/components/accordion.tsx +3 -3
  10. package/dist/assets/components/alert-dialog.stories.tsx +142 -0
  11. package/dist/assets/components/alert-dialog.tsx +143 -0
  12. package/dist/assets/components/alert.stories.tsx +3 -3
  13. package/dist/assets/components/alert.tsx +4 -3
  14. package/dist/assets/components/aspect-ratio.stories.tsx +70 -0
  15. package/dist/assets/components/aspect-ratio.tsx +8 -0
  16. package/dist/assets/components/autocomplete.stories.tsx +9 -9
  17. package/dist/assets/components/autocomplete.tsx +3 -3
  18. package/dist/assets/components/avatar.stories.tsx +5 -5
  19. package/dist/assets/components/avatar.tsx +67 -23
  20. package/dist/assets/components/badge.stories.tsx +10 -10
  21. package/dist/assets/components/badge.tsx +3 -3
  22. package/dist/assets/components/breadcrumbs.stories.tsx +7 -7
  23. package/dist/assets/components/breadcrumbs.tsx +13 -8
  24. package/dist/assets/components/button.stories.tsx +74 -74
  25. package/dist/assets/components/button.tsx +2 -0
  26. package/dist/assets/components/calendar.stories.tsx +11 -11
  27. package/dist/assets/components/calendar.tsx +4 -4
  28. package/dist/assets/components/card.stories.tsx +22 -22
  29. package/dist/assets/components/card.tsx +7 -3
  30. package/dist/assets/components/carousel.stories.tsx +158 -0
  31. package/dist/assets/components/carousel.tsx +264 -0
  32. package/dist/assets/components/chart.stories.tsx +376 -0
  33. package/dist/assets/components/chart.tsx +384 -0
  34. package/dist/assets/components/checkbox-group.stories.tsx +6 -6
  35. package/dist/assets/components/checkbox-group.tsx +3 -3
  36. package/dist/assets/components/checkbox.stories.tsx +23 -20
  37. package/dist/assets/components/checkbox.tsx +13 -6
  38. package/dist/assets/components/code.stories.tsx +24 -24
  39. package/dist/assets/components/code.tsx +22 -27
  40. package/dist/assets/components/collapsible.stories.tsx +128 -0
  41. package/dist/assets/components/collapsible.tsx +10 -0
  42. package/dist/assets/components/command.stories.tsx +183 -0
  43. package/dist/assets/components/command.tsx +171 -0
  44. package/dist/assets/components/context-menu.stories.tsx +159 -0
  45. package/dist/assets/components/context-menu.tsx +214 -0
  46. package/dist/assets/components/date-input.stories.tsx +9 -9
  47. package/dist/assets/components/date-input.tsx +2 -2
  48. package/dist/assets/components/date-picker.stories.tsx +9 -9
  49. package/dist/assets/components/date-picker.tsx +3 -3
  50. package/dist/assets/components/date-range-picker.stories.tsx +12 -12
  51. package/dist/assets/components/date-range-picker.tsx +3 -3
  52. package/dist/assets/components/dialog.stories.tsx +40 -40
  53. package/dist/assets/components/dialog.tsx +8 -12
  54. package/dist/assets/components/divider.stories.tsx +30 -30
  55. package/dist/assets/components/divider.tsx +34 -35
  56. package/dist/assets/components/drawer.stories.tsx +32 -31
  57. package/dist/assets/components/drawer.tsx +7 -6
  58. package/dist/assets/components/dropdown-menu.tsx +213 -0
  59. package/dist/assets/components/dropdown.stories.tsx +12 -12
  60. package/dist/assets/components/dropdown.tsx +5 -5
  61. package/dist/assets/components/form.stories.tsx +30 -29
  62. package/dist/assets/components/form.tsx +5 -5
  63. package/dist/assets/components/hover-card.stories.tsx +115 -0
  64. package/dist/assets/components/hover-card.tsx +35 -0
  65. package/dist/assets/components/image.stories.tsx +48 -25
  66. package/dist/assets/components/image.tsx +8 -5
  67. package/dist/assets/components/input-otp.stories.tsx +15 -15
  68. package/dist/assets/components/input-otp.tsx +5 -5
  69. package/dist/assets/components/input.stories.tsx +30 -25
  70. package/dist/assets/components/input.tsx +7 -4
  71. package/dist/assets/components/kbd.stories.tsx +34 -34
  72. package/dist/assets/components/kbd.tsx +9 -9
  73. package/dist/assets/components/link.stories.tsx +36 -36
  74. package/dist/assets/components/link.tsx +4 -0
  75. package/dist/assets/components/listbox.stories.tsx +5 -5
  76. package/dist/assets/components/listbox.tsx +4 -4
  77. package/dist/assets/components/menubar.stories.tsx +208 -0
  78. package/dist/assets/components/menubar.tsx +247 -0
  79. package/dist/assets/components/navbar.stories.tsx +24 -24
  80. package/dist/assets/components/navbar.tsx +8 -14
  81. package/dist/assets/components/navigation-menu.stories.tsx +239 -0
  82. package/dist/assets/components/navigation-menu.tsx +135 -0
  83. package/dist/assets/components/number-input.stories.tsx +11 -11
  84. package/dist/assets/components/number-input.tsx +3 -3
  85. package/dist/assets/components/pagination.stories.tsx +13 -13
  86. package/dist/assets/components/pagination.tsx +6 -6
  87. package/dist/assets/components/popover.stories.tsx +35 -35
  88. package/dist/assets/components/popover.tsx +98 -15
  89. package/dist/assets/components/progress.stories.tsx +5 -5
  90. package/dist/assets/components/progress.tsx +5 -5
  91. package/dist/assets/components/radio-group.stories.tsx +7 -7
  92. package/dist/assets/components/radio-group.tsx +3 -3
  93. package/dist/assets/components/range-calendar.stories.tsx +18 -18
  94. package/dist/assets/components/range-calendar.tsx +3 -3
  95. package/dist/assets/components/resizable.stories.tsx +197 -0
  96. package/dist/assets/components/resizable.tsx +47 -0
  97. package/dist/assets/components/scroll-area.stories.tsx +123 -0
  98. package/dist/assets/components/scroll-area.tsx +48 -0
  99. package/dist/assets/components/scroll-shadow.stories.tsx +17 -17
  100. package/dist/assets/components/scroll-shadow.tsx +31 -9
  101. package/dist/assets/components/select.stories.tsx +20 -19
  102. package/dist/assets/components/select.tsx +10 -6
  103. package/dist/assets/components/separator.tsx +32 -0
  104. package/dist/assets/components/sheet.tsx +137 -0
  105. package/dist/assets/components/sidebar.stories.tsx +351 -0
  106. package/dist/assets/components/sidebar.tsx +757 -0
  107. package/dist/assets/components/skeleton.stories.tsx +3 -3
  108. package/dist/assets/components/skeleton.tsx +2 -2
  109. package/dist/assets/components/slider.stories.tsx +6 -6
  110. package/dist/assets/components/slider.tsx +3 -3
  111. package/dist/assets/components/spacer.stories.tsx +11 -11
  112. package/dist/assets/components/spacer.tsx +2 -2
  113. package/dist/assets/components/spinner.stories.tsx +8 -8
  114. package/dist/assets/components/spinner.tsx +5 -5
  115. package/dist/assets/components/switch.stories.tsx +24 -20
  116. package/dist/assets/components/switch.tsx +14 -6
  117. package/dist/assets/components/table.stories.tsx +7 -7
  118. package/dist/assets/components/table.tsx +8 -8
  119. package/dist/assets/components/tabs.stories.tsx +37 -37
  120. package/dist/assets/components/tabs.tsx +3 -3
  121. package/dist/assets/components/textarea.stories.tsx +13 -12
  122. package/dist/assets/components/textarea.tsx +3 -3
  123. package/dist/assets/components/theme-toggle.stories.tsx +31 -30
  124. package/dist/assets/components/theme-toggle.tsx +2 -2
  125. package/dist/assets/components/time-input.stories.tsx +16 -16
  126. package/dist/assets/components/time-input.tsx +2 -2
  127. package/dist/assets/components/toast.stories.tsx +8 -5
  128. package/dist/assets/components/toast.tsx +6 -6
  129. package/dist/assets/components/toggle-group.stories.tsx +153 -0
  130. package/dist/assets/components/toggle-group.tsx +61 -0
  131. package/dist/assets/components/toggle.stories.tsx +77 -0
  132. package/dist/assets/components/toggle.tsx +46 -0
  133. package/dist/assets/components/tooltip.stories.tsx +49 -27
  134. package/dist/assets/components/tooltip.tsx +23 -90
  135. package/dist/assets/components/user.stories.tsx +23 -23
  136. package/dist/assets/components/user.tsx +7 -4
  137. package/dist/assets/dev-tools/SonanceDevTools.tsx +4201 -0
  138. package/dist/assets/dev-tools/index.ts +10 -0
  139. package/dist/assets/globals.css +39 -0
  140. package/dist/assets/logos/40th-anniversary/Sonance_40_Logo_CMYK_BEAM_BLUE_40_AND_BEAM_DARK.png +0 -0
  141. package/dist/assets/logos/Sonance logo dark mode.png +0 -0
  142. package/dist/assets/logos/Sonance logo light mode.png +0 -0
  143. package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_2C_Light_RGB_05162025.png +0 -0
  144. package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_3C_Dark_RGB_05162025.png +0 -0
  145. package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_White_RGB_05162025.png +0 -0
  146. package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Dark_RGB.png +0 -0
  147. package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Light_RGB.png +0 -0
  148. package/dist/assets/logos/james/James_Logo_Black_CMYK.png +0 -0
  149. package/dist/assets/logos/james/James_Logo_Black_RGB.png +0 -0
  150. package/dist/assets/logos/james/James_Logo_LtGray_CMYK.png +0 -0
  151. package/dist/assets/logos/james/James_Logo_LtGray_RGB.png +0 -0
  152. package/dist/assets/logos/james/James_Logo_Polished_RGB.png +0 -0
  153. package/dist/assets/logos/james/James_Logo_Reverse_CMYK.png +0 -0
  154. package/dist/assets/logos/james/James_Logo_Reverse_RGB.png +0 -0
  155. package/dist/assets/logos/james/James_Logo_White_CMYK.png +0 -0
  156. package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Dark_RGB.png +0 -0
  157. package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Light_RGB.png +0 -0
  158. package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Dark_RGB.png +0 -0
  159. package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Light_RGB.png +0 -0
  160. package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Reverse_RGB.png +0 -0
  161. package/dist/assets/logos/my-sonance/My.Sonance_Logo_Black_RGB.png +0 -0
  162. package/dist/assets/logos/my-sonance/My.Sonance_Logo_Reverse_RGB.png +0 -0
  163. package/dist/assets/logos/sonance/Sonance_Logo_2C_Dark_RGB.png +0 -0
  164. package/dist/assets/logos/sonance/Sonance_Logo_2C_Light_RGB.png +0 -0
  165. package/dist/assets/logos/sonance/Sonance_Logo_2C_Reverse_RGB.png +0 -0
  166. package/dist/assets/logos/sonance/Sonance_Logo_Black_RGB.png +0 -0
  167. package/dist/assets/logos/sonance/Sonance_Logo_Grayscale_RGB.png +0 -0
  168. package/dist/assets/logos/sonance/Sonance_Logo_Reverse_RGB.png +0 -0
  169. package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Dark_CMYK.png +0 -0
  170. package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Light_CMYK.png +0 -0
  171. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Dark_RGB.png +0 -0
  172. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Light_RGB.png +0 -0
  173. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Reverse_RGB.png +0 -0
  174. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Black_RGB.png +0 -0
  175. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Grayscale_RGB.png +0 -0
  176. package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Reverse_RGB.png +0 -0
  177. package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Dark.png +0 -0
  178. package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Light.png +0 -0
  179. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Dark.png +0 -0
  180. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Light.png +0 -0
  181. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Dark.png +0 -0
  182. package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Light.png +0 -0
  183. package/dist/assets/logos/trufig/TrufigLogo_Black.png +0 -0
  184. package/dist/assets/logos/trufig/TrufigLogo_Light.png +0 -0
  185. package/dist/assets/logos/trufig/TrufigWatermark_Black.png +0 -0
  186. package/dist/assets/logos/trufig/TrufigWatermark_Light.png +0 -0
  187. package/dist/assets/styles/brand-overrides.css +37 -0
  188. package/dist/index.js +2055 -15
  189. package/package.json +1 -1
@@ -108,7 +108,7 @@ export const TimeInput = forwardRef<HTMLInputElement, TimeInputProps>(
108
108
  };
109
109
 
110
110
  return (
111
- <div className={cn("w-full", className)}>
111
+ <div data-sonance-name="time-input" className={cn("w-full", className)}>
112
112
  {label && (
113
113
  <label className="mb-2 block text-xs font-medium uppercase tracking-widest text-foreground-muted">
114
114
  {label}
@@ -154,7 +154,7 @@ export const TimeInput = forwardRef<HTMLInputElement, TimeInputProps>(
154
154
  </button>
155
155
  )}
156
156
  </div>
157
- {error && <p className="mt-1 text-sm text-error">{error}</p>}
157
+ {error && <p id="p-error" className="mt-1 text-sm text-error">{error}</p>}
158
158
  </div>
159
159
  );
160
160
  }
@@ -89,7 +89,7 @@ export const WithAction: Story = {
89
89
  description: 'A new version of the app is ready to install.',
90
90
  onClose: () => {},
91
91
  action: (
92
- <Button size="sm" variant="secondary">
92
+ <Button id="with-action-button-secondary" size="sm" variant="secondary">
93
93
  Update now
94
94
  </Button>
95
95
  ),
@@ -108,8 +108,9 @@ function ToastDemo() {
108
108
  const { addToast } = useToast();
109
109
 
110
110
  return (
111
- <div className="space-y-4">
111
+ <div data-sonance-name="toast.stories" className="space-y-4">
112
112
  <Button
113
+ id="toast-demo-button"
113
114
  onClick={() =>
114
115
  addToast({
115
116
  title: 'Success',
@@ -121,6 +122,7 @@ function ToastDemo() {
121
122
  Show Success Toast
122
123
  </Button>
123
124
  <Button
125
+ id="toast-demo-button-secondary"
124
126
  variant="secondary"
125
127
  onClick={() =>
126
128
  addToast({
@@ -133,6 +135,7 @@ function ToastDemo() {
133
135
  Show Error Toast
134
136
  </Button>
135
137
  <Button
138
+ id="toast-demo-button-ghost"
136
139
  variant="ghost"
137
140
  onClick={() =>
138
141
  addToast({
@@ -162,7 +165,7 @@ export const ResponsiveMatrix: Story = {
162
165
  <div className="space-y-8">
163
166
  {/* Mobile */}
164
167
  <div>
165
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
168
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
166
169
  <div className="w-[375px] border border-dashed border-border p-4 space-y-2">
167
170
  <Toast variant="success" title="Success" description="Changes saved." onClose={() => {}} />
168
171
  <Toast variant="error" title="Error" description="Failed to save." onClose={() => {}} />
@@ -170,7 +173,7 @@ export const ResponsiveMatrix: Story = {
170
173
  </div>
171
174
  {/* Tablet */}
172
175
  <div>
173
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
176
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
174
177
  <div className="w-[768px] border border-dashed border-border p-4">
175
178
  <div className="flex gap-4">
176
179
  <Toast variant="success" title="Success" description="Your changes have been saved." onClose={() => {}} />
@@ -180,7 +183,7 @@ export const ResponsiveMatrix: Story = {
180
183
  </div>
181
184
  {/* Desktop */}
182
185
  <div>
183
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
186
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
184
187
  <div className="w-[1280px] border border-dashed border-border p-4">
185
188
  <div className="flex gap-4">
186
189
  <Toast variant="default" title="Notification" description="Default toast notification." onClose={() => {}} />
@@ -47,17 +47,17 @@ export const Toast = forwardRef<HTMLDivElement, ToastProps>(
47
47
  const Icon = iconMap[variant || "default"];
48
48
 
49
49
  return (
50
- <div
50
+ <div data-sonance-name="toast"
51
51
  ref={ref}
52
52
  role="alert"
53
- className={cn(toastVariants({ variant }), className)}
53
+ className={cn(toastVariants({ variant }), className)}
54
54
  {...props}
55
55
  >
56
56
  <Icon className="h-5 w-5 shrink-0 mt-0.5" />
57
57
  <div className="flex-1 space-y-1">
58
- {title && <p className="text-sm font-medium">{title}</p>}
58
+ {title && <p id="icon-p-title" className="text-sm font-medium">{title}</p>}
59
59
  {description && (
60
- <p className={cn("text-sm", variant === "default" && "text-foreground-secondary")}>
60
+ <p id="icon-p-description" className={cn("text-sm", variant === "default" && "text-foreground-secondary")}>
61
61
  {description}
62
62
  </p>
63
63
  )}
@@ -70,7 +70,7 @@ export const Toast = forwardRef<HTMLDivElement, ToastProps>(
70
70
  className="shrink-0 p-1 opacity-70 hover:opacity-100 transition-opacity"
71
71
  >
72
72
  <X className="h-4 w-4" />
73
- <span className="sr-only">Dismiss</span>
73
+ <span id="icon-span-dismiss" className="sr-only">Dismiss</span>
74
74
  </button>
75
75
  )}
76
76
  </div>
@@ -163,7 +163,7 @@ export function ToastProvider({
163
163
  return (
164
164
  <ToastContext.Provider value={{ toasts, addToast, removeToast, clearToasts }}>
165
165
  {children}
166
- <div
166
+ <div data-sonance-name="toast"
167
167
  className={cn(
168
168
  "fixed z-[100] flex flex-col gap-2 pointer-events-none",
169
169
  positionClasses[position]
@@ -0,0 +1,153 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Bold, Italic, Underline, AlignLeft, AlignCenter, AlignRight } from "lucide-react";
3
+ import { ToggleGroup, ToggleGroupItem } from "./toggle-group";
4
+
5
+ const meta: Meta<typeof ToggleGroup> = {
6
+ title: "Components/Forms/ToggleGroup",
7
+ component: ToggleGroup,
8
+ parameters: {
9
+ layout: "centered",
10
+ },
11
+ tags: ["autodocs"],
12
+ argTypes: {
13
+ variant: {
14
+ control: "select",
15
+ options: ["default", "outline"],
16
+ },
17
+ size: {
18
+ control: "select",
19
+ options: ["default", "sm", "lg"],
20
+ },
21
+ type: {
22
+ control: "select",
23
+ options: ["single", "multiple"],
24
+ },
25
+ },
26
+ };
27
+
28
+ export default meta;
29
+ type Story = StoryObj<typeof ToggleGroup>;
30
+
31
+ export const Single: Story = {
32
+ args: {
33
+ type: "single",
34
+ defaultValue: "center",
35
+ },
36
+ render: (args) => (
37
+ <ToggleGroup {...args}>
38
+ <ToggleGroupItem value="left" aria-label="Left aligned">
39
+ <AlignLeft className="h-4 w-4" />
40
+ </ToggleGroupItem>
41
+ <ToggleGroupItem value="center" aria-label="Center aligned">
42
+ <AlignCenter className="h-4 w-4" />
43
+ </ToggleGroupItem>
44
+ <ToggleGroupItem value="right" aria-label="Right aligned">
45
+ <AlignRight className="h-4 w-4" />
46
+ </ToggleGroupItem>
47
+ </ToggleGroup>
48
+ ),
49
+ };
50
+
51
+ export const Multiple: Story = {
52
+ args: {
53
+ type: "multiple",
54
+ defaultValue: ["bold"],
55
+ },
56
+ render: (args) => (
57
+ <ToggleGroup {...args}>
58
+ <ToggleGroupItem value="bold" aria-label="Toggle bold">
59
+ <Bold className="h-4 w-4" />
60
+ </ToggleGroupItem>
61
+ <ToggleGroupItem value="italic" aria-label="Toggle italic">
62
+ <Italic className="h-4 w-4" />
63
+ </ToggleGroupItem>
64
+ <ToggleGroupItem value="underline" aria-label="Toggle underline">
65
+ <Underline className="h-4 w-4" />
66
+ </ToggleGroupItem>
67
+ </ToggleGroup>
68
+ ),
69
+ };
70
+
71
+ export const Outline: Story = {
72
+ args: {
73
+ type: "single",
74
+ variant: "outline",
75
+ defaultValue: "center",
76
+ },
77
+ render: (args) => (
78
+ <ToggleGroup {...args}>
79
+ <ToggleGroupItem value="left" aria-label="Left aligned">
80
+ <AlignLeft className="h-4 w-4" />
81
+ </ToggleGroupItem>
82
+ <ToggleGroupItem value="center" aria-label="Center aligned">
83
+ <AlignCenter className="h-4 w-4" />
84
+ </ToggleGroupItem>
85
+ <ToggleGroupItem value="right" aria-label="Right aligned">
86
+ <AlignRight className="h-4 w-4" />
87
+ </ToggleGroupItem>
88
+ </ToggleGroup>
89
+ ),
90
+ };
91
+
92
+ export const Small: Story = {
93
+ args: {
94
+ type: "multiple",
95
+ size: "sm",
96
+ },
97
+ render: (args) => (
98
+ <ToggleGroup {...args}>
99
+ <ToggleGroupItem value="bold" aria-label="Toggle bold">
100
+ <Bold className="h-4 w-4" />
101
+ </ToggleGroupItem>
102
+ <ToggleGroupItem value="italic" aria-label="Toggle italic">
103
+ <Italic className="h-4 w-4" />
104
+ </ToggleGroupItem>
105
+ <ToggleGroupItem value="underline" aria-label="Toggle underline">
106
+ <Underline className="h-4 w-4" />
107
+ </ToggleGroupItem>
108
+ </ToggleGroup>
109
+ ),
110
+ };
111
+
112
+ export const Large: Story = {
113
+ args: {
114
+ type: "single",
115
+ size: "lg",
116
+ defaultValue: "left",
117
+ },
118
+ render: (args) => (
119
+ <ToggleGroup {...args}>
120
+ <ToggleGroupItem value="left" aria-label="Left aligned">
121
+ <AlignLeft className="h-4 w-4" />
122
+ </ToggleGroupItem>
123
+ <ToggleGroupItem value="center" aria-label="Center aligned">
124
+ <AlignCenter className="h-4 w-4" />
125
+ </ToggleGroupItem>
126
+ <ToggleGroupItem value="right" aria-label="Right aligned">
127
+ <AlignRight className="h-4 w-4" />
128
+ </ToggleGroupItem>
129
+ </ToggleGroup>
130
+ ),
131
+ };
132
+
133
+ export const Disabled: Story = {
134
+ args: {
135
+ type: "single",
136
+ defaultValue: "center",
137
+ disabled: true,
138
+ },
139
+ render: (args) => (
140
+ <ToggleGroup {...args}>
141
+ <ToggleGroupItem value="left" aria-label="Left aligned">
142
+ <AlignLeft className="h-4 w-4" />
143
+ </ToggleGroupItem>
144
+ <ToggleGroupItem value="center" aria-label="Center aligned">
145
+ <AlignCenter className="h-4 w-4" />
146
+ </ToggleGroupItem>
147
+ <ToggleGroupItem value="right" aria-label="Right aligned">
148
+ <AlignRight className="h-4 w-4" />
149
+ </ToggleGroupItem>
150
+ </ToggleGroup>
151
+ ),
152
+ };
153
+
@@ -0,0 +1,61 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
5
+ import { type VariantProps } from "class-variance-authority";
6
+ import { cn } from "@/lib/utils";
7
+ import { toggleVariants } from "@/components/ui/toggle";
8
+
9
+ const ToggleGroupContext = React.createContext<
10
+ VariantProps<typeof toggleVariants>
11
+ >({
12
+ size: "default",
13
+ variant: "default",
14
+ });
15
+
16
+ const ToggleGroup = React.forwardRef<
17
+ React.ElementRef<typeof ToggleGroupPrimitive.Root>,
18
+ React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
19
+ VariantProps<typeof toggleVariants>
20
+ >(({ className, variant, size, children, ...props }, ref) => (
21
+ <ToggleGroupPrimitive.Root data-sonance-name="toggle-group"
22
+ ref={ref}
23
+ className={cn("flex items-center justify-center gap-1", className)}
24
+ {...props}
25
+ >
26
+ <ToggleGroupContext.Provider value={{ variant, size }}>
27
+ {children}
28
+ </ToggleGroupContext.Provider>
29
+ </ToggleGroupPrimitive.Root>
30
+ ));
31
+
32
+ ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
33
+
34
+ const ToggleGroupItem = React.forwardRef<
35
+ React.ElementRef<typeof ToggleGroupPrimitive.Item>,
36
+ React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
37
+ VariantProps<typeof toggleVariants>
38
+ >(({ className, children, variant, size, ...props }, ref) => {
39
+ const context = React.useContext(ToggleGroupContext);
40
+
41
+ return (
42
+ <ToggleGroupPrimitive.Item
43
+ ref={ref}
44
+ className={cn(
45
+ toggleVariants({
46
+ variant: context.variant || variant,
47
+ size: context.size || size,
48
+ }),
49
+ className
50
+ )}
51
+ {...props}
52
+ >
53
+ {children}
54
+ </ToggleGroupPrimitive.Item>
55
+ );
56
+ });
57
+
58
+ ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
59
+
60
+ export { ToggleGroup, ToggleGroupItem };
61
+
@@ -0,0 +1,77 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Bold, Italic, Underline } from "lucide-react";
3
+ import { Toggle } from "./toggle";
4
+
5
+ const meta: Meta<typeof Toggle> = {
6
+ title: "Components/Forms/Toggle",
7
+ component: Toggle,
8
+ parameters: {
9
+ layout: "centered",
10
+ },
11
+ tags: ["autodocs"],
12
+ argTypes: {
13
+ variant: {
14
+ control: "select",
15
+ options: ["default", "outline"],
16
+ },
17
+ size: {
18
+ control: "select",
19
+ options: ["default", "sm", "lg"],
20
+ },
21
+ },
22
+ };
23
+
24
+ export default meta;
25
+ type Story = StoryObj<typeof Toggle>;
26
+
27
+ export const Default: Story = {
28
+ args: {
29
+ "aria-label": "Toggle bold",
30
+ children: <Bold className="h-4 w-4" />,
31
+ },
32
+ };
33
+
34
+ export const Outline: Story = {
35
+ args: {
36
+ variant: "outline",
37
+ "aria-label": "Toggle italic",
38
+ children: <Italic className="h-4 w-4" />,
39
+ },
40
+ };
41
+
42
+ export const WithText: Story = {
43
+ args: {
44
+ "aria-label": "Toggle italic",
45
+ children: (
46
+ <>
47
+ <Italic className="h-4 w-4" />
48
+ Italic
49
+ </>
50
+ ),
51
+ },
52
+ };
53
+
54
+ export const Small: Story = {
55
+ args: {
56
+ size: "sm",
57
+ "aria-label": "Toggle bold",
58
+ children: <Bold className="h-4 w-4" />,
59
+ },
60
+ };
61
+
62
+ export const Large: Story = {
63
+ args: {
64
+ size: "lg",
65
+ "aria-label": "Toggle bold",
66
+ children: <Bold className="h-4 w-4" />,
67
+ },
68
+ };
69
+
70
+ export const Disabled: Story = {
71
+ args: {
72
+ "aria-label": "Toggle underline",
73
+ disabled: true,
74
+ children: <Underline className="h-4 w-4" />,
75
+ },
76
+ };
77
+
@@ -0,0 +1,46 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as TogglePrimitive from "@radix-ui/react-toggle";
5
+ import { cva, type VariantProps } from "class-variance-authority";
6
+ import { cn } from "@/lib/utils";
7
+
8
+ const toggleVariants = cva(
9
+ "inline-flex items-center justify-center gap-2 rounded-sm text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default:
14
+ "bg-transparent hover:bg-secondary-hover text-foreground-secondary data-[state=on]:bg-secondary-hover data-[state=on]:text-foreground",
15
+ outline:
16
+ "border border-border bg-transparent hover:bg-secondary-hover hover:text-foreground data-[state=on]:bg-primary data-[state=on]:text-primary-foreground",
17
+ },
18
+ size: {
19
+ default: "h-10 px-3 min-w-10",
20
+ sm: "h-8 px-2 min-w-8",
21
+ lg: "h-11 px-4 min-w-11",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: "default",
26
+ size: "default",
27
+ },
28
+ }
29
+ );
30
+
31
+ const Toggle = React.forwardRef<
32
+ React.ElementRef<typeof TogglePrimitive.Root>,
33
+ React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
34
+ VariantProps<typeof toggleVariants>
35
+ >(({ className, variant, size, ...props }, ref) => (
36
+ <TogglePrimitive.Root data-sonance-name="toggle"
37
+ ref={ref}
38
+ className={cn(toggleVariants({ variant, size, className }))}
39
+ {...props}
40
+ />
41
+ ));
42
+
43
+ Toggle.displayName = TogglePrimitive.Root.displayName;
44
+
45
+ export { Toggle, toggleVariants };
46
+
@@ -1,7 +1,29 @@
1
1
  import type { Meta, StoryObj } from '@storybook/nextjs-vite';
2
- import { Tooltip } from './tooltip';
2
+ import { Tooltip as TooltipRoot, TooltipContent, TooltipProvider, TooltipTrigger } from './tooltip';
3
3
  import { Button } from './button';
4
4
 
5
+ const Tooltip = ({
6
+ children,
7
+ content,
8
+ side,
9
+ delay,
10
+ ...props
11
+ }: {
12
+ children: React.ReactNode;
13
+ content: string;
14
+ side?: 'top' | 'bottom' | 'left' | 'right';
15
+ delay?: number;
16
+ } & React.ComponentProps<typeof TooltipRoot>) => {
17
+ return (
18
+ <TooltipProvider delayDuration={delay}>
19
+ <TooltipRoot data-sonance-name="tooltip.stories" {...props}>
20
+ <TooltipTrigger asChild>{children}</TooltipTrigger>
21
+ <TooltipContent side={side}>{content}</TooltipContent>
22
+ </TooltipRoot>
23
+ </TooltipProvider>
24
+ );
25
+ };
26
+
5
27
  const meta: Meta<typeof Tooltip> = {
6
28
  title: 'Components/Overlays/Tooltip',
7
29
  component: Tooltip,
@@ -44,7 +66,7 @@ type Story = StoryObj<typeof meta>;
44
66
  export const Default: Story = {
45
67
  render: () => (
46
68
  <Tooltip content="This is a tooltip">
47
- <Button variant="secondary">Hover me</Button>
69
+ <Button id="default-button-secondary" variant="secondary">Hover me</Button>
48
70
  </Tooltip>
49
71
  ),
50
72
  };
@@ -53,7 +75,7 @@ export const Default: Story = {
53
75
  export const Top: Story = {
54
76
  render: () => (
55
77
  <Tooltip content="Tooltip on top" side="top">
56
- <Button variant="secondary">Top</Button>
78
+ <Button id="top-button-secondary" variant="secondary">Top</Button>
57
79
  </Tooltip>
58
80
  ),
59
81
  };
@@ -62,7 +84,7 @@ export const Top: Story = {
62
84
  export const Bottom: Story = {
63
85
  render: () => (
64
86
  <Tooltip content="Tooltip on bottom" side="bottom">
65
- <Button variant="secondary">Bottom</Button>
87
+ <Button id="bottom-button-secondary" variant="secondary">Bottom</Button>
66
88
  </Tooltip>
67
89
  ),
68
90
  };
@@ -71,7 +93,7 @@ export const Bottom: Story = {
71
93
  export const Left: Story = {
72
94
  render: () => (
73
95
  <Tooltip content="Tooltip on left" side="left">
74
- <Button variant="secondary">Left</Button>
96
+ <Button id="left-button-secondary" variant="secondary">Left</Button>
75
97
  </Tooltip>
76
98
  ),
77
99
  };
@@ -80,7 +102,7 @@ export const Left: Story = {
80
102
  export const Right: Story = {
81
103
  render: () => (
82
104
  <Tooltip content="Tooltip on right" side="right">
83
- <Button variant="secondary">Right</Button>
105
+ <Button id="right-button-secondary" variant="secondary">Right</Button>
84
106
  </Tooltip>
85
107
  ),
86
108
  };
@@ -90,16 +112,16 @@ export const AllPositions: Story = {
90
112
  render: () => (
91
113
  <div className="flex items-center gap-8 p-8">
92
114
  <Tooltip content="Top tooltip" side="top">
93
- <Button variant="secondary">Top</Button>
115
+ <Button id="all-positions-button-secondary" variant="secondary">Top</Button>
94
116
  </Tooltip>
95
117
  <Tooltip content="Bottom tooltip" side="bottom">
96
- <Button variant="secondary">Bottom</Button>
118
+ <Button id="all-positions-button-secondary" variant="secondary">Bottom</Button>
97
119
  </Tooltip>
98
120
  <Tooltip content="Left tooltip" side="left">
99
- <Button variant="secondary">Left</Button>
121
+ <Button id="all-positions-button-secondary" variant="secondary">Left</Button>
100
122
  </Tooltip>
101
123
  <Tooltip content="Right tooltip" side="right">
102
- <Button variant="secondary">Right</Button>
124
+ <Button id="all-positions-button-secondary" variant="secondary">Right</Button>
103
125
  </Tooltip>
104
126
  </div>
105
127
  ),
@@ -110,13 +132,13 @@ export const WithDelay: Story = {
110
132
  render: () => (
111
133
  <div className="flex gap-4">
112
134
  <Tooltip content="No delay (0ms)" delay={0}>
113
- <Button variant="secondary">Instant</Button>
135
+ <Button id="with-delay-button-secondary" variant="secondary">Instant</Button>
114
136
  </Tooltip>
115
137
  <Tooltip content="Default delay (200ms)" delay={200}>
116
- <Button variant="secondary">Default</Button>
138
+ <Button id="with-delay-button-secondary" variant="secondary">Default</Button>
117
139
  </Tooltip>
118
140
  <Tooltip content="Slow delay (500ms)" delay={500}>
119
- <Button variant="secondary">Slow</Button>
141
+ <Button id="with-delay-button-secondary" variant="secondary">Slow</Button>
120
142
  </Tooltip>
121
143
  </div>
122
144
  ),
@@ -155,7 +177,7 @@ export const OnIconButton: Story = {
155
177
  export const LongContent: Story = {
156
178
  render: () => (
157
179
  <Tooltip content="This is a tooltip with longer content that explains something in more detail">
158
- <Button variant="secondary">Hover for details</Button>
180
+ <Button id="long-content-button-secondary" variant="secondary">Hover for details</Button>
159
181
  </Tooltip>
160
182
  ),
161
183
  };
@@ -163,10 +185,10 @@ export const LongContent: Story = {
163
185
  // On Text
164
186
  export const OnText: Story = {
165
187
  render: () => (
166
- <p className="text-foreground-secondary">
188
+ <p id="on-text-p" className="text-foreground-secondary">
167
189
  Hover over the{' '}
168
190
  <Tooltip content="This is additional information">
169
- <span className="text-foreground border-b border-dashed border-foreground-muted cursor-help">
191
+ <span id="on-text-span-underlined-text" className="text-foreground border-b border-dashed border-foreground-muted cursor-help">
170
192
  underlined text
171
193
  </span>
172
194
  </Tooltip>{' '}
@@ -181,43 +203,43 @@ export const ResponsiveMatrix: Story = {
181
203
  <div className="space-y-8">
182
204
  {/* Mobile */}
183
205
  <div>
184
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
206
+ <h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
185
207
  <div className="w-[375px] border border-dashed border-border p-4 flex justify-center">
186
208
  <Tooltip content="Mobile tooltip">
187
- <Button variant="secondary" size="sm">Hover me</Button>
209
+ <Button id="responsive-matrix-button-secondary" variant="secondary" size="sm">Hover me</Button>
188
210
  </Tooltip>
189
211
  </div>
190
212
  </div>
191
213
  {/* Tablet */}
192
214
  <div>
193
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
215
+ <h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
194
216
  <div className="w-[768px] border border-dashed border-border p-4 flex justify-center gap-4">
195
217
  <Tooltip content="Top" side="top">
196
- <Button variant="secondary">Top</Button>
218
+ <Button id="responsive-matrix-button-secondary" variant="secondary">Top</Button>
197
219
  </Tooltip>
198
220
  <Tooltip content="Bottom" side="bottom">
199
- <Button variant="secondary">Bottom</Button>
221
+ <Button id="responsive-matrix-button-secondary" variant="secondary">Bottom</Button>
200
222
  </Tooltip>
201
223
  <Tooltip content="Left" side="left">
202
- <Button variant="secondary">Left</Button>
224
+ <Button id="responsive-matrix-button-secondary" variant="secondary">Left</Button>
203
225
  </Tooltip>
204
226
  <Tooltip content="Right" side="right">
205
- <Button variant="secondary">Right</Button>
227
+ <Button id="responsive-matrix-button-secondary" variant="secondary">Right</Button>
206
228
  </Tooltip>
207
229
  </div>
208
230
  </div>
209
231
  {/* Desktop */}
210
232
  <div>
211
- <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
233
+ <h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
212
234
  <div className="w-[1280px] border border-dashed border-border p-4 flex justify-between items-center">
213
235
  <Tooltip content="Edit item">
214
- <Button variant="ghost" size="sm">Edit</Button>
236
+ <Button id="responsive-matrix-button-ghost" variant="ghost" size="sm">Edit</Button>
215
237
  </Tooltip>
216
238
  <Tooltip content="This is a longer tooltip with more detailed explanation">
217
- <Button variant="secondary">Hover for details</Button>
239
+ <Button id="responsive-matrix-button-secondary" variant="secondary">Hover for details</Button>
218
240
  </Tooltip>
219
241
  <Tooltip content="Delete permanently" side="left">
220
- <Button variant="ghost" size="sm">Delete</Button>
242
+ <Button id="responsive-matrix-button-ghost" variant="ghost" size="sm">Delete</Button>
221
243
  </Tooltip>
222
244
  </div>
223
245
  </div>