sonance-brand-mcp 1.1.4 → 1.2.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 (73) hide show
  1. package/dist/assets/BRAND_GUIDELINES.md +0 -8
  2. package/dist/assets/components/accordion.stories.tsx +310 -0
  3. package/dist/assets/components/accordion.tsx +56 -30
  4. package/dist/assets/components/alert.stories.tsx +199 -0
  5. package/dist/assets/components/autocomplete.stories.tsx +307 -0
  6. package/dist/assets/components/autocomplete.tsx +28 -4
  7. package/dist/assets/components/avatar.stories.tsx +175 -0
  8. package/dist/assets/components/badge.stories.tsx +258 -0
  9. package/dist/assets/components/breadcrumbs.stories.tsx +175 -0
  10. package/dist/assets/components/button.stories.tsx +362 -0
  11. package/dist/assets/components/button.tsx +48 -3
  12. package/dist/assets/components/calendar.stories.tsx +247 -0
  13. package/dist/assets/components/card.stories.tsx +275 -0
  14. package/dist/assets/components/card.tsx +26 -1
  15. package/dist/assets/components/checkbox-group.stories.tsx +281 -0
  16. package/dist/assets/components/checkbox.stories.tsx +160 -0
  17. package/dist/assets/components/checkbox.tsx +32 -4
  18. package/dist/assets/components/code.stories.tsx +265 -0
  19. package/dist/assets/components/date-input.stories.tsx +278 -0
  20. package/dist/assets/components/date-input.tsx +24 -2
  21. package/dist/assets/components/date-picker.stories.tsx +337 -0
  22. package/dist/assets/components/date-picker.tsx +28 -4
  23. package/dist/assets/components/date-range-picker.stories.tsx +340 -0
  24. package/dist/assets/components/dialog.stories.tsx +285 -0
  25. package/dist/assets/components/divider.stories.tsx +176 -0
  26. package/dist/assets/components/drawer.stories.tsx +216 -0
  27. package/dist/assets/components/dropdown.stories.tsx +342 -0
  28. package/dist/assets/components/dropdown.tsx +55 -10
  29. package/dist/assets/components/form.stories.tsx +372 -0
  30. package/dist/assets/components/image.stories.tsx +348 -0
  31. package/dist/assets/components/input-otp.stories.tsx +336 -0
  32. package/dist/assets/components/input-otp.tsx +24 -2
  33. package/dist/assets/components/input.stories.tsx +223 -0
  34. package/dist/assets/components/input.tsx +27 -2
  35. package/dist/assets/components/kbd.stories.tsx +272 -0
  36. package/dist/assets/components/link.stories.tsx +199 -0
  37. package/dist/assets/components/link.tsx +50 -1
  38. package/dist/assets/components/listbox.stories.tsx +287 -0
  39. package/dist/assets/components/listbox.tsx +30 -7
  40. package/dist/assets/components/navbar.stories.tsx +218 -0
  41. package/dist/assets/components/number-input.stories.tsx +295 -0
  42. package/dist/assets/components/number-input.tsx +30 -8
  43. package/dist/assets/components/pagination.stories.tsx +280 -0
  44. package/dist/assets/components/pagination.tsx +45 -21
  45. package/dist/assets/components/popover.stories.tsx +219 -0
  46. package/dist/assets/components/progress.stories.tsx +153 -0
  47. package/dist/assets/components/radio-group.stories.tsx +187 -0
  48. package/dist/assets/components/radio-group.tsx +30 -6
  49. package/dist/assets/components/range-calendar.stories.tsx +334 -0
  50. package/dist/assets/components/scroll-shadow.stories.tsx +335 -0
  51. package/dist/assets/components/select.stories.tsx +192 -0
  52. package/dist/assets/components/select.tsx +54 -7
  53. package/dist/assets/components/skeleton.stories.tsx +166 -0
  54. package/dist/assets/components/slider.stories.tsx +145 -0
  55. package/dist/assets/components/slider.tsx +43 -8
  56. package/dist/assets/components/spacer.stories.tsx +216 -0
  57. package/dist/assets/components/spinner.stories.tsx +149 -0
  58. package/dist/assets/components/switch.stories.tsx +170 -0
  59. package/dist/assets/components/switch.tsx +29 -4
  60. package/dist/assets/components/table.stories.tsx +322 -0
  61. package/dist/assets/components/tabs.stories.tsx +306 -0
  62. package/dist/assets/components/tabs.tsx +25 -4
  63. package/dist/assets/components/textarea.stories.tsx +103 -0
  64. package/dist/assets/components/textarea.tsx +27 -3
  65. package/dist/assets/components/theme-toggle.stories.tsx +248 -0
  66. package/dist/assets/components/time-input.stories.tsx +365 -0
  67. package/dist/assets/components/time-input.tsx +25 -3
  68. package/dist/assets/components/toast.stories.tsx +195 -0
  69. package/dist/assets/components/tooltip.stories.tsx +226 -0
  70. package/dist/assets/components/user.stories.tsx +274 -0
  71. package/dist/assets/logo-manifest.json +0 -18
  72. package/dist/index.js +2142 -85
  73. package/package.json +1 -1
@@ -0,0 +1,160 @@
1
+ import type { Meta, StoryObj } from '@storybook/nextjs-vite';
2
+ import { Checkbox } from './checkbox';
3
+
4
+ const meta: Meta<typeof Checkbox> = {
5
+ title: 'Components/Forms/Checkbox',
6
+ component: Checkbox,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ docs: {
10
+ description: {
11
+ component: 'A checkbox input with optional label and description. Clean, minimal design.',
12
+ },
13
+ },
14
+ },
15
+ argTypes: {
16
+ label: {
17
+ control: 'text',
18
+ description: 'Label text',
19
+ },
20
+ description: {
21
+ control: 'text',
22
+ description: 'Description text below the label',
23
+ },
24
+ checked: {
25
+ control: 'boolean',
26
+ description: 'Checked state',
27
+ },
28
+ disabled: {
29
+ control: 'boolean',
30
+ description: 'Disabled state',
31
+ },
32
+ },
33
+ };
34
+
35
+ export default meta;
36
+ type Story = StoryObj<typeof meta>;
37
+
38
+ // Default
39
+ export const Default: Story = {
40
+ args: {},
41
+ };
42
+
43
+ // With Label
44
+ export const WithLabel: Story = {
45
+ args: {
46
+ label: 'Accept terms and conditions',
47
+ },
48
+ };
49
+
50
+ // With Description
51
+ export const WithDescription: Story = {
52
+ args: {
53
+ label: 'Marketing emails',
54
+ description: 'Receive emails about new products, features, and more.',
55
+ },
56
+ };
57
+
58
+ // Checked
59
+ export const Checked: Story = {
60
+ args: {
61
+ label: 'Remember me',
62
+ defaultChecked: true,
63
+ },
64
+ };
65
+
66
+ // Disabled
67
+ export const Disabled: Story = {
68
+ args: {
69
+ label: 'Disabled option',
70
+ disabled: true,
71
+ },
72
+ };
73
+
74
+ // Disabled Checked
75
+ export const DisabledChecked: Story = {
76
+ args: {
77
+ label: 'Disabled checked',
78
+ disabled: true,
79
+ defaultChecked: true,
80
+ },
81
+ };
82
+
83
+ // All States
84
+ export const AllStates: Story = {
85
+ render: () => (
86
+ <div className="space-y-4">
87
+ <Checkbox label="Unchecked" />
88
+ <Checkbox label="Checked" defaultChecked />
89
+ <Checkbox label="With description" description="Additional information about this option" />
90
+ <Checkbox label="Disabled" disabled />
91
+ <Checkbox label="Disabled checked" disabled defaultChecked />
92
+ </div>
93
+ ),
94
+ };
95
+
96
+ // Form Example
97
+ export const FormExample: Story = {
98
+ render: () => (
99
+ <div className="space-y-6 w-80">
100
+ <div className="space-y-4">
101
+ <h3 className="text-sm font-medium text-foreground">Notification Preferences</h3>
102
+ <Checkbox
103
+ label="Email notifications"
104
+ description="Get notified about account activity via email"
105
+ defaultChecked
106
+ />
107
+ <Checkbox
108
+ label="SMS notifications"
109
+ description="Get notified via text message"
110
+ />
111
+ <Checkbox
112
+ label="Push notifications"
113
+ description="Get notified on your mobile device"
114
+ defaultChecked
115
+ />
116
+ </div>
117
+ </div>
118
+ ),
119
+ };
120
+
121
+ // Responsive Matrix - Mobile, Tablet, Desktop
122
+ export const ResponsiveMatrix: Story = {
123
+ render: () => (
124
+ <div className="space-y-8">
125
+ {/* Mobile */}
126
+ <div>
127
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
128
+ <div className="w-[375px] border border-dashed border-border p-4 space-y-4">
129
+ <Checkbox label="Accept terms and conditions" />
130
+ <Checkbox label="Subscribe to newsletter" description="Receive updates about new features" />
131
+ <Checkbox label="Remember me" defaultChecked />
132
+ </div>
133
+ </div>
134
+ {/* Tablet */}
135
+ <div>
136
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
137
+ <div className="w-[768px] border border-dashed border-border p-4">
138
+ <div className="grid grid-cols-2 gap-4">
139
+ <Checkbox label="Email notifications" description="Get notified via email" defaultChecked />
140
+ <Checkbox label="SMS notifications" description="Get notified via text" />
141
+ <Checkbox label="Push notifications" description="Mobile app notifications" defaultChecked />
142
+ <Checkbox label="Marketing emails" description="Product updates and offers" />
143
+ </div>
144
+ </div>
145
+ </div>
146
+ {/* Desktop */}
147
+ <div>
148
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
149
+ <div className="w-[1280px] border border-dashed border-border p-4">
150
+ <div className="grid grid-cols-4 gap-4">
151
+ <Checkbox label="Unchecked" />
152
+ <Checkbox label="Checked" defaultChecked />
153
+ <Checkbox label="Disabled" disabled />
154
+ <Checkbox label="Disabled checked" disabled defaultChecked />
155
+ </div>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ ),
160
+ };
@@ -1,17 +1,38 @@
1
1
  "use client";
2
2
 
3
- import { forwardRef } from "react";
3
+ import { forwardRef, useId } from "react";
4
4
  import { Check } from "lucide-react";
5
5
  import { cn } from "@/lib/utils";
6
6
 
7
+ export type CheckboxState = "default" | "hover" | "focus" | "checked" | "disabled";
8
+
7
9
  interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type"> {
8
10
  label?: string;
9
11
  description?: string;
12
+ /** Visual state for Storybook/Figma documentation */
13
+ state?: CheckboxState;
10
14
  }
11
15
 
16
+ // State styles for Storybook/Figma visualization
17
+ const getStateStyles = (state?: CheckboxState) => {
18
+ if (!state || state === "default") return "";
19
+
20
+ const stateMap: Record<string, string> = {
21
+ hover: "border-border-hover",
22
+ focus: "ring-2 ring-border-focus ring-offset-2 ring-offset-background",
23
+ checked: "border-primary bg-primary",
24
+ disabled: "opacity-50 cursor-not-allowed",
25
+ };
26
+
27
+ return stateMap[state] || "";
28
+ };
29
+
12
30
  export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
13
- ({ className, label, description, id, ...props }, ref) => {
14
- const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
31
+ ({ className, label, description, id, state, disabled, checked, ...props }, ref) => {
32
+ const uniqueId = useId();
33
+ const inputId = id || `checkbox-${uniqueId}`;
34
+ const isDisabled = disabled || state === "disabled";
35
+ const isChecked = checked || state === "checked";
15
36
 
16
37
  return (
17
38
  <div className="flex items-start gap-3">
@@ -20,18 +41,25 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
20
41
  type="checkbox"
21
42
  id={inputId}
22
43
  ref={ref}
44
+ disabled={isDisabled}
45
+ checked={isChecked}
23
46
  className={cn(
24
47
  "peer h-5 w-5 shrink-0 appearance-none border border-border bg-input",
48
+ "hover:border-border-hover",
25
49
  "checked:border-primary checked:bg-primary",
26
50
  "focus:outline-none focus:ring-2 focus:ring-border-focus focus:ring-offset-2 focus:ring-offset-background",
27
51
  "disabled:cursor-not-allowed disabled:opacity-50",
28
52
  "transition-colors duration-150",
53
+ getStateStyles(state),
29
54
  className
30
55
  )}
31
56
  {...props}
32
57
  />
33
58
  <Check
34
- className="pointer-events-none absolute h-3.5 w-3.5 text-primary-foreground opacity-0 peer-checked:opacity-100 transition-opacity"
59
+ className={cn(
60
+ "pointer-events-none absolute h-3.5 w-3.5 text-primary-foreground opacity-0 peer-checked:opacity-100 transition-opacity",
61
+ state === "checked" && "opacity-100"
62
+ )}
35
63
  />
36
64
  </div>
37
65
  {(label || description) && (
@@ -0,0 +1,265 @@
1
+ import type { Meta, StoryObj } from '@storybook/nextjs-vite';
2
+ import { Code, CodeBlock, Snippet } from './code';
3
+
4
+ const meta: Meta<typeof Code> = {
5
+ title: 'Components/Utilities/Code',
6
+ component: Code,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ docs: {
10
+ description: {
11
+ component: 'Components for displaying code inline and in blocks with syntax highlighting.',
12
+ },
13
+ },
14
+ },
15
+ argTypes: {
16
+ variant: {
17
+ control: 'select',
18
+ options: ['default', 'primary'],
19
+ },
20
+ },
21
+ };
22
+
23
+ export default meta;
24
+ type Story = StoryObj<typeof meta>;
25
+
26
+ export const InlineDefault: Story = {
27
+ render: () => (
28
+ <p className="text-foreground-secondary">
29
+ Use the <Code>npm install</Code> command to install dependencies.
30
+ </p>
31
+ ),
32
+ };
33
+
34
+ export const InlinePrimary: Story = {
35
+ render: () => (
36
+ <p className="text-foreground-secondary">
37
+ The <Code variant="primary">useState</Code> hook is used for managing state in React.
38
+ </p>
39
+ ),
40
+ };
41
+
42
+ export const Block: Story = {
43
+ render: () => (
44
+ <CodeBlock
45
+ code={`function greet(name) {
46
+ console.log(\`Hello, \${name}!\`);
47
+ }
48
+
49
+ greet('Sonance');`}
50
+ language="javascript"
51
+ />
52
+ ),
53
+ };
54
+
55
+ export const BlockWithFilename: Story = {
56
+ render: () => (
57
+ <CodeBlock
58
+ filename="greeting.ts"
59
+ language="typescript"
60
+ code={`interface User {
61
+ name: string;
62
+ email: string;
63
+ }
64
+
65
+ function greet(user: User): string {
66
+ return \`Hello, \${user.name}!\`;
67
+ }`}
68
+ />
69
+ ),
70
+ };
71
+
72
+ export const BlockWithLineNumbers: Story = {
73
+ render: () => (
74
+ <CodeBlock
75
+ showLineNumbers
76
+ code={`import { useState } from 'react';
77
+
78
+ export function Counter() {
79
+ const [count, setCount] = useState(0);
80
+
81
+ return (
82
+ <button onClick={() => setCount(count + 1)}>
83
+ Count: {count}
84
+ </button>
85
+ );
86
+ }`}
87
+ language="tsx"
88
+ />
89
+ ),
90
+ };
91
+
92
+ export const BlockWithHighlightedLines: Story = {
93
+ render: () => (
94
+ <CodeBlock
95
+ showLineNumbers
96
+ highlightLines={[4, 5, 6]}
97
+ code={`import { useState } from 'react';
98
+
99
+ export function Counter() {
100
+ const [count, setCount] = useState(0);
101
+ const increment = () => setCount(count + 1);
102
+ const decrement = () => setCount(count - 1);
103
+
104
+ return (
105
+ <div>
106
+ <button onClick={decrement}>-</button>
107
+ <span>{count}</span>
108
+ <button onClick={increment}>+</button>
109
+ </div>
110
+ );
111
+ }`}
112
+ language="tsx"
113
+ filename="Counter.tsx"
114
+ />
115
+ ),
116
+ };
117
+
118
+ export const SnippetDefault: Story = {
119
+ render: () => <Snippet text="npm install @sonance/ui" />,
120
+ };
121
+
122
+ export const SnippetWithoutSymbol: Story = {
123
+ render: () => <Snippet text="pnpm add @sonance/ui" symbol="" />,
124
+ };
125
+
126
+ export const SnippetNoCopy: Story = {
127
+ render: () => <Snippet text="yarn add @sonance/ui" hideCopyButton />,
128
+ };
129
+
130
+ export const InstallCommands: Story = {
131
+ render: () => (
132
+ <div className="space-y-4">
133
+ <div>
134
+ <p className="text-xs text-foreground-muted mb-2">npm</p>
135
+ <Snippet text="npm install @sonance/ui" />
136
+ </div>
137
+ <div>
138
+ <p className="text-xs text-foreground-muted mb-2">pnpm</p>
139
+ <Snippet text="pnpm add @sonance/ui" />
140
+ </div>
141
+ <div>
142
+ <p className="text-xs text-foreground-muted mb-2">yarn</p>
143
+ <Snippet text="yarn add @sonance/ui" />
144
+ </div>
145
+ </div>
146
+ ),
147
+ };
148
+
149
+ export const DocumentationExample: Story = {
150
+ render: () => (
151
+ <div className="max-w-2xl space-y-6">
152
+ <h2 className="text-xl font-semibold text-foreground">Button Component</h2>
153
+
154
+ <p className="text-foreground-secondary">
155
+ Import the <Code>Button</Code> component from the UI library:
156
+ </p>
157
+
158
+ <CodeBlock
159
+ filename="example.tsx"
160
+ language="tsx"
161
+ code={`import { Button } from '@sonance/ui';
162
+
163
+ export function MyComponent() {
164
+ return (
165
+ <Button variant="primary" size="lg">
166
+ Click me
167
+ </Button>
168
+ );
169
+ }`}
170
+ />
171
+
172
+ <h3 className="text-lg font-medium text-foreground">Props</h3>
173
+
174
+ <p className="text-foreground-secondary">
175
+ The <Code variant="primary">variant</Code> prop accepts{' '}
176
+ <Code>primary</Code>, <Code>secondary</Code>, <Code>ghost</Code>, or{' '}
177
+ <Code>inverted</Code>.
178
+ </p>
179
+ </div>
180
+ ),
181
+ };
182
+
183
+ export const AllExamples: Story = {
184
+ render: () => (
185
+ <div className="space-y-8 max-w-2xl">
186
+ <div>
187
+ <h3 className="text-sm font-medium text-foreground mb-2">Inline Code</h3>
188
+ <p className="text-foreground-secondary">
189
+ Default: <Code>const x = 1</Code> | Primary: <Code variant="primary">useState</Code>
190
+ </p>
191
+ </div>
192
+
193
+ <div>
194
+ <h3 className="text-sm font-medium text-foreground mb-2">Code Block</h3>
195
+ <CodeBlock
196
+ code={`const greeting = "Hello, World!";
197
+ console.log(greeting);`}
198
+ />
199
+ </div>
200
+
201
+ <div>
202
+ <h3 className="text-sm font-medium text-foreground mb-2">Snippet</h3>
203
+ <Snippet text="npm install @sonance/ui" />
204
+ </div>
205
+ </div>
206
+ ),
207
+ };
208
+
209
+ // Responsive Matrix - Mobile, Tablet, Desktop
210
+ export const ResponsiveMatrix: Story = {
211
+ render: () => (
212
+ <div className="space-y-8">
213
+ {/* Mobile */}
214
+ <div>
215
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
216
+ <div className="w-[375px] border border-dashed border-border p-4 space-y-4">
217
+ <p className="text-foreground-secondary text-sm">
218
+ Use <Code>npm install</Code> to install.
219
+ </p>
220
+ <Snippet text="npm install @sonance/ui" />
221
+ </div>
222
+ </div>
223
+ {/* Tablet */}
224
+ <div>
225
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
226
+ <div className="w-[768px] border border-dashed border-border p-4">
227
+ <CodeBlock
228
+ code={`import { Button } from '@sonance/ui';
229
+
230
+ export function App() {
231
+ return <Button>Click me</Button>;
232
+ }`}
233
+ language="tsx"
234
+ />
235
+ </div>
236
+ </div>
237
+ {/* Desktop */}
238
+ <div>
239
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
240
+ <div className="w-[1280px] border border-dashed border-border p-4">
241
+ <CodeBlock
242
+ filename="component.tsx"
243
+ showLineNumbers
244
+ code={`import { useState } from 'react';
245
+ import { Button, Card, Input } from '@sonance/ui';
246
+
247
+ export function ContactForm() {
248
+ const [name, setName] = useState('');
249
+ const [email, setEmail] = useState('');
250
+
251
+ return (
252
+ <Card>
253
+ <Input label="Name" value={name} onChange={(e) => setName(e.target.value)} />
254
+ <Input label="Email" value={email} onChange={(e) => setEmail(e.target.value)} />
255
+ <Button>Submit</Button>
256
+ </Card>
257
+ );
258
+ }`}
259
+ language="tsx"
260
+ />
261
+ </div>
262
+ </div>
263
+ </div>
264
+ ),
265
+ };