@shipfox/react-ui 0.0.1 → 0.1.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.0.1 build /runnertmp/_work/tooling/tooling/libs/react/ui
3
+ > @shipfox/react-ui@0.1.0 build /runnertmp/_work/tooling/tooling/libs/react/ui
4
4
  > swc
5
5
 
6
- Successfully compiled: 43 files with swc (174.16ms)
6
+ Successfully compiled: 45 files with swc (307.49ms)
@@ -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.0.1 check /runnertmp/_work/tooling/tooling/libs/react/ui
3
+ > @shipfox/react-ui@0.1.0 check /runnertmp/_work/tooling/tooling/libs/react/ui
4
4
  > biome --fix
5
5
 
6
- Checked 59 files in 269ms. No fixes applied.
6
+ Checked 61 files in 482ms. 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.0.1 type /runnertmp/_work/tooling/tooling/libs/react/ui
3
+ > @shipfox/react-ui@0.1.0 type /runnertmp/_work/tooling/tooling/libs/react/ui
4
4
  > tsc-emit
5
5
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @shipfox/react-ui
2
2
 
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - cd386f2: Add Input component
8
+
9
+ ### Patch Changes
10
+
11
+ - 674ecbb: Add README for all packages
12
+
3
13
  ## 0.0.1
4
14
 
5
15
  ### Patch Changes
package/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Shipfox Design System
2
+
3
+ The Shipfox Design System is the core of the [Shipfox](https://www.shipfox.io/) UI grammar. It contains all the React components which are the building blocks of our front-end projects.
4
+
5
+ ## Installation
6
+
7
+ ### Installation
8
+
9
+ ```bash
10
+ pnpm add @shipfox/react-ui
11
+ # or
12
+ yarn add @shipfox/react-ui
13
+ # or
14
+ npm install @shipfox/react-ui
15
+ ```
16
+
17
+ ## Storybook
18
+
19
+ The storybook is [publicly accessible online](react-ui.shipfox.vercel.app).
20
+
21
+ You can also launch it locally by running `pnpm storybook` from within this package's directory.
@@ -0,0 +1,10 @@
1
+ import { type VariantProps } from 'class-variance-authority';
2
+ import type { ComponentProps } from 'react';
3
+ export declare const inputVariants: (props?: ({
4
+ variant?: "base" | "component" | null | undefined;
5
+ size?: "base" | "small" | null | undefined;
6
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
+ type InputProps = Omit<ComponentProps<'input'>, 'size'> & VariantProps<typeof inputVariants>;
8
+ export declare function Input({ className, type, variant, size, ...props }: InputProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/components/input.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,OAAO,CAAC;AAG1C,eAAO,MAAM,aAAa;;;8EAexB,CAAC;AAEH,KAAK,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC;AAE7F,wBAAgB,KAAK,CAAC,EAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,KAAK,EAAC,EAAE,UAAU,2CAmB3E"}
@@ -0,0 +1,32 @@
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 inputVariants = 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 Input({ className, type, variant, size, ...props }) {
21
+ return /*#__PURE__*/ _jsx("input", {
22
+ type: type,
23
+ "data-slot": "input",
24
+ className: cn('placeholder:text-foreground-neutral-muted w-full min-w-0 rounded-6 px-8 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', 'file:text-foreground-neutral-base file:inline-flex file:font-medium', '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', inputVariants({
25
+ variant,
26
+ size
27
+ }), className),
28
+ ...props
29
+ });
30
+ }
31
+
32
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/input.tsx"],"sourcesContent":["import {cva, type VariantProps} from 'class-variance-authority';\nimport type {ComponentProps} from 'react';\nimport {cn} from 'utils/cn';\n\nexport const inputVariants = 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 InputProps = Omit<ComponentProps<'input'>, 'size'> & VariantProps<typeof inputVariants>;\n\nexport function Input({className, type, variant, size, ...props}: InputProps) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n 'placeholder:text-foreground-neutral-muted w-full min-w-0 rounded-6 px-8 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 'file:text-foreground-neutral-base file:inline-flex file:font-medium',\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 inputVariants({variant, size}),\n className,\n )}\n {...props}\n />\n );\n}\n"],"names":["cva","cn","inputVariants","variants","variant","base","component","size","small","defaultVariants","Input","className","type","props","input","data-slot"],"mappings":";AAAA,SAAQA,GAAG,QAA0B,2BAA2B;AAEhE,SAAQC,EAAE,QAAO,WAAW;AAE5B,OAAO,MAAMC,gBAAgBF,IAAI,IAAI;IACnCG,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;AAIH,OAAO,SAASG,MAAM,EAACC,SAAS,EAAEC,IAAI,EAAER,OAAO,EAAEG,IAAI,EAAE,GAAGM,OAAkB;IAC1E,qBACE,KAACC;QACCF,MAAMA;QACNG,aAAU;QACVJ,WAAWV,GACT,yLACA,mCACA,6FACA,uEACA,mKACA,uDACA,oCACAC,cAAc;YAACE;YAASG;QAAI,IAC5BI;QAED,GAAGE,KAAK;;AAGf"}
@@ -0,0 +1,199 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Code, Header } from '../components/typography/index.js';
3
+ import { Input } from './input.js';
4
+ const typeOptions = [
5
+ 'text',
6
+ 'email',
7
+ 'password',
8
+ 'number',
9
+ 'search',
10
+ 'url',
11
+ 'tel',
12
+ 'date',
13
+ 'time',
14
+ 'datetime-local',
15
+ 'month',
16
+ 'week',
17
+ 'color',
18
+ 'file'
19
+ ];
20
+ const meta = {
21
+ title: 'Components/Input',
22
+ component: Input,
23
+ tags: [
24
+ 'autodocs'
25
+ ],
26
+ argTypes: {
27
+ type: {
28
+ control: 'select',
29
+ options: typeOptions
30
+ },
31
+ placeholder: {
32
+ control: 'text'
33
+ },
34
+ disabled: {
35
+ control: 'boolean'
36
+ },
37
+ 'aria-invalid': {
38
+ control: 'boolean'
39
+ }
40
+ },
41
+ args: {
42
+ type: 'text',
43
+ placeholder: 'Type something…',
44
+ disabled: false,
45
+ 'aria-invalid': false
46
+ }
47
+ };
48
+ export default meta;
49
+ export const Default = {};
50
+ const variants = [
51
+ 'base',
52
+ 'component'
53
+ ];
54
+ const sizes = [
55
+ 'base',
56
+ 'small'
57
+ ];
58
+ export const States = {
59
+ render: (args)=>/*#__PURE__*/ _jsx("div", {
60
+ className: "flex flex-col gap-32",
61
+ children: variants.map((variant)=>sizes.map((size)=>/*#__PURE__*/ _jsxs("div", {
62
+ className: "flex flex-col gap-16",
63
+ children: [
64
+ /*#__PURE__*/ _jsxs(Header, {
65
+ variant: "h3",
66
+ children: [
67
+ variant,
68
+ " ",
69
+ size
70
+ ]
71
+ }),
72
+ /*#__PURE__*/ _jsxs("div", {
73
+ className: "flex flex-col gap-8",
74
+ children: [
75
+ /*#__PURE__*/ _jsx(Code, {
76
+ variant: "label",
77
+ className: "text-foreground-neutral-subtle",
78
+ children: "Default"
79
+ }),
80
+ /*#__PURE__*/ _jsx(Input, {
81
+ ...args,
82
+ variant: variant,
83
+ size: size
84
+ })
85
+ ]
86
+ }),
87
+ /*#__PURE__*/ _jsxs("div", {
88
+ className: "flex flex-col gap-8",
89
+ children: [
90
+ /*#__PURE__*/ _jsx(Code, {
91
+ variant: "label",
92
+ className: "text-foreground-neutral-subtle",
93
+ children: "Hover"
94
+ }),
95
+ /*#__PURE__*/ _jsx(Input, {
96
+ ...args,
97
+ className: "hover",
98
+ variant: variant,
99
+ size: size
100
+ })
101
+ ]
102
+ }),
103
+ /*#__PURE__*/ _jsxs("div", {
104
+ className: "flex flex-col gap-8",
105
+ children: [
106
+ /*#__PURE__*/ _jsx(Code, {
107
+ variant: "label",
108
+ className: "text-foreground-neutral-subtle",
109
+ children: "Active"
110
+ }),
111
+ /*#__PURE__*/ _jsx(Input, {
112
+ ...args,
113
+ className: "active",
114
+ defaultValue: "The quick brown fox jumps over the lazy dog",
115
+ variant: variant,
116
+ size: size
117
+ })
118
+ ]
119
+ }),
120
+ /*#__PURE__*/ _jsxs("div", {
121
+ className: "flex flex-col gap-8",
122
+ children: [
123
+ /*#__PURE__*/ _jsx(Code, {
124
+ variant: "label",
125
+ className: "text-foreground-neutral-subtle",
126
+ children: "Focus"
127
+ }),
128
+ /*#__PURE__*/ _jsx(Input, {
129
+ ...args,
130
+ className: "focus",
131
+ variant: variant,
132
+ size: size
133
+ })
134
+ ]
135
+ }),
136
+ /*#__PURE__*/ _jsxs("div", {
137
+ className: "flex flex-col gap-8",
138
+ children: [
139
+ /*#__PURE__*/ _jsx(Code, {
140
+ variant: "label",
141
+ className: "text-foreground-neutral-subtle",
142
+ children: "Disabled"
143
+ }),
144
+ /*#__PURE__*/ _jsx(Input, {
145
+ ...args,
146
+ disabled: true,
147
+ variant: variant,
148
+ size: size
149
+ })
150
+ ]
151
+ }),
152
+ /*#__PURE__*/ _jsxs("div", {
153
+ className: "flex flex-col gap-8",
154
+ children: [
155
+ /*#__PURE__*/ _jsx(Code, {
156
+ variant: "label",
157
+ className: "text-foreground-neutral-subtle",
158
+ children: "Invalid"
159
+ }),
160
+ /*#__PURE__*/ _jsx(Input, {
161
+ ...args,
162
+ "aria-invalid": true,
163
+ variant: variant,
164
+ size: size
165
+ })
166
+ ]
167
+ })
168
+ ]
169
+ }, variant + size)))
170
+ })
171
+ };
172
+ States.parameters = {
173
+ pseudo: {
174
+ hover: '.hover',
175
+ active: '.active',
176
+ focusVisible: '.focus'
177
+ }
178
+ };
179
+ export const Types = {
180
+ render: (args)=>/*#__PURE__*/ _jsx("div", {
181
+ className: "flex flex-col gap-32",
182
+ children: typeOptions.map((t)=>/*#__PURE__*/ _jsxs("div", {
183
+ className: "flex flex-col gap-8",
184
+ children: [
185
+ /*#__PURE__*/ _jsx(Code, {
186
+ variant: "label",
187
+ className: "text-foreground-neutral-subtle",
188
+ children: t
189
+ }),
190
+ /*#__PURE__*/ _jsx(Input, {
191
+ ...args,
192
+ type: t
193
+ })
194
+ ]
195
+ }, t))
196
+ })
197
+ };
198
+
199
+ //# sourceMappingURL=input.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/input.stories.tsx"],"sourcesContent":["import type {Meta, StoryObj} from '@storybook/react';\nimport {Code, Header} from 'components/typography';\nimport {Input} from './input';\n\nconst typeOptions = [\n 'text',\n 'email',\n 'password',\n 'number',\n 'search',\n 'url',\n 'tel',\n 'date',\n 'time',\n 'datetime-local',\n 'month',\n 'week',\n 'color',\n 'file',\n] as const;\n\nconst meta = {\n title: 'Components/Input',\n component: Input,\n tags: ['autodocs'],\n argTypes: {\n type: {\n control: 'select',\n options: typeOptions,\n },\n placeholder: {control: 'text'},\n disabled: {control: 'boolean'},\n 'aria-invalid': {control: 'boolean'},\n },\n args: {\n type: 'text',\n placeholder: 'Type something…',\n disabled: false,\n 'aria-invalid': false,\n },\n} satisfies Meta<typeof Input>;\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 <Input {...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 <Input {...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 <Input\n {...args}\n className=\"active\"\n defaultValue=\"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 <Input {...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 <Input {...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 <Input {...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 Types: Story = {\n render: (args) => (\n <div className=\"flex flex-col gap-32\">\n {typeOptions.map((t) => (\n <div key={t} className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n {t}\n </Code>\n <Input {...args} type={t} />\n </div>\n ))}\n </div>\n ),\n};\n"],"names":["Code","Header","Input","typeOptions","meta","title","component","tags","argTypes","type","control","options","placeholder","disabled","args","Default","variants","sizes","States","render","div","className","map","variant","size","defaultValue","aria-invalid","parameters","pseudo","hover","active","focusVisible","Types","t"],"mappings":";AACA,SAAQA,IAAI,EAAEC,MAAM,QAAO,wBAAwB;AACnD,SAAQC,KAAK,QAAO,UAAU;AAE9B,MAAMC,cAAc;IAClB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,MAAMC,OAAO;IACXC,OAAO;IACPC,WAAWJ;IACXK,MAAM;QAAC;KAAW;IAClBC,UAAU;QACRC,MAAM;YACJC,SAAS;YACTC,SAASR;QACX;QACAS,aAAa;YAACF,SAAS;QAAM;QAC7BG,UAAU;YAACH,SAAS;QAAS;QAC7B,gBAAgB;YAACA,SAAS;QAAS;IACrC;IACAI,MAAM;QACJL,MAAM;QACNG,aAAa;QACbC,UAAU;QACV,gBAAgB;IAClB;AACF;AAEA,eAAeT,KAAK;AAIpB,OAAO,MAAMW,UAAiB,CAAC,EAAE;AAEjC,MAAMC,WAAW;IAAC;IAAQ;CAAY;AACtC,MAAMC,QAAQ;IAAC;IAAQ;CAAQ;AAE/B,OAAO,MAAMC,SAAgB;IAC3BC,QAAQ,CAACL,qBACP,KAACM;YAAIC,WAAU;sBACZL,SAASM,GAAG,CAAC,CAACC,UACbN,MAAMK,GAAG,CAAC,CAACE,qBACT,MAACJ;wBAAyBC,WAAU;;0CAClC,MAACpB;gCAAOsB,SAAQ;;oCACbA;oCAAQ;oCAAEC;;;0CAEb,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCAAO,GAAGY,IAAI;wCAAES,SAASA;wCAASC,MAAMA;;;;0CAG3C,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCAAO,GAAGY,IAAI;wCAAEO,WAAU;wCAAQE,SAASA;wCAASC,MAAMA;;;;0CAE7D,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCACE,GAAGY,IAAI;wCACRO,WAAU;wCACVI,cAAa;wCACbF,SAASA;wCACTC,MAAMA;;;;0CAGV,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCAAO,GAAGY,IAAI;wCAAEO,WAAU;wCAAQE,SAASA;wCAASC,MAAMA;;;;0CAE7D,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCAAO,GAAGY,IAAI;wCAAED,QAAQ;wCAACU,SAASA;wCAASC,MAAMA;;;;0CAEpD,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCAAO,GAAGY,IAAI;wCAAEY,cAAY;wCAACH,SAASA;wCAASC,MAAMA;;;;;uBAnDhDD,UAAUC;;AA0D9B,EAAE;AAEFN,OAAOS,UAAU,GAAG;IAClBC,QAAQ;QACNC,OAAO;QACPC,QAAQ;QACRC,cAAc;IAChB;AACF;AAEA,OAAO,MAAMC,QAAe;IAC1Bb,QAAQ,CAACL,qBACP,KAACM;YAAIC,WAAU;sBACZlB,YAAYmB,GAAG,CAAC,CAACW,kBAChB,MAACb;oBAAYC,WAAU;;sCACrB,KAACrB;4BAAKuB,SAAQ;4BAAQF,WAAU;sCAC7BY;;sCAEH,KAAC/B;4BAAO,GAAGY,IAAI;4BAAEL,MAAMwB;;;mBAJfA;;AASlB,EAAE"}
package/index.css CHANGED
@@ -421,6 +421,12 @@
421
421
  --alpha-400: var(--color-alpha-white-24);
422
422
 
423
423
  /* Shadow */
424
+ --shadow-border-base:
425
+ 0 -1px 0 0 var(--color-alpha-white-6), 0 0 0 1px var(--color-alpha-white-6), 0 0 0 1px
426
+ var(--color-neutral-800), 0 0 1px 1.5px var(--color-alpha-black-24), 0 2px 2px 0
427
+ var(--color-alpha-black-24);
428
+ --shadow-border-interactive-with-active: 0 0 0 1px #ff8b16, 0 0 0 4px rgba(255, 49, 0, 0.25);
429
+ --shadow-border-error: 0 0 0 1px #ff1f5a, 0 0 0 3px rgba(246, 0, 67, 0.25);
424
430
  --shadow-button-inverted:
425
431
  0 -1px 0 0 var(--color-alpha-white-12), 0 0 0 1px var(--color-alpha-white-10), 0 0 0 1px
426
432
  var(--color-neutral-600), 0 0 1px 1.5px var(--color-alpha-black-24), 0 2px 2px 0
@@ -756,6 +762,9 @@
756
762
  --font-display: "Inter", sans-serif;
757
763
 
758
764
  /* Shadow */
765
+ --shadow-border-base: var(--shadow-border-base);
766
+ --shadow-border-interactive-with-active: var(--shadow-border-interactive-with-active);
767
+ --shadow-border-error: var(--shadow-border-error);
759
768
  --shadow-button-inverted: var(--shadow-button-inverted);
760
769
  --shadow-button-inverted-focus: var(--shadow-button-inverted-focus);
761
770
  --shadow-button-neutral: var(--shadow-button-neutral);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/react-ui",
3
3
  "license": "MIT",
4
- "version": "0.0.1",
4
+ "version": "0.1.0",
5
5
  "private": false,
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -56,12 +56,12 @@
56
56
  "storybook-addon-pseudo-states": "^9.1.8",
57
57
  "tailwindcss": "^4.1.13",
58
58
  "tw-animate-css": "^1.4.0",
59
- "@shipfox/biome": "1.2.1",
60
- "@shipfox/swc": "1.2.0",
61
- "@shipfox/ts-config": "1.3.4",
62
- "@shipfox/typescript": "1.1.1",
63
- "@shipfox/vite": "1.2.0",
64
- "@shipfox/vitest": "1.1.1"
59
+ "@shipfox/biome": "1.2.2",
60
+ "@shipfox/swc": "1.2.1",
61
+ "@shipfox/ts-config": "1.3.5",
62
+ "@shipfox/typescript": "1.1.2",
63
+ "@shipfox/vite": "1.2.1",
64
+ "@shipfox/vitest": "1.1.2"
65
65
  },
66
66
  "scripts": {
67
67
  "build": "swc",
@@ -0,0 +1,138 @@
1
+ import type {Meta, StoryObj} from '@storybook/react';
2
+ import {Code, Header} from 'components/typography';
3
+ import {Input} from './input';
4
+
5
+ const typeOptions = [
6
+ 'text',
7
+ 'email',
8
+ 'password',
9
+ 'number',
10
+ 'search',
11
+ 'url',
12
+ 'tel',
13
+ 'date',
14
+ 'time',
15
+ 'datetime-local',
16
+ 'month',
17
+ 'week',
18
+ 'color',
19
+ 'file',
20
+ ] as const;
21
+
22
+ const meta = {
23
+ title: 'Components/Input',
24
+ component: Input,
25
+ tags: ['autodocs'],
26
+ argTypes: {
27
+ type: {
28
+ control: 'select',
29
+ options: typeOptions,
30
+ },
31
+ placeholder: {control: 'text'},
32
+ disabled: {control: 'boolean'},
33
+ 'aria-invalid': {control: 'boolean'},
34
+ },
35
+ args: {
36
+ type: 'text',
37
+ placeholder: 'Type something…',
38
+ disabled: false,
39
+ 'aria-invalid': false,
40
+ },
41
+ } satisfies Meta<typeof Input>;
42
+
43
+ export default meta;
44
+
45
+ type Story = StoryObj<typeof meta>;
46
+
47
+ export const Default: Story = {};
48
+
49
+ const variants = ['base', 'component'] as const;
50
+ const sizes = ['base', 'small'] as const;
51
+
52
+ export const States: Story = {
53
+ render: (args) => (
54
+ <div className="flex flex-col gap-32">
55
+ {variants.map((variant) =>
56
+ sizes.map((size) => (
57
+ <div key={variant + size} className="flex flex-col gap-16">
58
+ <Header variant="h3">
59
+ {variant} {size}
60
+ </Header>
61
+ <div className="flex flex-col gap-8">
62
+ <Code variant="label" className="text-foreground-neutral-subtle">
63
+ Default
64
+ </Code>
65
+
66
+ <Input {...args} variant={variant} size={size} />
67
+ </div>
68
+
69
+ <div className="flex flex-col gap-8">
70
+ <Code variant="label" className="text-foreground-neutral-subtle">
71
+ Hover
72
+ </Code>
73
+
74
+ <Input {...args} className="hover" variant={variant} size={size} />
75
+ </div>
76
+ <div className="flex flex-col gap-8">
77
+ <Code variant="label" className="text-foreground-neutral-subtle">
78
+ Active
79
+ </Code>
80
+
81
+ <Input
82
+ {...args}
83
+ className="active"
84
+ defaultValue="The quick brown fox jumps over the lazy dog"
85
+ variant={variant}
86
+ size={size}
87
+ />
88
+ </div>
89
+ <div className="flex flex-col gap-8">
90
+ <Code variant="label" className="text-foreground-neutral-subtle">
91
+ Focus
92
+ </Code>
93
+
94
+ <Input {...args} className="focus" variant={variant} size={size} />
95
+ </div>
96
+ <div className="flex flex-col gap-8">
97
+ <Code variant="label" className="text-foreground-neutral-subtle">
98
+ Disabled
99
+ </Code>
100
+
101
+ <Input {...args} disabled variant={variant} size={size} />
102
+ </div>
103
+ <div className="flex flex-col gap-8">
104
+ <Code variant="label" className="text-foreground-neutral-subtle">
105
+ Invalid
106
+ </Code>
107
+
108
+ <Input {...args} aria-invalid variant={variant} size={size} />
109
+ </div>
110
+ </div>
111
+ )),
112
+ )}
113
+ </div>
114
+ ),
115
+ };
116
+
117
+ States.parameters = {
118
+ pseudo: {
119
+ hover: '.hover',
120
+ active: '.active',
121
+ focusVisible: '.focus',
122
+ },
123
+ };
124
+
125
+ export const Types: Story = {
126
+ render: (args) => (
127
+ <div className="flex flex-col gap-32">
128
+ {typeOptions.map((t) => (
129
+ <div key={t} className="flex flex-col gap-8">
130
+ <Code variant="label" className="text-foreground-neutral-subtle">
131
+ {t}
132
+ </Code>
133
+ <Input {...args} type={t} />
134
+ </div>
135
+ ))}
136
+ </div>
137
+ ),
138
+ };
@@ -0,0 +1,43 @@
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 inputVariants = 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 InputProps = Omit<ComponentProps<'input'>, 'size'> & VariantProps<typeof inputVariants>;
23
+
24
+ export function Input({className, type, variant, size, ...props}: InputProps) {
25
+ return (
26
+ <input
27
+ type={type}
28
+ data-slot="input"
29
+ className={cn(
30
+ 'placeholder:text-foreground-neutral-muted w-full min-w-0 rounded-6 px-8 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
+ 'file:text-foreground-neutral-base file:inline-flex file:font-medium',
34
+ 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-background-neutral-disabled disabled:shadow-none disabled:text-foreground-neutral-disabled',
35
+ 'focus-visible:shadow-border-interactive-with-active',
36
+ 'aria-invalid:shadow-border-error',
37
+ inputVariants({variant, size}),
38
+ className,
39
+ )}
40
+ {...props}
41
+ />
42
+ );
43
+ }
@@ -1,4 +1,4 @@
1
- import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
1
+ import {afterEach, beforeEach, describe, expect, it, vi} from '@shipfox/vitest/vi';
2
2
  import {
3
3
  generateDurationShortcut,
4
4
  intervalToNowFromDuration,
@@ -1,3 +1,4 @@
1
+ import {afterEach, beforeEach, describe, expect, it, vi} from '@shipfox/vitest/vi';
1
2
  import {
2
3
  addDays,
3
4
  addYears,
@@ -8,7 +9,6 @@ import {
8
9
  subHours,
9
10
  subYears,
10
11
  } from 'date-fns';
11
- import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
12
12
  import {formatDateTimeRange} from './date';
13
13
 
14
14
  describe('Format - Date', () => {
@@ -1,4 +1,4 @@
1
- import {describe, expect, it} from 'vitest';
1
+ import {describe, expect, it} from '@shipfox/vitest/vi';
2
2
  import {formatDuration} from './duration';
3
3
 
4
4
  describe('formatDuration', () => {
@@ -1,4 +1,4 @@
1
- import {describe, expect, it} from 'vitest';
1
+ import {describe, expect, it} from '@shipfox/vitest/vi';
2
2
  import {formatNumber, formatNumberCompact, formatPercent} from './number';
3
3
 
4
4
  describe('Format - Number', () => {
package/test/setup.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import {afterEach, expect} from '@shipfox/vitest/vi';
1
2
  import * as extensions from '@testing-library/jest-dom/matchers';
2
3
  import {cleanup} from '@testing-library/react';
3
- import {afterEach, expect} from 'vitest';
4
4
 
5
5
  expect.extend(extensions);
6
6