@shipfox/react-ui 0.1.0 → 0.2.0

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.
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/runnertmp/_work/tooling/tooling/.npmrc". Failed to replace env in config: ${NPM_ACCESS_TOKEN}
2
2
 
3
- > @shipfox/react-ui@0.1.0 build /runnertmp/_work/tooling/tooling/libs/react/ui
3
+ > @shipfox/react-ui@0.2.0 build /runnertmp/_work/tooling/tooling/libs/react/ui
4
4
  > swc
5
5
 
6
- Successfully compiled: 45 files with swc (307.49ms)
6
+ Successfully compiled: 48 files with swc (555.95ms)
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/runnertmp/_work/tooling/tooling/.npmrc". Failed to replace env in config: ${NPM_ACCESS_TOKEN}
2
2
 
3
- > @shipfox/react-ui@0.1.0 check /runnertmp/_work/tooling/tooling/libs/react/ui
3
+ > @shipfox/react-ui@0.2.0 check /runnertmp/_work/tooling/tooling/libs/react/ui
4
4
  > biome --fix
5
5
 
6
- Checked 61 files in 482ms. No fixes applied.
6
+ Checked 64 files in 542ms. No fixes applied.
@@ -1,5 +1,5 @@
1
1
   WARN  Issue while reading "/runnertmp/_work/tooling/tooling/.npmrc". Failed to replace env in config: ${NPM_ACCESS_TOKEN}
2
2
 
3
- > @shipfox/react-ui@0.1.0 type /runnertmp/_work/tooling/tooling/libs/react/ui
3
+ > @shipfox/react-ui@0.2.0 type /runnertmp/_work/tooling/tooling/libs/react/ui
4
4
  > tsc-emit
5
5
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @shipfox/react-ui
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d2f5795: Add textarea component
8
+
3
9
  ## 0.1.0
4
10
 
5
11
  ### Minor Changes
@@ -1,5 +1,6 @@
1
1
  export * from './button';
2
2
  export * from './icon';
3
+ export * from './textarea';
3
4
  export * from './theme-provider';
4
5
  export * from './typography';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC"}
@@ -1,5 +1,6 @@
1
1
  export * from './button.js';
2
2
  export * from './icon/index.js';
3
+ export * from './textarea/index.js';
3
4
  export * from './theme-provider.js';
4
5
  export * from './typography/index.js';
5
6
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/index.ts"],"sourcesContent":["export * from './button';\nexport * from './icon';\nexport * from './theme-provider';\nexport * from './typography';\n"],"names":[],"mappings":"AAAA,cAAc,WAAW;AACzB,cAAc,SAAS;AACvB,cAAc,mBAAmB;AACjC,cAAc,eAAe"}
1
+ {"version":3,"sources":["../../src/components/index.ts"],"sourcesContent":["export * from './button';\nexport * from './icon';\nexport * from './textarea';\nexport * from './theme-provider';\nexport * from './typography';\n"],"names":[],"mappings":"AAAA,cAAc,WAAW;AACzB,cAAc,SAAS;AACvB,cAAc,aAAa;AAC3B,cAAc,mBAAmB;AACjC,cAAc,eAAe"}
@@ -0,0 +1,2 @@
1
+ export * from './textarea';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/textarea/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './textarea.js';
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/textarea/index.ts"],"sourcesContent":["export * from './textarea';\n"],"names":[],"mappings":"AAAA,cAAc,aAAa"}
@@ -0,0 +1,10 @@
1
+ import { type VariantProps } from 'class-variance-authority';
2
+ import type { ComponentProps } from 'react';
3
+ export declare const textareaVariants: (props?: ({
4
+ variant?: "base" | "component" | null | undefined;
5
+ size?: "base" | "small" | null | undefined;
6
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
+ type TextareaProps = Omit<ComponentProps<'textarea'>, 'size'> & VariantProps<typeof textareaVariants>;
8
+ export declare function Textarea({ className, variant, size, ...props }: TextareaProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=textarea.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../../src/components/textarea/textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,OAAO,CAAC;AAG1C,eAAO,MAAM,gBAAgB;;;8EAe3B,CAAC;AAEH,KAAK,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,GAC3D,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAExC,wBAAgB,QAAQ,CAAC,EAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,KAAK,EAAC,EAAE,aAAa,2CAiB3E"}
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cva } from 'class-variance-authority';
3
+ import { cn } from '../../utils/cn.js';
4
+ export const textareaVariants = cva('', {
5
+ variants: {
6
+ variant: {
7
+ base: 'bg-background-field-base',
8
+ component: 'bg-background-field-component'
9
+ },
10
+ size: {
11
+ base: 'py-6',
12
+ small: 'py-4'
13
+ }
14
+ },
15
+ defaultVariants: {
16
+ variant: 'base',
17
+ size: 'base'
18
+ }
19
+ });
20
+ export function Textarea({ className, variant, size, ...props }) {
21
+ return /*#__PURE__*/ _jsx("textarea", {
22
+ "data-slot": "textarea",
23
+ className: cn('textarea-resize-custom placeholder:text-foreground-neutral-muted w-full min-w-0 rounded-6 px-8 pr-24 text-sm leading-20 text-foreground-neutral-base shadow-border-base transition-[color,box-shadow] outline-none', 'hover:bg-background-field-hover', 'selection:bg-background-accent-neutral-soft selection:text-foreground-neutral-on-inverted', 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-background-neutral-disabled disabled:shadow-none disabled:text-foreground-neutral-disabled', 'focus-visible:shadow-border-interactive-with-active', 'aria-invalid:shadow-border-error', textareaVariants({
24
+ variant,
25
+ size
26
+ }), className),
27
+ ...props
28
+ });
29
+ }
30
+
31
+ //# sourceMappingURL=textarea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/textarea/textarea.tsx"],"sourcesContent":["import {cva, type VariantProps} from 'class-variance-authority';\nimport type {ComponentProps} from 'react';\nimport {cn} from 'utils/cn';\n\nexport const textareaVariants = cva('', {\n variants: {\n variant: {\n base: 'bg-background-field-base',\n component: 'bg-background-field-component',\n },\n size: {\n base: 'py-6',\n small: 'py-4',\n },\n },\n defaultVariants: {\n variant: 'base',\n size: 'base',\n },\n});\n\ntype TextareaProps = Omit<ComponentProps<'textarea'>, 'size'> &\n VariantProps<typeof textareaVariants>;\n\nexport function Textarea({className, variant, size, ...props}: TextareaProps) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n 'textarea-resize-custom placeholder:text-foreground-neutral-muted w-full min-w-0 rounded-6 px-8 pr-24 text-sm leading-20 text-foreground-neutral-base shadow-border-base transition-[color,box-shadow] outline-none',\n 'hover:bg-background-field-hover',\n 'selection:bg-background-accent-neutral-soft selection:text-foreground-neutral-on-inverted',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-background-neutral-disabled disabled:shadow-none disabled:text-foreground-neutral-disabled',\n 'focus-visible:shadow-border-interactive-with-active',\n 'aria-invalid:shadow-border-error',\n textareaVariants({variant, size}),\n className,\n )}\n {...props}\n />\n );\n}\n"],"names":["cva","cn","textareaVariants","variants","variant","base","component","size","small","defaultVariants","Textarea","className","props","textarea","data-slot"],"mappings":";AAAA,SAAQA,GAAG,QAA0B,2BAA2B;AAEhE,SAAQC,EAAE,QAAO,WAAW;AAE5B,OAAO,MAAMC,mBAAmBF,IAAI,IAAI;IACtCG,UAAU;QACRC,SAAS;YACPC,MAAM;YACNC,WAAW;QACb;QACAC,MAAM;YACJF,MAAM;YACNG,OAAO;QACT;IACF;IACAC,iBAAiB;QACfL,SAAS;QACTG,MAAM;IACR;AACF,GAAG;AAKH,OAAO,SAASG,SAAS,EAACC,SAAS,EAAEP,OAAO,EAAEG,IAAI,EAAE,GAAGK,OAAqB;IAC1E,qBACE,KAACC;QACCC,aAAU;QACVH,WAAWV,GACT,sNACA,mCACA,6FACA,mKACA,uDACA,oCACAC,iBAAiB;YAACE;YAASG;QAAI,IAC/BI;QAED,GAAGC,KAAK;;AAGf"}
@@ -0,0 +1,333 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Code, Header } from '../../components/typography/index.js';
3
+ import { Textarea } from './textarea.js';
4
+ const meta = {
5
+ title: 'Components/Textarea',
6
+ component: Textarea,
7
+ tags: [
8
+ 'autodocs'
9
+ ],
10
+ argTypes: {
11
+ placeholder: {
12
+ control: 'text'
13
+ },
14
+ disabled: {
15
+ control: 'boolean'
16
+ },
17
+ 'aria-invalid': {
18
+ control: 'boolean'
19
+ },
20
+ rows: {
21
+ control: 'number'
22
+ },
23
+ cols: {
24
+ control: 'number'
25
+ }
26
+ },
27
+ args: {
28
+ placeholder: 'Type something…',
29
+ disabled: false,
30
+ 'aria-invalid': false,
31
+ rows: 4
32
+ }
33
+ };
34
+ export default meta;
35
+ export const Default = {};
36
+ const variants = [
37
+ 'base',
38
+ 'component'
39
+ ];
40
+ const sizes = [
41
+ 'base',
42
+ 'small'
43
+ ];
44
+ export const States = {
45
+ render: (args)=>/*#__PURE__*/ _jsx("div", {
46
+ className: "flex flex-col gap-32",
47
+ children: variants.map((variant)=>sizes.map((size)=>/*#__PURE__*/ _jsxs("div", {
48
+ className: "flex flex-col gap-16",
49
+ children: [
50
+ /*#__PURE__*/ _jsxs(Header, {
51
+ variant: "h3",
52
+ children: [
53
+ variant,
54
+ " ",
55
+ size
56
+ ]
57
+ }),
58
+ /*#__PURE__*/ _jsxs("div", {
59
+ className: "flex flex-col gap-8",
60
+ children: [
61
+ /*#__PURE__*/ _jsx(Code, {
62
+ variant: "label",
63
+ className: "text-foreground-neutral-subtle",
64
+ children: "Default"
65
+ }),
66
+ /*#__PURE__*/ _jsx(Textarea, {
67
+ ...args,
68
+ variant: variant,
69
+ size: size
70
+ })
71
+ ]
72
+ }),
73
+ /*#__PURE__*/ _jsxs("div", {
74
+ className: "flex flex-col gap-8",
75
+ children: [
76
+ /*#__PURE__*/ _jsx(Code, {
77
+ variant: "label",
78
+ className: "text-foreground-neutral-subtle",
79
+ children: "Hover"
80
+ }),
81
+ /*#__PURE__*/ _jsx(Textarea, {
82
+ ...args,
83
+ className: "hover",
84
+ variant: variant,
85
+ size: size
86
+ })
87
+ ]
88
+ }),
89
+ /*#__PURE__*/ _jsxs("div", {
90
+ className: "flex flex-col gap-8",
91
+ children: [
92
+ /*#__PURE__*/ _jsx(Code, {
93
+ variant: "label",
94
+ className: "text-foreground-neutral-subtle",
95
+ children: "Active"
96
+ }),
97
+ /*#__PURE__*/ _jsx(Textarea, {
98
+ ...args,
99
+ className: "active",
100
+ defaultValue: "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.",
101
+ variant: variant,
102
+ size: size
103
+ })
104
+ ]
105
+ }),
106
+ /*#__PURE__*/ _jsxs("div", {
107
+ className: "flex flex-col gap-8",
108
+ children: [
109
+ /*#__PURE__*/ _jsx(Code, {
110
+ variant: "label",
111
+ className: "text-foreground-neutral-subtle",
112
+ children: "Focus"
113
+ }),
114
+ /*#__PURE__*/ _jsx(Textarea, {
115
+ ...args,
116
+ className: "focus",
117
+ variant: variant,
118
+ size: size
119
+ })
120
+ ]
121
+ }),
122
+ /*#__PURE__*/ _jsxs("div", {
123
+ className: "flex flex-col gap-8",
124
+ children: [
125
+ /*#__PURE__*/ _jsx(Code, {
126
+ variant: "label",
127
+ className: "text-foreground-neutral-subtle",
128
+ children: "Disabled"
129
+ }),
130
+ /*#__PURE__*/ _jsx(Textarea, {
131
+ ...args,
132
+ disabled: true,
133
+ variant: variant,
134
+ size: size
135
+ })
136
+ ]
137
+ }),
138
+ /*#__PURE__*/ _jsxs("div", {
139
+ className: "flex flex-col gap-8",
140
+ children: [
141
+ /*#__PURE__*/ _jsx(Code, {
142
+ variant: "label",
143
+ className: "text-foreground-neutral-subtle",
144
+ children: "Invalid"
145
+ }),
146
+ /*#__PURE__*/ _jsx(Textarea, {
147
+ ...args,
148
+ "aria-invalid": true,
149
+ variant: variant,
150
+ size: size
151
+ })
152
+ ]
153
+ })
154
+ ]
155
+ }, variant + size)))
156
+ })
157
+ };
158
+ States.parameters = {
159
+ pseudo: {
160
+ hover: '.hover',
161
+ active: '.active',
162
+ focusVisible: '.focus'
163
+ }
164
+ };
165
+ export const Sizes = {
166
+ render: (args)=>/*#__PURE__*/ _jsxs("div", {
167
+ className: "flex flex-col gap-32",
168
+ children: [
169
+ /*#__PURE__*/ _jsxs("div", {
170
+ className: "flex flex-col gap-8",
171
+ children: [
172
+ /*#__PURE__*/ _jsx(Code, {
173
+ variant: "label",
174
+ className: "text-foreground-neutral-subtle",
175
+ children: "Rows: 2"
176
+ }),
177
+ /*#__PURE__*/ _jsx(Textarea, {
178
+ ...args,
179
+ rows: 2
180
+ })
181
+ ]
182
+ }),
183
+ /*#__PURE__*/ _jsxs("div", {
184
+ className: "flex flex-col gap-8",
185
+ children: [
186
+ /*#__PURE__*/ _jsx(Code, {
187
+ variant: "label",
188
+ className: "text-foreground-neutral-subtle",
189
+ children: "Rows: 4 (default)"
190
+ }),
191
+ /*#__PURE__*/ _jsx(Textarea, {
192
+ ...args,
193
+ rows: 4
194
+ })
195
+ ]
196
+ }),
197
+ /*#__PURE__*/ _jsxs("div", {
198
+ className: "flex flex-col gap-8",
199
+ children: [
200
+ /*#__PURE__*/ _jsx(Code, {
201
+ variant: "label",
202
+ className: "text-foreground-neutral-subtle",
203
+ children: "Rows: 6"
204
+ }),
205
+ /*#__PURE__*/ _jsx(Textarea, {
206
+ ...args,
207
+ rows: 6
208
+ })
209
+ ]
210
+ }),
211
+ /*#__PURE__*/ _jsxs("div", {
212
+ className: "flex flex-col gap-8",
213
+ children: [
214
+ /*#__PURE__*/ _jsx(Code, {
215
+ variant: "label",
216
+ className: "text-foreground-neutral-subtle",
217
+ children: "Rows: 10"
218
+ }),
219
+ /*#__PURE__*/ _jsx(Textarea, {
220
+ ...args,
221
+ rows: 10
222
+ })
223
+ ]
224
+ })
225
+ ]
226
+ })
227
+ };
228
+ export const DesignMock = {
229
+ render: ()=>{
230
+ const variants = [
231
+ {
232
+ key: 'base',
233
+ label: 'Primary'
234
+ },
235
+ {
236
+ key: 'component',
237
+ label: 'Secondary'
238
+ }
239
+ ];
240
+ const states = [
241
+ {
242
+ name: 'Default',
243
+ props: {}
244
+ },
245
+ {
246
+ name: 'Hover',
247
+ props: {
248
+ className: 'hover'
249
+ }
250
+ },
251
+ {
252
+ name: 'Focus',
253
+ props: {
254
+ className: 'focus'
255
+ }
256
+ },
257
+ {
258
+ name: 'Filled',
259
+ props: {
260
+ defaultValue: 'Placeholder'
261
+ }
262
+ },
263
+ {
264
+ name: 'Filled Hover',
265
+ props: {
266
+ defaultValue: 'Placeholder',
267
+ className: 'hover'
268
+ }
269
+ },
270
+ {
271
+ name: 'Disabled',
272
+ props: {
273
+ disabled: true
274
+ }
275
+ },
276
+ {
277
+ name: 'Error',
278
+ props: {
279
+ 'aria-invalid': true
280
+ }
281
+ }
282
+ ];
283
+ return /*#__PURE__*/ _jsxs("div", {
284
+ className: "flex flex-col gap-32 pb-64 pt-32 px-32",
285
+ children: [
286
+ /*#__PURE__*/ _jsx(Header, {
287
+ variant: "h3",
288
+ className: "text-foreground-neutral-subtle",
289
+ children: "TEXT AREA"
290
+ }),
291
+ /*#__PURE__*/ _jsx("div", {
292
+ className: "flex flex-row gap-32",
293
+ children: variants.map((variant)=>/*#__PURE__*/ _jsx("div", {
294
+ className: "flex flex-col gap-32",
295
+ children: states.map((state)=>/*#__PURE__*/ _jsxs("div", {
296
+ className: "flex flex-col gap-8",
297
+ children: [
298
+ /*#__PURE__*/ _jsxs(Code, {
299
+ variant: "label",
300
+ className: "text-foreground-neutral-subtle",
301
+ children: [
302
+ "Size=Base (32), State=",
303
+ state.name,
304
+ ", Color=",
305
+ variant.label
306
+ ]
307
+ }),
308
+ /*#__PURE__*/ _jsx("div", {
309
+ className: "w-[280px]",
310
+ children: /*#__PURE__*/ _jsx(Textarea, {
311
+ placeholder: "Placeholder",
312
+ variant: variant.key,
313
+ size: "base",
314
+ rows: 2,
315
+ ...state.props
316
+ })
317
+ })
318
+ ]
319
+ }, state.name))
320
+ }, variant.key))
321
+ })
322
+ ]
323
+ });
324
+ }
325
+ };
326
+ DesignMock.parameters = {
327
+ pseudo: {
328
+ hover: '.hover',
329
+ focusVisible: '.focus'
330
+ }
331
+ };
332
+
333
+ //# sourceMappingURL=textarea.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/textarea/textarea.stories.tsx"],"sourcesContent":["import type {Meta, StoryObj} from '@storybook/react';\nimport {Code, Header} from 'components/typography';\nimport {Textarea} from './textarea';\n\nconst meta = {\n title: 'Components/Textarea',\n component: Textarea,\n tags: ['autodocs'],\n argTypes: {\n placeholder: {control: 'text'},\n disabled: {control: 'boolean'},\n 'aria-invalid': {control: 'boolean'},\n rows: {control: 'number'},\n cols: {control: 'number'},\n },\n args: {\n placeholder: 'Type something…',\n disabled: false,\n 'aria-invalid': false,\n rows: 4,\n },\n} satisfies Meta<typeof Textarea>;\n\nexport default meta;\n\ntype Story = StoryObj<typeof meta>;\n\nexport const Default: Story = {};\n\nconst variants = ['base', 'component'] as const;\nconst sizes = ['base', 'small'] as const;\n\nexport const States: Story = {\n render: (args) => (\n <div className=\"flex flex-col gap-32\">\n {variants.map((variant) =>\n sizes.map((size) => (\n <div key={variant + size} className=\"flex flex-col gap-16\">\n <Header variant=\"h3\">\n {variant} {size}\n </Header>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Default\n </Code>\n\n <Textarea {...args} variant={variant} size={size} />\n </div>\n\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Hover\n </Code>\n\n <Textarea {...args} className=\"hover\" variant={variant} size={size} />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Active\n </Code>\n\n <Textarea\n {...args}\n className=\"active\"\n defaultValue=\"The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\"\n variant={variant}\n size={size}\n />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Focus\n </Code>\n\n <Textarea {...args} className=\"focus\" variant={variant} size={size} />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Disabled\n </Code>\n\n <Textarea {...args} disabled variant={variant} size={size} />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Invalid\n </Code>\n\n <Textarea {...args} aria-invalid variant={variant} size={size} />\n </div>\n </div>\n )),\n )}\n </div>\n ),\n};\n\nStates.parameters = {\n pseudo: {\n hover: '.hover',\n active: '.active',\n focusVisible: '.focus',\n },\n};\n\nexport const Sizes: Story = {\n render: (args) => (\n <div className=\"flex flex-col gap-32\">\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Rows: 2\n </Code>\n <Textarea {...args} rows={2} />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Rows: 4 (default)\n </Code>\n <Textarea {...args} rows={4} />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Rows: 6\n </Code>\n <Textarea {...args} rows={6} />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Rows: 10\n </Code>\n <Textarea {...args} rows={10} />\n </div>\n </div>\n ),\n};\n\nexport const DesignMock: Story = {\n render: () => {\n const variants = [\n {key: 'base', label: 'Primary'},\n {key: 'component', label: 'Secondary'},\n ] as const;\n const states = [\n {name: 'Default', props: {}},\n {name: 'Hover', props: {className: 'hover'}},\n {name: 'Focus', props: {className: 'focus'}},\n {name: 'Filled', props: {defaultValue: 'Placeholder'}},\n {name: 'Filled Hover', props: {defaultValue: 'Placeholder', className: 'hover'}},\n {name: 'Disabled', props: {disabled: true}},\n {name: 'Error', props: {'aria-invalid': true}},\n ] as const;\n\n return (\n <div className=\"flex flex-col gap-32 pb-64 pt-32 px-32\">\n <Header variant=\"h3\" className=\"text-foreground-neutral-subtle\">\n TEXT AREA\n </Header>\n <div className=\"flex flex-row gap-32\">\n {variants.map((variant) => (\n <div key={variant.key} className=\"flex flex-col gap-32\">\n {states.map((state) => (\n <div key={state.name} className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Size=Base (32), State={state.name}, Color={variant.label}\n </Code>\n <div className=\"w-[280px]\">\n <Textarea\n placeholder=\"Placeholder\"\n variant={variant.key}\n size=\"base\"\n rows={2}\n {...state.props}\n />\n </div>\n </div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n },\n};\n\nDesignMock.parameters = {\n pseudo: {\n hover: '.hover',\n focusVisible: '.focus',\n },\n};\n"],"names":["Code","Header","Textarea","meta","title","component","tags","argTypes","placeholder","control","disabled","rows","cols","args","Default","variants","sizes","States","render","div","className","map","variant","size","defaultValue","aria-invalid","parameters","pseudo","hover","active","focusVisible","Sizes","DesignMock","key","label","states","name","props","state"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/react-ui",
3
3
  "license": "MIT",
4
- "version": "0.1.0",
4
+ "version": "0.2.0",
5
5
  "private": false,
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -60,8 +60,8 @@
60
60
  "@shipfox/swc": "1.2.1",
61
61
  "@shipfox/ts-config": "1.3.5",
62
62
  "@shipfox/typescript": "1.1.2",
63
- "@shipfox/vite": "1.2.1",
64
- "@shipfox/vitest": "1.1.2"
63
+ "@shipfox/vite": "1.2.2",
64
+ "@shipfox/vitest": "1.1.3"
65
65
  },
66
66
  "scripts": {
67
67
  "build": "swc",
@@ -1,4 +1,5 @@
1
1
  export * from './button';
2
2
  export * from './icon';
3
+ export * from './textarea';
3
4
  export * from './theme-provider';
4
5
  export * from './typography';
@@ -0,0 +1 @@
1
+ export * from './textarea';
@@ -0,0 +1,190 @@
1
+ import type {Meta, StoryObj} from '@storybook/react';
2
+ import {Code, Header} from 'components/typography';
3
+ import {Textarea} from './textarea';
4
+
5
+ const meta = {
6
+ title: 'Components/Textarea',
7
+ component: Textarea,
8
+ tags: ['autodocs'],
9
+ argTypes: {
10
+ placeholder: {control: 'text'},
11
+ disabled: {control: 'boolean'},
12
+ 'aria-invalid': {control: 'boolean'},
13
+ rows: {control: 'number'},
14
+ cols: {control: 'number'},
15
+ },
16
+ args: {
17
+ placeholder: 'Type something…',
18
+ disabled: false,
19
+ 'aria-invalid': false,
20
+ rows: 4,
21
+ },
22
+ } satisfies Meta<typeof Textarea>;
23
+
24
+ export default meta;
25
+
26
+ type Story = StoryObj<typeof meta>;
27
+
28
+ export const Default: Story = {};
29
+
30
+ const variants = ['base', 'component'] as const;
31
+ const sizes = ['base', 'small'] as const;
32
+
33
+ export const States: Story = {
34
+ render: (args) => (
35
+ <div className="flex flex-col gap-32">
36
+ {variants.map((variant) =>
37
+ sizes.map((size) => (
38
+ <div key={variant + size} className="flex flex-col gap-16">
39
+ <Header variant="h3">
40
+ {variant} {size}
41
+ </Header>
42
+ <div className="flex flex-col gap-8">
43
+ <Code variant="label" className="text-foreground-neutral-subtle">
44
+ Default
45
+ </Code>
46
+
47
+ <Textarea {...args} variant={variant} size={size} />
48
+ </div>
49
+
50
+ <div className="flex flex-col gap-8">
51
+ <Code variant="label" className="text-foreground-neutral-subtle">
52
+ Hover
53
+ </Code>
54
+
55
+ <Textarea {...args} className="hover" variant={variant} size={size} />
56
+ </div>
57
+ <div className="flex flex-col gap-8">
58
+ <Code variant="label" className="text-foreground-neutral-subtle">
59
+ Active
60
+ </Code>
61
+
62
+ <Textarea
63
+ {...args}
64
+ className="active"
65
+ defaultValue="The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog."
66
+ variant={variant}
67
+ size={size}
68
+ />
69
+ </div>
70
+ <div className="flex flex-col gap-8">
71
+ <Code variant="label" className="text-foreground-neutral-subtle">
72
+ Focus
73
+ </Code>
74
+
75
+ <Textarea {...args} className="focus" variant={variant} size={size} />
76
+ </div>
77
+ <div className="flex flex-col gap-8">
78
+ <Code variant="label" className="text-foreground-neutral-subtle">
79
+ Disabled
80
+ </Code>
81
+
82
+ <Textarea {...args} disabled variant={variant} size={size} />
83
+ </div>
84
+ <div className="flex flex-col gap-8">
85
+ <Code variant="label" className="text-foreground-neutral-subtle">
86
+ Invalid
87
+ </Code>
88
+
89
+ <Textarea {...args} aria-invalid variant={variant} size={size} />
90
+ </div>
91
+ </div>
92
+ )),
93
+ )}
94
+ </div>
95
+ ),
96
+ };
97
+
98
+ States.parameters = {
99
+ pseudo: {
100
+ hover: '.hover',
101
+ active: '.active',
102
+ focusVisible: '.focus',
103
+ },
104
+ };
105
+
106
+ export const Sizes: Story = {
107
+ render: (args) => (
108
+ <div className="flex flex-col gap-32">
109
+ <div className="flex flex-col gap-8">
110
+ <Code variant="label" className="text-foreground-neutral-subtle">
111
+ Rows: 2
112
+ </Code>
113
+ <Textarea {...args} rows={2} />
114
+ </div>
115
+ <div className="flex flex-col gap-8">
116
+ <Code variant="label" className="text-foreground-neutral-subtle">
117
+ Rows: 4 (default)
118
+ </Code>
119
+ <Textarea {...args} rows={4} />
120
+ </div>
121
+ <div className="flex flex-col gap-8">
122
+ <Code variant="label" className="text-foreground-neutral-subtle">
123
+ Rows: 6
124
+ </Code>
125
+ <Textarea {...args} rows={6} />
126
+ </div>
127
+ <div className="flex flex-col gap-8">
128
+ <Code variant="label" className="text-foreground-neutral-subtle">
129
+ Rows: 10
130
+ </Code>
131
+ <Textarea {...args} rows={10} />
132
+ </div>
133
+ </div>
134
+ ),
135
+ };
136
+
137
+ export const DesignMock: Story = {
138
+ render: () => {
139
+ const variants = [
140
+ {key: 'base', label: 'Primary'},
141
+ {key: 'component', label: 'Secondary'},
142
+ ] as const;
143
+ const states = [
144
+ {name: 'Default', props: {}},
145
+ {name: 'Hover', props: {className: 'hover'}},
146
+ {name: 'Focus', props: {className: 'focus'}},
147
+ {name: 'Filled', props: {defaultValue: 'Placeholder'}},
148
+ {name: 'Filled Hover', props: {defaultValue: 'Placeholder', className: 'hover'}},
149
+ {name: 'Disabled', props: {disabled: true}},
150
+ {name: 'Error', props: {'aria-invalid': true}},
151
+ ] as const;
152
+
153
+ return (
154
+ <div className="flex flex-col gap-32 pb-64 pt-32 px-32">
155
+ <Header variant="h3" className="text-foreground-neutral-subtle">
156
+ TEXT AREA
157
+ </Header>
158
+ <div className="flex flex-row gap-32">
159
+ {variants.map((variant) => (
160
+ <div key={variant.key} className="flex flex-col gap-32">
161
+ {states.map((state) => (
162
+ <div key={state.name} className="flex flex-col gap-8">
163
+ <Code variant="label" className="text-foreground-neutral-subtle">
164
+ Size=Base (32), State={state.name}, Color={variant.label}
165
+ </Code>
166
+ <div className="w-[280px]">
167
+ <Textarea
168
+ placeholder="Placeholder"
169
+ variant={variant.key}
170
+ size="base"
171
+ rows={2}
172
+ {...state.props}
173
+ />
174
+ </div>
175
+ </div>
176
+ ))}
177
+ </div>
178
+ ))}
179
+ </div>
180
+ </div>
181
+ );
182
+ },
183
+ };
184
+
185
+ DesignMock.parameters = {
186
+ pseudo: {
187
+ hover: '.hover',
188
+ focusVisible: '.focus',
189
+ },
190
+ };
@@ -0,0 +1,42 @@
1
+ import {cva, type VariantProps} from 'class-variance-authority';
2
+ import type {ComponentProps} from 'react';
3
+ import {cn} from 'utils/cn';
4
+
5
+ export const textareaVariants = cva('', {
6
+ variants: {
7
+ variant: {
8
+ base: 'bg-background-field-base',
9
+ component: 'bg-background-field-component',
10
+ },
11
+ size: {
12
+ base: 'py-6',
13
+ small: 'py-4',
14
+ },
15
+ },
16
+ defaultVariants: {
17
+ variant: 'base',
18
+ size: 'base',
19
+ },
20
+ });
21
+
22
+ type TextareaProps = Omit<ComponentProps<'textarea'>, 'size'> &
23
+ VariantProps<typeof textareaVariants>;
24
+
25
+ export function Textarea({className, variant, size, ...props}: TextareaProps) {
26
+ return (
27
+ <textarea
28
+ data-slot="textarea"
29
+ className={cn(
30
+ 'textarea-resize-custom placeholder:text-foreground-neutral-muted w-full min-w-0 rounded-6 px-8 pr-24 text-sm leading-20 text-foreground-neutral-base shadow-border-base transition-[color,box-shadow] outline-none',
31
+ 'hover:bg-background-field-hover',
32
+ 'selection:bg-background-accent-neutral-soft selection:text-foreground-neutral-on-inverted',
33
+ 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-background-neutral-disabled disabled:shadow-none disabled:text-foreground-neutral-disabled',
34
+ 'focus-visible:shadow-border-interactive-with-active',
35
+ 'aria-invalid:shadow-border-error',
36
+ textareaVariants({variant, size}),
37
+ className,
38
+ )}
39
+ {...props}
40
+ />
41
+ );
42
+ }