@regardio/react 0.5.7 → 0.6.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.
- package/dist/background-slideshow/index.d.mts +36 -0
- package/dist/background-slideshow/index.mjs +110 -0
- package/dist/blurry-gradient/index.d.mts +17 -0
- package/dist/blurry-gradient/index.mjs +93 -0
- package/dist/button/index.d.mts +2 -0
- package/dist/button/index.mjs +3 -0
- package/dist/button-BiSQpBbc.mjs +129 -0
- package/dist/carousel/index.d.mts +40 -0
- package/dist/carousel/index.mjs +141 -0
- package/dist/checkbox/index.d.mts +37 -0
- package/dist/checkbox/index.mjs +70 -0
- package/dist/checkbox-group/index.d.mts +17 -0
- package/dist/checkbox-group/index.mjs +29 -0
- package/dist/chunk-BTpB_u-K.mjs +18 -0
- package/dist/countdown/index.d.mts +6 -0
- package/dist/countdown/index.mjs +58 -0
- package/dist/field/index.d.mts +66 -0
- package/dist/field/index.mjs +115 -0
- package/dist/fieldset/index.d.mts +33 -0
- package/dist/fieldset/index.mjs +61 -0
- package/dist/form/index.d.mts +22 -0
- package/dist/form/index.mjs +31 -0
- package/dist/generic-error/{index.d.ts → index.d.mts} +22 -18
- package/dist/generic-error/index.mjs +57 -0
- package/dist/grid/index.d.mts +1197 -0
- package/dist/grid/index.mjs +221 -0
- package/dist/heading/index.d.mts +31 -0
- package/dist/heading/index.mjs +29 -0
- package/dist/highlight/index.d.mts +18 -0
- package/dist/highlight/index.mjs +35 -0
- package/dist/hooks/{use-current-route-data.d.ts → use-current-route-data.d.mts} +3 -2
- package/dist/hooks/use-current-route-data.mjs +20 -0
- package/dist/hooks/{use-focus-search.d.ts → use-focus-search.d.mts} +4 -3
- package/dist/hooks/use-focus-search.mjs +21 -0
- package/dist/hooks/{use-matches-data.d.ts → use-matches-data.d.mts} +3 -2
- package/dist/hooks/use-matches-data.mjs +21 -0
- package/dist/hooks/{use-media-query.d.ts → use-media-query.d.mts} +3 -2
- package/dist/hooks/use-media-query.mjs +26 -0
- package/dist/hooks/use-mobile.d.mts +4 -0
- package/dist/hooks/use-mobile.mjs +20 -0
- package/dist/hooks/use-nonce.d.mts +8 -0
- package/dist/hooks/use-nonce.mjs +13 -0
- package/dist/hooks/{use-orientation.d.ts → use-orientation.d.mts} +3 -2
- package/dist/hooks/use-orientation.mjs +30 -0
- package/dist/hooks/use-user.d.mts +55 -0
- package/dist/hooks/use-user.mjs +39 -0
- package/dist/icon-button/index.d.mts +29 -0
- package/dist/icon-button/index.mjs +36 -0
- package/dist/if/index.d.mts +15 -0
- package/dist/if/index.mjs +21 -0
- package/dist/iframe/index.d.mts +11 -0
- package/dist/iframe/index.mjs +15 -0
- package/dist/index-Bm-tWhsb.d.mts +30 -0
- package/dist/index-YT2CkvL6.d.mts +36 -0
- package/dist/input/index.d.mts +2 -0
- package/dist/input/index.mjs +3 -0
- package/dist/input-CtR6aRVi.mjs +73 -0
- package/dist/link/index.d.mts +73 -0
- package/dist/link/index.mjs +129 -0
- package/dist/list/index.d.mts +71 -0
- package/dist/list/index.mjs +54 -0
- package/dist/markdown-container/index.d.mts +23 -0
- package/dist/markdown-container/index.mjs +71 -0
- package/dist/password-input/index.d.mts +24 -0
- package/dist/password-input/index.mjs +92 -0
- package/dist/picture/{index.d.ts → index.d.mts} +21 -20
- package/dist/picture/index.mjs +3 -0
- package/dist/picture-DkX3W5zl.mjs +69 -0
- package/dist/protected-email/{index.d.ts → index.d.mts} +14 -8
- package/dist/protected-email/index.mjs +37 -0
- package/dist/radio/index.d.mts +37 -0
- package/dist/radio/index.mjs +72 -0
- package/dist/radio-group/index.d.mts +17 -0
- package/dist/radio-group/index.mjs +29 -0
- package/dist/slider/index.d.mts +85 -0
- package/dist/slider/index.mjs +133 -0
- package/dist/switch/index.d.mts +38 -0
- package/dist/switch/index.mjs +87 -0
- package/dist/text/index.d.mts +26 -0
- package/dist/text/index.mjs +32 -0
- package/dist/text-CPlUND-Z.mjs +58 -0
- package/dist/toggle/index.d.mts +59 -0
- package/dist/toggle/index.mjs +82 -0
- package/dist/utils/author/index.d.mts +4 -0
- package/dist/utils/author/index.mjs +26 -0
- package/dist/utils/text/{index.d.ts → index.d.mts} +4 -3
- package/dist/utils/text/index.mjs +3 -0
- package/package.json +5 -117
- package/src/button/button.stories.tsx +161 -0
- package/src/button/button.test.tsx +73 -0
- package/src/button/button.tsx +112 -0
- package/src/button/index.ts +2 -0
- package/src/carousel/carousel-next.tsx +2 -2
- package/src/carousel/carousel-previous.tsx +2 -2
- package/src/checkbox/checkbox.stories.tsx +118 -0
- package/src/checkbox/checkbox.tsx +91 -0
- package/src/checkbox/index.ts +2 -0
- package/src/checkbox-group/checkbox-group.tsx +40 -0
- package/src/checkbox-group/index.ts +2 -0
- package/src/field/field.stories.tsx +105 -0
- package/src/field/field.test.tsx +61 -0
- package/src/field/field.tsx +165 -0
- package/src/field/index.ts +12 -0
- package/src/fieldset/fieldset.stories.tsx +204 -0
- package/src/fieldset/fieldset.test.tsx +63 -0
- package/src/fieldset/fieldset.tsx +75 -0
- package/src/fieldset/index.ts +7 -0
- package/src/form/form.stories.tsx +230 -0
- package/src/form/form.test.tsx +68 -0
- package/src/form/form.tsx +38 -0
- package/src/form/index.ts +2 -0
- package/src/icon-button/icon-button.stories.tsx +128 -7
- package/src/icon-button/icon-button.test.tsx +152 -0
- package/src/icon-button/icon-button.tsx +43 -9
- package/src/input/index.ts +2 -0
- package/src/input/input.stories.tsx +151 -0
- package/src/input/input.test.tsx +65 -0
- package/src/input/input.tsx +113 -0
- package/src/password-input/index.ts +1 -1
- package/src/password-input/password-input.tsx +104 -27
- package/src/radio/index.ts +2 -0
- package/src/radio/radio.tsx +92 -0
- package/src/radio-group/index.ts +2 -0
- package/src/radio-group/radio-group.tsx +36 -0
- package/src/slider/index.ts +18 -0
- package/src/slider/slider.tsx +179 -0
- package/src/switch/index.ts +2 -0
- package/src/switch/switch.stories.tsx +118 -0
- package/src/switch/switch.tsx +101 -0
- package/src/toggle/index.ts +2 -0
- package/src/toggle/toggle.stories.tsx +232 -0
- package/src/toggle/toggle.test.tsx +149 -0
- package/src/toggle/toggle.tsx +88 -0
- package/dist/background-slideshow/index.d.ts +0 -24
- package/dist/background-slideshow/index.js +0 -165
- package/dist/blurry-gradient/index.d.ts +0 -16
- package/dist/blurry-gradient/index.js +0 -128
- package/dist/carousel/index.d.ts +0 -36
- package/dist/carousel/index.js +0 -171
- package/dist/countdown/index.d.ts +0 -5
- package/dist/countdown/index.js +0 -73
- package/dist/generic-error/index.js +0 -47
- package/dist/grid/index.d.ts +0 -1196
- package/dist/grid/index.js +0 -239
- package/dist/heading/index.d.ts +0 -24
- package/dist/heading/index.js +0 -99
- package/dist/highlight/index.d.ts +0 -13
- package/dist/highlight/index.js +0 -59
- package/dist/hooks/use-current-route-data.js +0 -16
- package/dist/hooks/use-focus-search.js +0 -19
- package/dist/hooks/use-matches-data.js +0 -15
- package/dist/hooks/use-media-query.js +0 -20
- package/dist/hooks/use-mobile.d.ts +0 -3
- package/dist/hooks/use-mobile.js +0 -19
- package/dist/hooks/use-nonce.d.ts +0 -7
- package/dist/hooks/use-nonce.js +0 -8
- package/dist/hooks/use-orientation.js +0 -29
- package/dist/hooks/use-user.d.ts +0 -50
- package/dist/hooks/use-user.js +0 -25
- package/dist/icon-button/index.d.ts +0 -9
- package/dist/icon-button/index.js +0 -17
- package/dist/if/index.d.ts +0 -10
- package/dist/if/index.js +0 -24
- package/dist/iframe/index.d.ts +0 -10
- package/dist/iframe/index.js +0 -17
- package/dist/link/index.d.ts +0 -55
- package/dist/link/index.js +0 -195
- package/dist/list/index.d.ts +0 -69
- package/dist/list/index.js +0 -65
- package/dist/markdown-container/index.d.ts +0 -22
- package/dist/markdown-container/index.js +0 -128
- package/dist/password-input/index.d.ts +0 -11
- package/dist/password-input/index.js +0 -46
- package/dist/picture/index.js +0 -68
- package/dist/protected-email/index.js +0 -30
- package/dist/text/index.d.ts +0 -20
- package/dist/text/index.js +0 -38
- package/dist/utils/author/index.d.ts +0 -3
- package/dist/utils/author/index.js +0 -33
- package/dist/utils/text/index.js +0 -73
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://www.schemastore.org/package.json",
|
|
3
3
|
"name": "@regardio/react",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Regardio React UI components",
|
|
7
7
|
"keywords": [
|
|
@@ -26,128 +26,16 @@
|
|
|
26
26
|
],
|
|
27
27
|
"type": "module",
|
|
28
28
|
"exports": {
|
|
29
|
-
"./
|
|
30
|
-
"types": "./dist/background-slideshow/index.d.ts",
|
|
31
|
-
"import": "./dist/background-slideshow/index.js"
|
|
32
|
-
},
|
|
33
|
-
"./blurry-gradient": {
|
|
34
|
-
"types": "./dist/blurry-gradient/index.d.ts",
|
|
35
|
-
"import": "./dist/blurry-gradient/index.js"
|
|
36
|
-
},
|
|
37
|
-
"./carousel": {
|
|
38
|
-
"types": "./dist/carousel/index.d.ts",
|
|
39
|
-
"import": "./dist/carousel/index.js"
|
|
40
|
-
},
|
|
41
|
-
"./countdown": {
|
|
42
|
-
"types": "./dist/countdown/index.d.ts",
|
|
43
|
-
"import": "./dist/countdown/index.js"
|
|
44
|
-
},
|
|
45
|
-
"./generic-error": {
|
|
46
|
-
"types": "./dist/generic-error/index.d.ts",
|
|
47
|
-
"import": "./dist/generic-error/index.js"
|
|
48
|
-
},
|
|
49
|
-
"./grid": {
|
|
50
|
-
"types": "./dist/grid/index.d.ts",
|
|
51
|
-
"import": "./dist/grid/index.js"
|
|
52
|
-
},
|
|
53
|
-
"./heading": {
|
|
54
|
-
"types": "./dist/heading/index.d.ts",
|
|
55
|
-
"import": "./dist/heading/index.js"
|
|
56
|
-
},
|
|
57
|
-
"./highlight": {
|
|
58
|
-
"types": "./dist/highlight/index.d.ts",
|
|
59
|
-
"import": "./dist/highlight/index.js"
|
|
60
|
-
},
|
|
61
|
-
"./hooks/use-current-route-data": {
|
|
62
|
-
"types": "./dist/hooks/use-current-route-data.d.ts",
|
|
63
|
-
"import": "./dist/hooks/use-current-route-data.js"
|
|
64
|
-
},
|
|
65
|
-
"./hooks/use-focus-search": {
|
|
66
|
-
"types": "./dist/hooks/use-focus-search.d.ts",
|
|
67
|
-
"import": "./dist/hooks/use-focus-search.js"
|
|
68
|
-
},
|
|
69
|
-
"./hooks/use-matches-data": {
|
|
70
|
-
"types": "./dist/hooks/use-matches-data.d.ts",
|
|
71
|
-
"import": "./dist/hooks/use-matches-data.js"
|
|
72
|
-
},
|
|
73
|
-
"./hooks/use-media-query": {
|
|
74
|
-
"types": "./dist/hooks/use-media-query.d.ts",
|
|
75
|
-
"import": "./dist/hooks/use-media-query.js"
|
|
76
|
-
},
|
|
77
|
-
"./hooks/use-mobile": {
|
|
78
|
-
"types": "./dist/hooks/use-mobile.d.ts",
|
|
79
|
-
"import": "./dist/hooks/use-mobile.js"
|
|
80
|
-
},
|
|
81
|
-
"./hooks/use-nonce": {
|
|
82
|
-
"types": "./dist/hooks/use-nonce.d.ts",
|
|
83
|
-
"import": "./dist/hooks/use-nonce.js"
|
|
84
|
-
},
|
|
85
|
-
"./hooks/use-orientation": {
|
|
86
|
-
"types": "./dist/hooks/use-orientation.d.ts",
|
|
87
|
-
"import": "./dist/hooks/use-orientation.js"
|
|
88
|
-
},
|
|
89
|
-
"./hooks/use-user": {
|
|
90
|
-
"types": "./dist/hooks/use-user.d.ts",
|
|
91
|
-
"import": "./dist/hooks/use-user.js"
|
|
92
|
-
},
|
|
93
|
-
"./icon-button": {
|
|
94
|
-
"types": "./dist/icon-button/index.d.ts",
|
|
95
|
-
"import": "./dist/icon-button/index.js"
|
|
96
|
-
},
|
|
97
|
-
"./if": {
|
|
98
|
-
"types": "./dist/if/index.d.ts",
|
|
99
|
-
"import": "./dist/if/index.js"
|
|
100
|
-
},
|
|
101
|
-
"./iframe": {
|
|
102
|
-
"types": "./dist/iframe/index.d.ts",
|
|
103
|
-
"import": "./dist/iframe/index.js"
|
|
104
|
-
},
|
|
105
|
-
"./link": {
|
|
106
|
-
"types": "./dist/link/index.d.ts",
|
|
107
|
-
"import": "./dist/link/index.js"
|
|
108
|
-
},
|
|
109
|
-
"./list": {
|
|
110
|
-
"types": "./dist/list/index.d.ts",
|
|
111
|
-
"import": "./dist/list/index.js"
|
|
112
|
-
},
|
|
113
|
-
"./markdown-container": {
|
|
114
|
-
"types": "./dist/markdown-container/index.d.ts",
|
|
115
|
-
"import": "./dist/markdown-container/index.js"
|
|
116
|
-
},
|
|
117
|
-
"./password-input": {
|
|
118
|
-
"types": "./dist/password-input/index.d.ts",
|
|
119
|
-
"import": "./dist/password-input/index.js"
|
|
120
|
-
},
|
|
121
|
-
"./picture": {
|
|
122
|
-
"types": "./dist/picture/index.d.ts",
|
|
123
|
-
"import": "./dist/picture/index.js"
|
|
124
|
-
},
|
|
125
|
-
"./protected-email": {
|
|
126
|
-
"types": "./dist/protected-email/index.d.ts",
|
|
127
|
-
"import": "./dist/protected-email/index.js"
|
|
128
|
-
},
|
|
129
|
-
"./tailwind.css": "./src/tailwind.css",
|
|
130
|
-
"./text": {
|
|
131
|
-
"types": "./dist/text/index.d.ts",
|
|
132
|
-
"import": "./dist/text/index.js"
|
|
133
|
-
},
|
|
134
|
-
"./utils/author": {
|
|
135
|
-
"types": "./dist/utils/author/index.d.ts",
|
|
136
|
-
"import": "./dist/utils/author/index.js"
|
|
137
|
-
},
|
|
138
|
-
"./utils/text": {
|
|
139
|
-
"types": "./dist/utils/text/index.d.ts",
|
|
140
|
-
"import": "./dist/utils/text/index.js"
|
|
141
|
-
}
|
|
29
|
+
"./tailwind.css": "./src/tailwind.css"
|
|
142
30
|
},
|
|
143
31
|
"files": [
|
|
144
32
|
"dist",
|
|
145
33
|
"src"
|
|
146
34
|
],
|
|
147
35
|
"scripts": {
|
|
148
|
-
"build": "
|
|
36
|
+
"build": "tsdown && post-build-exports --preserve \"./tailwind.css\" && pnpm fix",
|
|
149
37
|
"clean": "exec-clean .turbo dist",
|
|
150
|
-
"dev": "
|
|
38
|
+
"dev": "tsdown --watch",
|
|
151
39
|
"fix": "exec-p fix:*",
|
|
152
40
|
"fix:biome": "lint-biome check --write --unsafe .",
|
|
153
41
|
"fix:md": "lint-md --fix",
|
|
@@ -214,7 +102,7 @@
|
|
|
214
102
|
"playwright": "1.57.0",
|
|
215
103
|
"storybook": "10.1.11",
|
|
216
104
|
"tailwindcss": "4.1.18",
|
|
217
|
-
"
|
|
105
|
+
"tsdown": "0.20.0-beta.1",
|
|
218
106
|
"typescript": "5.9.3",
|
|
219
107
|
"vite": "7.3.1",
|
|
220
108
|
"vitest": "4.0.17"
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Button } from './button';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
argTypes: {
|
|
6
|
+
children: {
|
|
7
|
+
control: 'text',
|
|
8
|
+
description: 'Button content',
|
|
9
|
+
},
|
|
10
|
+
disabled: {
|
|
11
|
+
control: 'boolean',
|
|
12
|
+
description: 'Disable the button',
|
|
13
|
+
},
|
|
14
|
+
size: {
|
|
15
|
+
control: 'select',
|
|
16
|
+
description: 'Button size',
|
|
17
|
+
options: ['sm', 'md', 'lg', 'xl', '2xl'],
|
|
18
|
+
},
|
|
19
|
+
variant: {
|
|
20
|
+
control: 'select',
|
|
21
|
+
description: 'Button style variant',
|
|
22
|
+
options: ['primary', 'secondary', 'outline', 'ghost', 'destructive'],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
component: Button,
|
|
26
|
+
parameters: {
|
|
27
|
+
layout: 'centered',
|
|
28
|
+
},
|
|
29
|
+
tags: ['autodocs'],
|
|
30
|
+
title: 'Components/Button',
|
|
31
|
+
} satisfies Meta<typeof Button>;
|
|
32
|
+
|
|
33
|
+
export default meta;
|
|
34
|
+
type Story = StoryObj<typeof meta>;
|
|
35
|
+
|
|
36
|
+
export const Default: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
children: 'Button',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const Primary: Story = {
|
|
43
|
+
args: {
|
|
44
|
+
children: 'Primary Button',
|
|
45
|
+
variant: 'primary',
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const Secondary: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
children: 'Secondary Button',
|
|
52
|
+
variant: 'secondary',
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const Outline: Story = {
|
|
57
|
+
args: {
|
|
58
|
+
children: 'Outline Button',
|
|
59
|
+
variant: 'outline',
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const Ghost: Story = {
|
|
64
|
+
args: {
|
|
65
|
+
children: 'Ghost Button',
|
|
66
|
+
variant: 'ghost',
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const Destructive: Story = {
|
|
71
|
+
args: {
|
|
72
|
+
children: 'Destructive Button',
|
|
73
|
+
variant: 'destructive',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const Small: Story = {
|
|
78
|
+
args: {
|
|
79
|
+
children: 'Small Button',
|
|
80
|
+
size: 'sm',
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const Large: Story = {
|
|
85
|
+
args: {
|
|
86
|
+
children: 'Large Button',
|
|
87
|
+
size: 'lg',
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const ExtraLarge: Story = {
|
|
92
|
+
args: {
|
|
93
|
+
children: 'Extra Large Button',
|
|
94
|
+
size: 'xl',
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const DoubleExtraLarge: Story = {
|
|
99
|
+
args: {
|
|
100
|
+
children: '2XL Button',
|
|
101
|
+
size: '2xl',
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const Disabled: Story = {
|
|
106
|
+
args: {
|
|
107
|
+
children: 'Disabled Button',
|
|
108
|
+
disabled: true,
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export const WithCustomClass: Story = {
|
|
113
|
+
args: {
|
|
114
|
+
children: 'Button with shadow',
|
|
115
|
+
className: 'shadow-lg',
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export const AsLink: Story = {
|
|
120
|
+
args: {
|
|
121
|
+
children: 'Link Button',
|
|
122
|
+
nativeButton: false,
|
|
123
|
+
render: (props: React.ComponentProps<'a'>) => (
|
|
124
|
+
<a
|
|
125
|
+
{...props}
|
|
126
|
+
href="#example"
|
|
127
|
+
/>
|
|
128
|
+
),
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export const AllVariants: Story = {
|
|
133
|
+
render: () => (
|
|
134
|
+
<div className="flex flex-wrap gap-4">
|
|
135
|
+
<Button variant="primary">Primary</Button>
|
|
136
|
+
<Button variant="secondary">Secondary</Button>
|
|
137
|
+
<Button variant="outline">Outline</Button>
|
|
138
|
+
<Button variant="ghost">Ghost</Button>
|
|
139
|
+
<Button variant="destructive">Destructive</Button>
|
|
140
|
+
</div>
|
|
141
|
+
),
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const AllSizes: Story = {
|
|
145
|
+
render: () => (
|
|
146
|
+
<div className="flex flex-wrap items-center gap-4">
|
|
147
|
+
<Button size="sm">Small</Button>
|
|
148
|
+
<Button size="md">Medium</Button>
|
|
149
|
+
<Button size="lg">Large</Button>
|
|
150
|
+
<Button size="xl">Extra Large</Button>
|
|
151
|
+
<Button size="2xl">2XL</Button>
|
|
152
|
+
</div>
|
|
153
|
+
),
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
export const Interactive: Story = {
|
|
157
|
+
args: {
|
|
158
|
+
children: 'Click me!',
|
|
159
|
+
onClick: () => alert('Button clicked!'),
|
|
160
|
+
},
|
|
161
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { Button } from './button';
|
|
4
|
+
|
|
5
|
+
describe('Button', () => {
|
|
6
|
+
it('renders children correctly', () => {
|
|
7
|
+
render(<Button>Click me</Button>);
|
|
8
|
+
expect(screen.getByRole('button', { name: 'Click me' })).toBeInTheDocument();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('applies default variant and size classes', () => {
|
|
12
|
+
render(<Button>Default button</Button>);
|
|
13
|
+
const button = screen.getByRole('button', { name: 'Default button' });
|
|
14
|
+
expect(button).toHaveClass('bg-blue-600', 'text-white', 'px-4', 'py-2');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('applies variant classes correctly', () => {
|
|
18
|
+
render(<Button variant="secondary">Secondary button</Button>);
|
|
19
|
+
const button = screen.getByRole('button', { name: 'Secondary button' });
|
|
20
|
+
expect(button).toHaveClass('bg-gray-100', 'text-gray-900');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('applies size classes correctly', () => {
|
|
24
|
+
render(<Button size="lg">Large button</Button>);
|
|
25
|
+
const button = screen.getByRole('button', { name: 'Large button' });
|
|
26
|
+
expect(button).toHaveClass('px-6', 'py-3', 'text-lg');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('applies custom className', () => {
|
|
30
|
+
render(<Button className="custom-class">Custom button</Button>);
|
|
31
|
+
const button = screen.getByRole('button', { name: 'Custom button' });
|
|
32
|
+
expect(button).toHaveClass('custom-class');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('handles disabled state', () => {
|
|
36
|
+
render(<Button disabled>Disabled button</Button>);
|
|
37
|
+
const button = screen.getByRole('button', { name: 'Disabled button' });
|
|
38
|
+
expect(button).toBeDisabled();
|
|
39
|
+
expect(button).toHaveClass('disabled:opacity-50', 'disabled:cursor-not-allowed');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('passes through other props', () => {
|
|
43
|
+
render(
|
|
44
|
+
<Button
|
|
45
|
+
aria-label="Test button"
|
|
46
|
+
data-testid="test-button"
|
|
47
|
+
>
|
|
48
|
+
Test
|
|
49
|
+
</Button>,
|
|
50
|
+
);
|
|
51
|
+
const button = screen.getByTestId('test-button');
|
|
52
|
+
expect(button).toHaveAttribute('aria-label', 'Test button');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('renders as different element when render prop is provided', () => {
|
|
56
|
+
render(
|
|
57
|
+
<Button
|
|
58
|
+
nativeButton={false}
|
|
59
|
+
render={(props) => (
|
|
60
|
+
<a
|
|
61
|
+
{...props}
|
|
62
|
+
href="#test"
|
|
63
|
+
/>
|
|
64
|
+
)}
|
|
65
|
+
>
|
|
66
|
+
Link button
|
|
67
|
+
</Button>,
|
|
68
|
+
);
|
|
69
|
+
const link = screen.getByRole('button', { name: 'Link button' });
|
|
70
|
+
expect(link).toHaveAttribute('href', '#test');
|
|
71
|
+
expect(link.tagName).toBe('A');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Button as BaseUIButton } from '@base-ui/react/button';
|
|
2
|
+
import { tv } from '@regardio/tailwind/utils';
|
|
3
|
+
import type { ComponentProps } from 'react';
|
|
4
|
+
|
|
5
|
+
const buttonVariants = {
|
|
6
|
+
destructive: [
|
|
7
|
+
'bg-red-600',
|
|
8
|
+
'text-white',
|
|
9
|
+
'border-red-600',
|
|
10
|
+
'hover:bg-red-700',
|
|
11
|
+
'hover:border-red-700',
|
|
12
|
+
'focus-visible:ring-2',
|
|
13
|
+
'focus-visible:ring-red-500',
|
|
14
|
+
'focus-visible:ring-offset-2',
|
|
15
|
+
],
|
|
16
|
+
ghost: [
|
|
17
|
+
'bg-transparent',
|
|
18
|
+
'text-gray-900',
|
|
19
|
+
'border-transparent',
|
|
20
|
+
'hover:bg-gray-100',
|
|
21
|
+
'hover:border-transparent',
|
|
22
|
+
'focus-visible:ring-2',
|
|
23
|
+
'focus-visible:ring-gray-500',
|
|
24
|
+
'focus-visible:ring-offset-2',
|
|
25
|
+
],
|
|
26
|
+
outline: [
|
|
27
|
+
'bg-transparent',
|
|
28
|
+
'text-gray-900',
|
|
29
|
+
'border-gray-300',
|
|
30
|
+
'hover:bg-gray-50',
|
|
31
|
+
'hover:border-gray-400',
|
|
32
|
+
'focus-visible:ring-2',
|
|
33
|
+
'focus-visible:ring-gray-500',
|
|
34
|
+
'focus-visible:ring-offset-2',
|
|
35
|
+
],
|
|
36
|
+
primary: [
|
|
37
|
+
'bg-blue-600',
|
|
38
|
+
'text-white',
|
|
39
|
+
'border-blue-600',
|
|
40
|
+
'hover:bg-blue-700',
|
|
41
|
+
'hover:border-blue-700',
|
|
42
|
+
'focus-visible:ring-2',
|
|
43
|
+
'focus-visible:ring-blue-500',
|
|
44
|
+
'focus-visible:ring-offset-2',
|
|
45
|
+
],
|
|
46
|
+
secondary: [
|
|
47
|
+
'bg-gray-100',
|
|
48
|
+
'text-gray-900',
|
|
49
|
+
'border-gray-300',
|
|
50
|
+
'hover:bg-gray-200',
|
|
51
|
+
'hover:border-gray-400',
|
|
52
|
+
'focus-visible:ring-2',
|
|
53
|
+
'focus-visible:ring-gray-500',
|
|
54
|
+
'focus-visible:ring-offset-2',
|
|
55
|
+
],
|
|
56
|
+
} as const;
|
|
57
|
+
|
|
58
|
+
const buttonSizes = {
|
|
59
|
+
'2xl': ['px-10', 'py-5', 'text-2xl', 'font-medium', 'rounded-lg'],
|
|
60
|
+
lg: ['px-6', 'py-3', 'text-lg', 'font-medium', 'rounded-lg'],
|
|
61
|
+
md: ['px-4', 'py-2', 'text-base', 'font-medium', 'rounded-md'],
|
|
62
|
+
sm: ['px-3', 'py-1.5', 'text-sm', 'font-medium', 'rounded-md'],
|
|
63
|
+
xl: ['px-8', 'py-4', 'text-xl', 'font-medium', 'rounded-lg'],
|
|
64
|
+
} as const;
|
|
65
|
+
|
|
66
|
+
const button = tv({
|
|
67
|
+
base: [
|
|
68
|
+
'inline-flex',
|
|
69
|
+
'items-center',
|
|
70
|
+
'justify-center',
|
|
71
|
+
'border',
|
|
72
|
+
'transition-colors',
|
|
73
|
+
'duration-200',
|
|
74
|
+
'ease-in-out',
|
|
75
|
+
'disabled:opacity-50',
|
|
76
|
+
'disabled:cursor-not-allowed',
|
|
77
|
+
'disabled:pointer-events-none',
|
|
78
|
+
],
|
|
79
|
+
defaultVariants: {
|
|
80
|
+
size: 'md',
|
|
81
|
+
variant: 'primary',
|
|
82
|
+
},
|
|
83
|
+
variants: {
|
|
84
|
+
size: buttonSizes,
|
|
85
|
+
variant: buttonVariants,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
export type ButtonVariant = keyof typeof buttonVariants;
|
|
90
|
+
export type ButtonSize = keyof typeof buttonSizes;
|
|
91
|
+
|
|
92
|
+
export interface ButtonProps extends Omit<ComponentProps<typeof BaseUIButton>, 'className'> {
|
|
93
|
+
variant?: ButtonVariant;
|
|
94
|
+
size?: ButtonSize;
|
|
95
|
+
className?: string;
|
|
96
|
+
type?: 'button' | 'submit' | 'reset';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const Button = ({ children, className, variant, size, ...props }: ButtonProps) => {
|
|
100
|
+
return (
|
|
101
|
+
<BaseUIButton
|
|
102
|
+
className={button({
|
|
103
|
+
className,
|
|
104
|
+
size,
|
|
105
|
+
variant,
|
|
106
|
+
})}
|
|
107
|
+
{...props}
|
|
108
|
+
>
|
|
109
|
+
{children}
|
|
110
|
+
</BaseUIButton>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { forwardRef, type HTMLAttributes } from 'react';
|
|
4
|
+
import { Button } from '../button';
|
|
4
5
|
import { useCarousel } from './carousel-root';
|
|
5
6
|
|
|
6
7
|
export const CarouselNext = forwardRef<HTMLButtonElement, HTMLAttributes<HTMLButtonElement>>(
|
|
@@ -8,12 +9,11 @@ export const CarouselNext = forwardRef<HTMLButtonElement, HTMLAttributes<HTMLBut
|
|
|
8
9
|
const { canScrollNext, scrollNext } = useCarousel();
|
|
9
10
|
|
|
10
11
|
return (
|
|
11
|
-
<
|
|
12
|
+
<Button
|
|
12
13
|
className={className}
|
|
13
14
|
disabled={!canScrollNext}
|
|
14
15
|
onClick={scrollNext}
|
|
15
16
|
ref={ref}
|
|
16
|
-
type="button"
|
|
17
17
|
{...props}
|
|
18
18
|
/>
|
|
19
19
|
);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { forwardRef, type HTMLAttributes } from 'react';
|
|
4
|
+
import { Button } from '../button';
|
|
4
5
|
import { useCarousel } from './carousel-root';
|
|
5
6
|
|
|
6
7
|
export const CarouselPrevious = forwardRef<HTMLButtonElement, HTMLAttributes<HTMLButtonElement>>(
|
|
@@ -8,12 +9,11 @@ export const CarouselPrevious = forwardRef<HTMLButtonElement, HTMLAttributes<HTM
|
|
|
8
9
|
const { canScrollPrev, scrollPrev } = useCarousel();
|
|
9
10
|
|
|
10
11
|
return (
|
|
11
|
-
<
|
|
12
|
+
<Button
|
|
12
13
|
className={className}
|
|
13
14
|
disabled={!canScrollPrev}
|
|
14
15
|
onClick={scrollPrev}
|
|
15
16
|
ref={ref}
|
|
16
|
-
type="button"
|
|
17
17
|
{...props}
|
|
18
18
|
/>
|
|
19
19
|
);
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Field } from '../field';
|
|
4
|
+
import { Checkbox } from './checkbox';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Checkbox.Root> = {
|
|
7
|
+
argTypes: {
|
|
8
|
+
disabled: {
|
|
9
|
+
control: 'boolean',
|
|
10
|
+
description: 'Disable the checkbox',
|
|
11
|
+
},
|
|
12
|
+
size: {
|
|
13
|
+
control: 'select',
|
|
14
|
+
description: 'Checkbox size',
|
|
15
|
+
options: ['sm', 'md', 'lg'],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
component: Checkbox.Root,
|
|
19
|
+
parameters: {
|
|
20
|
+
layout: 'centered',
|
|
21
|
+
},
|
|
22
|
+
tags: ['autodocs'],
|
|
23
|
+
title: 'Components/Checkbox',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default meta;
|
|
27
|
+
type Story = StoryObj<typeof meta>;
|
|
28
|
+
|
|
29
|
+
export const Default: Story = {
|
|
30
|
+
render: () => (
|
|
31
|
+
<Checkbox.Root>
|
|
32
|
+
<Checkbox.Indicator />
|
|
33
|
+
</Checkbox.Root>
|
|
34
|
+
),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const Checked: Story = {
|
|
38
|
+
render: () => (
|
|
39
|
+
<Checkbox.Root defaultChecked>
|
|
40
|
+
<Checkbox.Indicator />
|
|
41
|
+
</Checkbox.Root>
|
|
42
|
+
),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const Small: Story = {
|
|
46
|
+
render: () => (
|
|
47
|
+
<Checkbox.Root size="sm">
|
|
48
|
+
<Checkbox.Indicator />
|
|
49
|
+
</Checkbox.Root>
|
|
50
|
+
),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const Large: Story = {
|
|
54
|
+
render: () => (
|
|
55
|
+
<Checkbox.Root size="lg">
|
|
56
|
+
<Checkbox.Indicator />
|
|
57
|
+
</Checkbox.Root>
|
|
58
|
+
),
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const Disabled: Story = {
|
|
62
|
+
render: () => (
|
|
63
|
+
<Checkbox.Root disabled>
|
|
64
|
+
<Checkbox.Indicator />
|
|
65
|
+
</Checkbox.Root>
|
|
66
|
+
),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const WithLabel: Story = {
|
|
70
|
+
render: () => (
|
|
71
|
+
<Field.Root>
|
|
72
|
+
<Field.Label>
|
|
73
|
+
<Checkbox.Root>
|
|
74
|
+
<Checkbox.Indicator />
|
|
75
|
+
</Checkbox.Root>
|
|
76
|
+
Accept terms and conditions
|
|
77
|
+
</Field.Label>
|
|
78
|
+
</Field.Root>
|
|
79
|
+
),
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const Controlled: Story = {
|
|
83
|
+
render: () => {
|
|
84
|
+
const [checked, setChecked] = useState(false);
|
|
85
|
+
return (
|
|
86
|
+
<div className="space-y-4">
|
|
87
|
+
<Field.Root>
|
|
88
|
+
<Field.Label>
|
|
89
|
+
<Checkbox.Root
|
|
90
|
+
checked={checked}
|
|
91
|
+
onCheckedChange={setChecked}
|
|
92
|
+
>
|
|
93
|
+
<Checkbox.Indicator />
|
|
94
|
+
</Checkbox.Root>
|
|
95
|
+
Subscribe to newsletter
|
|
96
|
+
</Field.Label>
|
|
97
|
+
</Field.Root>
|
|
98
|
+
<p className="text-sm text-gray-600">Status: {checked ? 'Subscribed' : 'Not subscribed'}</p>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const AllSizes: Story = {
|
|
105
|
+
render: () => (
|
|
106
|
+
<div className="flex items-center gap-4">
|
|
107
|
+
<Checkbox.Root size="sm">
|
|
108
|
+
<Checkbox.Indicator />
|
|
109
|
+
</Checkbox.Root>
|
|
110
|
+
<Checkbox.Root size="md">
|
|
111
|
+
<Checkbox.Indicator />
|
|
112
|
+
</Checkbox.Root>
|
|
113
|
+
<Checkbox.Root size="lg">
|
|
114
|
+
<Checkbox.Indicator />
|
|
115
|
+
</Checkbox.Root>
|
|
116
|
+
</div>
|
|
117
|
+
),
|
|
118
|
+
};
|