@jongh/ui 1.6.5
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/.storybook/index.css +1 -0
- package/.storybook/main.ts +40 -0
- package/.storybook/preview.ts +16 -0
- package/.storybook/vitest.setup.ts +9 -0
- package/.turbo/turbo-build.log +79 -0
- package/CHANGELOG.md +54 -0
- package/chromatic.config.json +6 -0
- package/eslint.config.mjs +14 -0
- package/index.html +13 -0
- package/package.json +58 -0
- package/panda.config.ts +13 -0
- package/postcss.config.cjs +3 -0
- package/preset.ts +134 -0
- package/src/component/accordion/ui/index.tsx +80 -0
- package/src/component/accordion/ui/recipe.ts +65 -0
- package/src/component/avatar/ui/index.tsx +47 -0
- package/src/component/avatar/ui/recipe.ts +30 -0
- package/src/component/button/ui/index.tsx +29 -0
- package/src/component/button/ui/recipe.ts +102 -0
- package/src/component/chip/ui/index.tsx +30 -0
- package/src/component/chip/ui/recipe.ts +112 -0
- package/src/component/dialog/ui/index.tsx +73 -0
- package/src/component/dialog/ui/recipe.ts +92 -0
- package/src/component/select/ui/index.tsx +128 -0
- package/src/component/select/ui/recipe.ts +142 -0
- package/src/component/slider/ui/index.tsx +61 -0
- package/src/component/slider/ui/recipe.ts +52 -0
- package/src/component/tabs/ui/index.tsx +61 -0
- package/src/component/tabs/ui/recipe.ts +59 -0
- package/src/hooks/createContext.tsx +34 -0
- package/src/hooks/useComposedRefs.ts +20 -0
- package/src/hooks/useControllableState.ts +87 -0
- package/src/hooks/useKeyboardEvent.ts +58 -0
- package/src/stories/accordion.stories.tsx +63 -0
- package/src/stories/avatar.stories.tsx +33 -0
- package/src/stories/button.stories.tsx +53 -0
- package/src/stories/chip.stories.tsx +69 -0
- package/src/stories/dialog.stories.tsx +134 -0
- package/src/stories/select.stories.tsx +35 -0
- package/src/stories/slider.stories.tsx +31 -0
- package/src/stories/tabs.stories.tsx +63 -0
- package/src/test/accordion.test.tsx +66 -0
- package/src/test/tabs.test.tsx +30 -0
- package/src/types/index.ts +1 -0
- package/src/utils/createStyleContext.tsx +108 -0
- package/src/utils/defineSafe.ts +46 -0
- package/src/utils/getObjectKeys.ts +20 -0
- package/src/vite-env.d.ts +1 -0
- package/storybook-static/assets/Color-F6OSRLHC-CrKta8Qx.js +1 -0
- package/storybook-static/assets/DocsRenderer-CFRXHY34-Crd9Mepd.js +586 -0
- package/storybook-static/assets/_commonjsHelpers-Cpj98o6Y.js +1 -0
- package/storybook-static/assets/accordion.stories-0Om0AnMm.js +50 -0
- package/storybook-static/assets/avatar.stories-DMDsrSks.js +16 -0
- package/storybook-static/assets/axe-Dzet_oDA.js +30 -0
- package/storybook-static/assets/button.stories-CuVC-3x-.js +40 -0
- package/storybook-static/assets/chip.stories-FBIp8XNi.js +48 -0
- package/storybook-static/assets/chunk-XP5HYGXS-D5tuasO7.js +1 -0
- package/storybook-static/assets/createLucideIcon-DmXe7Z8R.js +21 -0
- package/storybook-static/assets/dialog.stories-3WsEvXt4.js +106 -0
- package/storybook-static/assets/entry-preview-Bkgdgq1b.js +10 -0
- package/storybook-static/assets/entry-preview-docs-zLz1Es7d.js +46 -0
- package/storybook-static/assets/iframe-LPPPXabV.js +199 -0
- package/storybook-static/assets/index-Bklpsb39.js +1 -0
- package/storybook-static/assets/index-BrlJLjep.js +24 -0
- package/storybook-static/assets/index-C2tRLqin.js +41 -0
- package/storybook-static/assets/index-CBft-ReK.js +8 -0
- package/storybook-static/assets/index-CSbWd7UJ.js +1 -0
- package/storybook-static/assets/index-ClcD9ViR.js +9 -0
- package/storybook-static/assets/index-Cu4lwwaE.js +1 -0
- package/storybook-static/assets/index-Cvkemp2J.js +1 -0
- package/storybook-static/assets/index-D59aU5s_.js +240 -0
- package/storybook-static/assets/index-DNo8LKN3.js +1 -0
- package/storybook-static/assets/index-DUy19JZU.js +1 -0
- package/storybook-static/assets/index-D_35mznO.js +1 -0
- package/storybook-static/assets/index-DrFu-skq.js +6 -0
- package/storybook-static/assets/index-DvbTp2M2.js +1 -0
- package/storybook-static/assets/index-rtmQni2k.js +1 -0
- package/storybook-static/assets/jsx-runtime-BYYWji4R.js +9 -0
- package/storybook-static/assets/matchers-57EZJSQE-oeXCqs4p.js +14 -0
- package/storybook-static/assets/preview-1l6V4UsQ.js +1 -0
- package/storybook-static/assets/preview-B3PTUHS7.js +1 -0
- package/storybook-static/assets/preview-BBWR9nbA.js +1 -0
- package/storybook-static/assets/preview-BCV5r-Ja.js +1 -0
- package/storybook-static/assets/preview-BWzBA1C2.js +396 -0
- package/storybook-static/assets/preview-Bb56VplF.js +2 -0
- package/storybook-static/assets/preview-Bl8rsKRy.js +1 -0
- package/storybook-static/assets/preview-Bm-a94Ct.js +2 -0
- package/storybook-static/assets/preview-Br-h4d84.js +1 -0
- package/storybook-static/assets/preview-D77C14du.js +34 -0
- package/storybook-static/assets/preview-DC8N7cZb.css +1 -0
- package/storybook-static/assets/preview-DGUiP6tS.js +7 -0
- package/storybook-static/assets/react-18-BPs3tMGP.js +1 -0
- package/storybook-static/assets/select.stories-AN8Hb81Z.js +20 -0
- package/storybook-static/assets/slider.stories-CxOczq0y.js +12 -0
- package/storybook-static/assets/tabs.stories-BbTU4QU3.js +28 -0
- package/storybook-static/favicon.svg +1 -0
- package/storybook-static/iframe.html +666 -0
- package/storybook-static/index.html +193 -0
- package/storybook-static/index.json +1 -0
- package/storybook-static/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/project.json +1 -0
- package/storybook-static/sb-addons/a11y-12/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/a11y-12/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/chromatic-com-storybook-10/manager-bundle.js +331 -0
- package/storybook-static/sb-addons/chromatic-com-storybook-10/manager-bundle.js.LEGAL.txt +51 -0
- package/storybook-static/sb-addons/controls-11/manager-bundle.js +391 -0
- package/storybook-static/sb-addons/controls-11/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-actions-3/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-actions-3/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-backgrounds-5/manager-bundle.js +12 -0
- package/storybook-static/sb-addons/essentials-backgrounds-5/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-controls-2/manager-bundle.js +391 -0
- package/storybook-static/sb-addons/essentials-controls-2/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-docs-4/manager-bundle.js +230 -0
- package/storybook-static/sb-addons/essentials-docs-4/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-measure-8/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-measure-8/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-outline-9/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-outline-9/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-toolbars-7/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-toolbars-7/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-viewport-6/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-viewport-6/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/links-1/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/links-1/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js +3 -0
- package/storybook-static/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/storybook-experimental-addon-test-13/manager-bundle.js +211 -0
- package/storybook-static/sb-addons/storybook-experimental-addon-test-13/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-common-assets/favicon.svg +1 -0
- package/storybook-static/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/sb-manager/globals-module-info.js +1037 -0
- package/storybook-static/sb-manager/globals-runtime.js +40857 -0
- package/storybook-static/sb-manager/globals.js +48 -0
- package/storybook-static/sb-manager/runtime.js +11963 -0
- package/styled-system/css/conditions.mjs +36 -0
- package/styled-system/css/css.d.ts +22 -0
- package/styled-system/css/css.mjs +45 -0
- package/styled-system/css/cva.d.ts +6 -0
- package/styled-system/css/cva.mjs +87 -0
- package/styled-system/css/cx.d.ts +5 -0
- package/styled-system/css/cx.mjs +15 -0
- package/styled-system/css/index.d.ts +5 -0
- package/styled-system/css/index.mjs +4 -0
- package/styled-system/css/sva.d.ts +4 -0
- package/styled-system/css/sva.mjs +41 -0
- package/styled-system/helpers.mjs +336 -0
- package/styled-system/jsx/aspect-ratio.d.ts +10 -0
- package/styled-system/jsx/aspect-ratio.mjs +14 -0
- package/styled-system/jsx/bleed.d.ts +10 -0
- package/styled-system/jsx/bleed.mjs +14 -0
- package/styled-system/jsx/box.d.ts +10 -0
- package/styled-system/jsx/box.mjs +14 -0
- package/styled-system/jsx/center.d.ts +10 -0
- package/styled-system/jsx/center.mjs +14 -0
- package/styled-system/jsx/circle.d.ts +10 -0
- package/styled-system/jsx/circle.mjs +14 -0
- package/styled-system/jsx/container.d.ts +10 -0
- package/styled-system/jsx/container.mjs +14 -0
- package/styled-system/jsx/cq.d.ts +10 -0
- package/styled-system/jsx/cq.mjs +14 -0
- package/styled-system/jsx/divider.d.ts +10 -0
- package/styled-system/jsx/divider.mjs +14 -0
- package/styled-system/jsx/factory-helper.mjs +22 -0
- package/styled-system/jsx/factory.d.ts +3 -0
- package/styled-system/jsx/factory.mjs +80 -0
- package/styled-system/jsx/flex.d.ts +10 -0
- package/styled-system/jsx/flex.mjs +14 -0
- package/styled-system/jsx/float.d.ts +10 -0
- package/styled-system/jsx/float.mjs +14 -0
- package/styled-system/jsx/grid-item.d.ts +10 -0
- package/styled-system/jsx/grid-item.mjs +14 -0
- package/styled-system/jsx/grid.d.ts +10 -0
- package/styled-system/jsx/grid.mjs +14 -0
- package/styled-system/jsx/hstack.d.ts +10 -0
- package/styled-system/jsx/hstack.mjs +14 -0
- package/styled-system/jsx/index.d.ts +24 -0
- package/styled-system/jsx/index.mjs +22 -0
- package/styled-system/jsx/is-valid-prop.d.ts +11 -0
- package/styled-system/jsx/is-valid-prop.mjs +17 -0
- package/styled-system/jsx/link-overlay.d.ts +10 -0
- package/styled-system/jsx/link-overlay.mjs +14 -0
- package/styled-system/jsx/spacer.d.ts +10 -0
- package/styled-system/jsx/spacer.mjs +14 -0
- package/styled-system/jsx/square.d.ts +10 -0
- package/styled-system/jsx/square.mjs +14 -0
- package/styled-system/jsx/stack.d.ts +10 -0
- package/styled-system/jsx/stack.mjs +14 -0
- package/styled-system/jsx/visually-hidden.d.ts +10 -0
- package/styled-system/jsx/visually-hidden.mjs +14 -0
- package/styled-system/jsx/vstack.d.ts +10 -0
- package/styled-system/jsx/vstack.mjs +14 -0
- package/styled-system/jsx/wrap.d.ts +10 -0
- package/styled-system/jsx/wrap.mjs +14 -0
- package/styled-system/patterns/aspect-ratio.d.ts +21 -0
- package/styled-system/patterns/aspect-ratio.mjs +38 -0
- package/styled-system/patterns/bleed.d.ts +22 -0
- package/styled-system/patterns/bleed.mjs +24 -0
- package/styled-system/patterns/box.d.ts +21 -0
- package/styled-system/patterns/box.mjs +15 -0
- package/styled-system/patterns/center.d.ts +21 -0
- package/styled-system/patterns/center.mjs +21 -0
- package/styled-system/patterns/circle.d.ts +21 -0
- package/styled-system/patterns/circle.mjs +25 -0
- package/styled-system/patterns/container.d.ts +21 -0
- package/styled-system/patterns/container.mjs +21 -0
- package/styled-system/patterns/cq.d.ts +22 -0
- package/styled-system/patterns/cq.mjs +21 -0
- package/styled-system/patterns/divider.d.ts +23 -0
- package/styled-system/patterns/divider.mjs +25 -0
- package/styled-system/patterns/flex.d.ts +27 -0
- package/styled-system/patterns/flex.mjs +26 -0
- package/styled-system/patterns/float.d.ts +24 -0
- package/styled-system/patterns/float.mjs +52 -0
- package/styled-system/patterns/grid-item.d.ts +26 -0
- package/styled-system/patterns/grid-item.mjs +25 -0
- package/styled-system/patterns/grid.d.ts +25 -0
- package/styled-system/patterns/grid.mjs +27 -0
- package/styled-system/patterns/hstack.d.ts +22 -0
- package/styled-system/patterns/hstack.mjs +24 -0
- package/styled-system/patterns/index.d.ts +21 -0
- package/styled-system/patterns/index.mjs +20 -0
- package/styled-system/patterns/link-overlay.d.ts +21 -0
- package/styled-system/patterns/link-overlay.mjs +24 -0
- package/styled-system/patterns/spacer.d.ts +21 -0
- package/styled-system/patterns/spacer.mjs +21 -0
- package/styled-system/patterns/square.d.ts +21 -0
- package/styled-system/patterns/square.mjs +24 -0
- package/styled-system/patterns/stack.d.ts +24 -0
- package/styled-system/patterns/stack.mjs +24 -0
- package/styled-system/patterns/visually-hidden.d.ts +21 -0
- package/styled-system/patterns/visually-hidden.mjs +18 -0
- package/styled-system/patterns/vstack.d.ts +22 -0
- package/styled-system/patterns/vstack.mjs +24 -0
- package/styled-system/patterns/wrap.d.ts +25 -0
- package/styled-system/patterns/wrap.mjs +25 -0
- package/styled-system/tokens/index.d.ts +9 -0
- package/styled-system/tokens/index.mjs +1992 -0
- package/styled-system/tokens/tokens.d.ts +60 -0
- package/styled-system/types/composition.d.ts +164 -0
- package/styled-system/types/conditions.d.ts +274 -0
- package/styled-system/types/csstype.d.ts +21298 -0
- package/styled-system/types/global.d.ts +20 -0
- package/styled-system/types/index.d.ts +8 -0
- package/styled-system/types/jsx.d.ts +52 -0
- package/styled-system/types/parts.d.ts +8 -0
- package/styled-system/types/pattern.d.ts +78 -0
- package/styled-system/types/prop-type.d.ts +235 -0
- package/styled-system/types/recipe.d.ts +181 -0
- package/styled-system/types/selectors.d.ts +59 -0
- package/styled-system/types/static-css.d.ts +56 -0
- package/styled-system/types/style-props.d.ts +7468 -0
- package/styled-system/types/system-types.d.ts +109 -0
- package/tsconfig.json +13 -0
- package/turbo/generators/config.cjs +7 -0
- package/turbo/generators/stories.cjs +23 -0
- package/turbo/generators/templates/stories.tsx.hbs +16 -0
- package/turbo/generators/templates/ui.tsx.hbs +8 -0
- package/turbo/generators/ui.cjs +19 -0
- package/vite.config.ts +7 -0
- package/vitest.config.ts +45 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { sva } from "@styled-system/css"
|
|
2
|
+
|
|
3
|
+
export const recipe = sva({
|
|
4
|
+
className: "select",
|
|
5
|
+
slots: [
|
|
6
|
+
"root",
|
|
7
|
+
"group",
|
|
8
|
+
"value",
|
|
9
|
+
"trigger",
|
|
10
|
+
"viewport",
|
|
11
|
+
"content",
|
|
12
|
+
"label",
|
|
13
|
+
"item",
|
|
14
|
+
"itemIndicator",
|
|
15
|
+
"separator",
|
|
16
|
+
],
|
|
17
|
+
base: {
|
|
18
|
+
trigger: {
|
|
19
|
+
display: "flex",
|
|
20
|
+
h: "10",
|
|
21
|
+
w: "full",
|
|
22
|
+
alignItems: "center",
|
|
23
|
+
justifyContent: "space-between",
|
|
24
|
+
rounded: "md",
|
|
25
|
+
border: "input",
|
|
26
|
+
bg: "transparent",
|
|
27
|
+
px: "3",
|
|
28
|
+
py: "2",
|
|
29
|
+
textStyle: "sm",
|
|
30
|
+
cursor: "pointer",
|
|
31
|
+
ringColor: "background",
|
|
32
|
+
|
|
33
|
+
_placeholder: {
|
|
34
|
+
color: "muted.foreground",
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
_focus: {
|
|
38
|
+
ringWidth: "1",
|
|
39
|
+
ringColor: "ring",
|
|
40
|
+
outlineOffset: "1",
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
_disabled: {
|
|
44
|
+
cursor: "not-allowed",
|
|
45
|
+
opacity: "0.5",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
viewport: {
|
|
49
|
+
"&:is([data-position=popper])": {
|
|
50
|
+
h: "var(--radix-select-trigger-height)",
|
|
51
|
+
w: "full",
|
|
52
|
+
minW: "var(--radix-select-trigger-width)",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
content: {
|
|
56
|
+
position: "relative",
|
|
57
|
+
zIndex: 50,
|
|
58
|
+
minW: "full",
|
|
59
|
+
overflow: "hidden",
|
|
60
|
+
rounded: "md",
|
|
61
|
+
border: "base",
|
|
62
|
+
bg: "popover",
|
|
63
|
+
color: "popover.foreground",
|
|
64
|
+
shadow: "md",
|
|
65
|
+
maxH: "96",
|
|
66
|
+
|
|
67
|
+
"&:is([data-state=open])": {
|
|
68
|
+
animationName: "fadeIn",
|
|
69
|
+
animationState: "ease-in",
|
|
70
|
+
animationDuration: "slowest",
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
"&:is(&[data-state=closed])": {
|
|
74
|
+
animationName: "slideInDown",
|
|
75
|
+
animationState: "ease-in",
|
|
76
|
+
animationDuration: "slowest",
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
"&:is([data-position=popper])": {
|
|
80
|
+
"&:is([data-side=top])": {
|
|
81
|
+
translateY: "-1",
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
"&:is([data-side=bottom])": {
|
|
85
|
+
translateY: "1",
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
"&:is([data-side=left])": {
|
|
89
|
+
translateX: "-1",
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
"&:is([data-side=right])": {
|
|
93
|
+
translateX: "1",
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
label: {
|
|
98
|
+
py: "1.5",
|
|
99
|
+
pl: "8",
|
|
100
|
+
pr: "2",
|
|
101
|
+
textStyle: "sm",
|
|
102
|
+
fontWeight: "semibold",
|
|
103
|
+
},
|
|
104
|
+
item: {
|
|
105
|
+
position: "relative",
|
|
106
|
+
display: "flex",
|
|
107
|
+
cursor: "default",
|
|
108
|
+
userSelect: "none",
|
|
109
|
+
alignItems: "center",
|
|
110
|
+
rounded: "sm",
|
|
111
|
+
py: "1.5",
|
|
112
|
+
pl: "8",
|
|
113
|
+
pr: "2",
|
|
114
|
+
textStyle: "sm",
|
|
115
|
+
|
|
116
|
+
_focus: {
|
|
117
|
+
bg: "accent",
|
|
118
|
+
color: "accent.foreground",
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
["&[data-disabled]"]: {
|
|
122
|
+
pointerEvents: "none",
|
|
123
|
+
opacity: "0.5",
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
itemIndicator: {
|
|
127
|
+
position: "absolute",
|
|
128
|
+
left: "2",
|
|
129
|
+
display: "flex",
|
|
130
|
+
h: "3.5",
|
|
131
|
+
w: "3.5",
|
|
132
|
+
alignItems: "center",
|
|
133
|
+
justifyContent: "center",
|
|
134
|
+
},
|
|
135
|
+
separator: {
|
|
136
|
+
mx: "-1",
|
|
137
|
+
my: "1",
|
|
138
|
+
h: "1",
|
|
139
|
+
bg: "muted",
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
})
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { css, cx } from "@styled-system/css"
|
|
2
|
+
import { Slider as SliderPrimitive } from "radix-ui"
|
|
3
|
+
import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"
|
|
4
|
+
|
|
5
|
+
import { recipe } from "./recipe"
|
|
6
|
+
|
|
7
|
+
export const Root = forwardRef<
|
|
8
|
+
ElementRef<typeof SliderPrimitive.Root>,
|
|
9
|
+
ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
|
|
10
|
+
>(({ className, ...props }, ref) => {
|
|
11
|
+
const styles = recipe.raw()
|
|
12
|
+
return (
|
|
13
|
+
<SliderPrimitive.Root
|
|
14
|
+
ref={ref}
|
|
15
|
+
className={cx(css(styles.root), className)}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
export const Track = forwardRef<
|
|
22
|
+
ElementRef<typeof SliderPrimitive.Track>,
|
|
23
|
+
ComponentPropsWithoutRef<typeof SliderPrimitive.Track>
|
|
24
|
+
>(({ className, ...props }, ref) => {
|
|
25
|
+
const styles = recipe.raw()
|
|
26
|
+
return (
|
|
27
|
+
<SliderPrimitive.Track
|
|
28
|
+
ref={ref}
|
|
29
|
+
className={cx(css(styles.track), className)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
export const Range = forwardRef<
|
|
36
|
+
ElementRef<typeof SliderPrimitive.Range>,
|
|
37
|
+
ComponentPropsWithoutRef<typeof SliderPrimitive.Range>
|
|
38
|
+
>(({ className, ...props }, ref) => {
|
|
39
|
+
const styles = recipe.raw()
|
|
40
|
+
return (
|
|
41
|
+
<SliderPrimitive.Range
|
|
42
|
+
ref={ref}
|
|
43
|
+
className={cx(css(styles.range), className)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
export const Thumb = forwardRef<
|
|
50
|
+
ElementRef<typeof SliderPrimitive.Thumb>,
|
|
51
|
+
ComponentPropsWithoutRef<typeof SliderPrimitive.Thumb>
|
|
52
|
+
>(({ className, ...props }, ref) => {
|
|
53
|
+
const styles = recipe.raw()
|
|
54
|
+
return (
|
|
55
|
+
<SliderPrimitive.Thumb
|
|
56
|
+
ref={ref}
|
|
57
|
+
className={cx(css(styles.thumb), className)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
)
|
|
61
|
+
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { sva } from "@styled-system/css"
|
|
2
|
+
|
|
3
|
+
export const recipe = sva({
|
|
4
|
+
slots: ["root", "track", "range", "thumb"],
|
|
5
|
+
base: {
|
|
6
|
+
root: {
|
|
7
|
+
position: "relative",
|
|
8
|
+
display: "flex",
|
|
9
|
+
touchAction: "none",
|
|
10
|
+
userSelect: "none",
|
|
11
|
+
alignItems: "center",
|
|
12
|
+
},
|
|
13
|
+
track: {
|
|
14
|
+
position: "relative",
|
|
15
|
+
h: "2",
|
|
16
|
+
w: "full",
|
|
17
|
+
flexGrow: "1",
|
|
18
|
+
overflow: "hidden",
|
|
19
|
+
rounded: "full",
|
|
20
|
+
bg: "secondary",
|
|
21
|
+
},
|
|
22
|
+
range: {
|
|
23
|
+
position: "absolute",
|
|
24
|
+
h: "full",
|
|
25
|
+
bg: "primary",
|
|
26
|
+
},
|
|
27
|
+
thumb: {
|
|
28
|
+
display: "block",
|
|
29
|
+
h: "5",
|
|
30
|
+
w: "5",
|
|
31
|
+
cursor: "pointer",
|
|
32
|
+
rounded: "full",
|
|
33
|
+
borderWidth: "2px",
|
|
34
|
+
borderStyle: "solid",
|
|
35
|
+
borderColor: "primary",
|
|
36
|
+
bg: "background",
|
|
37
|
+
ringColor: "background",
|
|
38
|
+
transition: "colors",
|
|
39
|
+
|
|
40
|
+
_focusVisible: {
|
|
41
|
+
ringWidth: "1",
|
|
42
|
+
ringColor: "ring",
|
|
43
|
+
ringOffset: "1",
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
_disabled: {
|
|
47
|
+
pointerEvents: "none",
|
|
48
|
+
opacity: "0.5",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
})
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { css, cx } from "@styled-system/css"
|
|
2
|
+
import { Tabs as TabsPrimitive } from "radix-ui"
|
|
3
|
+
import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"
|
|
4
|
+
|
|
5
|
+
import { recipe } from "./recipe"
|
|
6
|
+
|
|
7
|
+
export const Root = forwardRef<
|
|
8
|
+
ElementRef<typeof TabsPrimitive.Root>,
|
|
9
|
+
ComponentPropsWithoutRef<typeof TabsPrimitive.Root>
|
|
10
|
+
>(({ className, ...props }, ref) => {
|
|
11
|
+
const styles = recipe.raw()
|
|
12
|
+
return (
|
|
13
|
+
<TabsPrimitive.Root
|
|
14
|
+
ref={ref}
|
|
15
|
+
className={cx(css(styles.root), className)}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
export const List = forwardRef<
|
|
22
|
+
ElementRef<typeof TabsPrimitive.List>,
|
|
23
|
+
ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
|
24
|
+
>(({ className, ...props }, ref) => {
|
|
25
|
+
const styles = recipe.raw()
|
|
26
|
+
return (
|
|
27
|
+
<TabsPrimitive.List
|
|
28
|
+
ref={ref}
|
|
29
|
+
className={cx(css(styles.list), className)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
export const Trigger = forwardRef<
|
|
36
|
+
ElementRef<typeof TabsPrimitive.Trigger>,
|
|
37
|
+
ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
|
38
|
+
>(({ className, ...props }, ref) => {
|
|
39
|
+
const styles = recipe.raw()
|
|
40
|
+
return (
|
|
41
|
+
<TabsPrimitive.Trigger
|
|
42
|
+
ref={ref}
|
|
43
|
+
className={cx(css(styles.trigger), className)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
export const Content = forwardRef<
|
|
50
|
+
ElementRef<typeof TabsPrimitive.Content>,
|
|
51
|
+
ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
|
52
|
+
>(({ className, ...props }, ref) => {
|
|
53
|
+
const styles = recipe.raw()
|
|
54
|
+
return (
|
|
55
|
+
<TabsPrimitive.Content
|
|
56
|
+
ref={ref}
|
|
57
|
+
className={cx(css(styles.content), className)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
)
|
|
61
|
+
})
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { sva } from "@styled-system/css"
|
|
2
|
+
|
|
3
|
+
export const recipe = sva({
|
|
4
|
+
slots: ["root", "list", "trigger", "content"],
|
|
5
|
+
base: {
|
|
6
|
+
list: {
|
|
7
|
+
display: "inline-flex",
|
|
8
|
+
h: "10",
|
|
9
|
+
alignItems: "center",
|
|
10
|
+
justifyContent: "center",
|
|
11
|
+
rounded: "md",
|
|
12
|
+
bg: "muted",
|
|
13
|
+
p: "1",
|
|
14
|
+
color: "muted.foreground",
|
|
15
|
+
},
|
|
16
|
+
trigger: {
|
|
17
|
+
display: "inline-flex",
|
|
18
|
+
alignItems: "center",
|
|
19
|
+
justifyContent: "center",
|
|
20
|
+
whiteSpace: "nowrap",
|
|
21
|
+
rounded: "sm",
|
|
22
|
+
px: "3",
|
|
23
|
+
py: "1.5",
|
|
24
|
+
textStyle: "sm",
|
|
25
|
+
fontWeight: "medium",
|
|
26
|
+
transition: "all",
|
|
27
|
+
cursor: "pointer",
|
|
28
|
+
ringColor: "background",
|
|
29
|
+
|
|
30
|
+
_focusVisible: {
|
|
31
|
+
ringWidth: "1",
|
|
32
|
+
ringColor: "ring",
|
|
33
|
+
ringOffset: "1",
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
_disabled: {
|
|
37
|
+
pointerEvents: "none",
|
|
38
|
+
opacity: "50%",
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
"&:is([data-state=active])": {
|
|
42
|
+
bg: "background",
|
|
43
|
+
color: "foreground",
|
|
44
|
+
shadow: "sm",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
content: {
|
|
48
|
+
mt: "2",
|
|
49
|
+
ringColor: "background",
|
|
50
|
+
|
|
51
|
+
_focusVisible: {
|
|
52
|
+
outlineWidth: "2",
|
|
53
|
+
outlineOffset: "2",
|
|
54
|
+
ringWidth: "2",
|
|
55
|
+
ringColor: "ring",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
2
|
+
import * as React from "react"
|
|
3
|
+
|
|
4
|
+
export function createContext<ContextValueType extends object | null>(
|
|
5
|
+
rootComponentName: string,
|
|
6
|
+
defaultContext?: ContextValueType,
|
|
7
|
+
) {
|
|
8
|
+
const C = React.createContext<ContextValueType | undefined>(defaultContext) //context 생성
|
|
9
|
+
const Provider = (
|
|
10
|
+
props: ContextValueType & { children: React.ReactNode },
|
|
11
|
+
) => {
|
|
12
|
+
const { children, ...context } = props
|
|
13
|
+
// Only re-memoize when prop values change
|
|
14
|
+
const value = React.useMemo(
|
|
15
|
+
() => context,
|
|
16
|
+
Object.values(context),
|
|
17
|
+
) as ContextValueType
|
|
18
|
+
|
|
19
|
+
return <C.Provider value={value}>{children}</C.Provider>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function useContext(consumerName?: string) {
|
|
23
|
+
const context = React.useContext(C)
|
|
24
|
+
if (context) return context
|
|
25
|
+
if (defaultContext !== undefined) return defaultContext
|
|
26
|
+
// if a defaultContext wasn't specified, it's a required context.
|
|
27
|
+
throw new Error(
|
|
28
|
+
`\`${consumerName}\` must be used within \`${rootComponentName}\``,
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
Provider.displayName = rootComponentName + "Provider"
|
|
33
|
+
return [Provider, useContext] as const
|
|
34
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useCallback } from "react"
|
|
2
|
+
|
|
3
|
+
type PossibleRef<T> = React.Ref<T> | undefined
|
|
4
|
+
|
|
5
|
+
function setRef<T>(ref: PossibleRef<T>, value: T) {
|
|
6
|
+
if (typeof ref === "function") {
|
|
7
|
+
ref(value)
|
|
8
|
+
} else if (ref !== null && ref !== undefined) {
|
|
9
|
+
;(ref as React.MutableRefObject<T>).current = value
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function composeRefs<T>(...refs: Array<PossibleRef<T>>) {
|
|
14
|
+
return (node: T) => refs.forEach((ref) => setRef(ref, node))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function useComposedRefs<T>(...refs: Array<PossibleRef<T>>) {
|
|
18
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
19
|
+
return useCallback(composeRefs(...refs), refs)
|
|
20
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import {
|
|
3
|
+
Dispatch,
|
|
4
|
+
SetStateAction,
|
|
5
|
+
useCallback,
|
|
6
|
+
useEffect,
|
|
7
|
+
useMemo,
|
|
8
|
+
useRef,
|
|
9
|
+
useState,
|
|
10
|
+
} from "react"
|
|
11
|
+
|
|
12
|
+
export const useCallbackRef = <T extends (...args: any[]) => any>(
|
|
13
|
+
callback?: T,
|
|
14
|
+
) => {
|
|
15
|
+
const callbackRef = useRef(callback)
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
callbackRef.current = callback
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
return useMemo(
|
|
22
|
+
() =>
|
|
23
|
+
(...args: any[]) =>
|
|
24
|
+
callbackRef.current?.(...args),
|
|
25
|
+
[],
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
//그냥 useState인데, onChange 이벤트를 할수있게 해준 hook
|
|
29
|
+
export const useUncontrolledState = <T>({
|
|
30
|
+
defaultValue,
|
|
31
|
+
onChange,
|
|
32
|
+
}: {
|
|
33
|
+
defaultValue?: T | undefined
|
|
34
|
+
onChange?: (params: T) => void
|
|
35
|
+
}) => {
|
|
36
|
+
const unControlledState = useState(defaultValue)
|
|
37
|
+
const [value] = unControlledState
|
|
38
|
+
const handleChange = useCallbackRef(onChange)
|
|
39
|
+
const ref = useRef(value)
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (ref.current !== value) {
|
|
42
|
+
handleChange(value)
|
|
43
|
+
ref.current = value
|
|
44
|
+
}
|
|
45
|
+
}, [value, ref, handleChange])
|
|
46
|
+
|
|
47
|
+
return unControlledState
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
type SetStateFn<T> = (prev: T) => void
|
|
51
|
+
|
|
52
|
+
type UseControllableState<T> = {
|
|
53
|
+
prop?: T | undefined
|
|
54
|
+
defaultProp?: T | undefined
|
|
55
|
+
onChange?: (state: T) => void
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const useControlledState = <T>({
|
|
59
|
+
prop,
|
|
60
|
+
defaultProp,
|
|
61
|
+
onChange,
|
|
62
|
+
}: UseControllableState<T>) => {
|
|
63
|
+
const isControlled = prop !== undefined
|
|
64
|
+
const [unControlledProp, setUncontrolledProp] = useUncontrolledState({
|
|
65
|
+
defaultValue: defaultProp,
|
|
66
|
+
onChange,
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
const value = isControlled ? prop : unControlledProp
|
|
70
|
+
const handleChange = useCallbackRef(onChange)
|
|
71
|
+
const setValue: Dispatch<SetStateAction<T | undefined>> = useCallback(
|
|
72
|
+
(nextValue) => {
|
|
73
|
+
if (isControlled) {
|
|
74
|
+
const setter = nextValue as SetStateFn<T>
|
|
75
|
+
const value = typeof nextValue === "function" ? setter(prop) : nextValue
|
|
76
|
+
if (value !== prop) {
|
|
77
|
+
handleChange?.(value as T)
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
setUncontrolledProp(nextValue)
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
[isControlled, prop, setUncontrolledProp, handleChange],
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
return [value, setValue] as const
|
|
87
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
2
|
+
import { KeyboardEvent, useCallback, useRef } from "react"
|
|
3
|
+
|
|
4
|
+
type UseKeybaordEvent = {
|
|
5
|
+
keyList: string[]
|
|
6
|
+
changeIndex?: (index: number) => void
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const useKeyboardEvent = ({
|
|
10
|
+
keyList,
|
|
11
|
+
changeIndex,
|
|
12
|
+
}: UseKeybaordEvent) => {
|
|
13
|
+
const refs = useRef<HTMLElement[]>([])
|
|
14
|
+
|
|
15
|
+
const handleKeyDown = useCallback(
|
|
16
|
+
(event: KeyboardEvent<HTMLElement>, callback?: () => void) => {
|
|
17
|
+
if (!keyList.includes(event.key)) return
|
|
18
|
+
const length = refs.current.length
|
|
19
|
+
const target = event.target as HTMLElement
|
|
20
|
+
const currentIndex = refs.current.indexOf(target)
|
|
21
|
+
event.preventDefault()
|
|
22
|
+
|
|
23
|
+
let nextIndex = 0
|
|
24
|
+
switch (event.key) {
|
|
25
|
+
case "ArrowDown":
|
|
26
|
+
nextIndex = (currentIndex + 1) % length
|
|
27
|
+
break
|
|
28
|
+
case "ArrowUp":
|
|
29
|
+
nextIndex = (currentIndex - 1 + length) % length
|
|
30
|
+
break
|
|
31
|
+
case "ArrowRight":
|
|
32
|
+
nextIndex = (currentIndex + 1) % length
|
|
33
|
+
break
|
|
34
|
+
case "ArrowLeft":
|
|
35
|
+
nextIndex = (currentIndex - 1 + length) % length
|
|
36
|
+
break
|
|
37
|
+
case "Home":
|
|
38
|
+
nextIndex = 0
|
|
39
|
+
break
|
|
40
|
+
case "End":
|
|
41
|
+
nextIndex = length - 1
|
|
42
|
+
break
|
|
43
|
+
case "Tab":
|
|
44
|
+
nextIndex = (currentIndex + 1) % length
|
|
45
|
+
break
|
|
46
|
+
case "Enter":
|
|
47
|
+
callback?.()
|
|
48
|
+
}
|
|
49
|
+
changeIndex?.(nextIndex)
|
|
50
|
+
refs.current[nextIndex]?.focus()
|
|
51
|
+
},
|
|
52
|
+
[],
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return { refs, handleKeyDown }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default useKeyboardEvent
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
import { expect, userEvent, waitFor } from "@storybook/test"
|
|
3
|
+
import { css } from "@styled-system/css"
|
|
4
|
+
|
|
5
|
+
import * as Accordion from "../component/accordion/ui"
|
|
6
|
+
export default {
|
|
7
|
+
title: "Accordion",
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
} satisfies Meta<typeof Accordion>
|
|
10
|
+
|
|
11
|
+
type Story = StoryObj<typeof Accordion>
|
|
12
|
+
|
|
13
|
+
export const Primary: Story = {
|
|
14
|
+
render: () => {
|
|
15
|
+
return (
|
|
16
|
+
<div style={{ width: "500px" }}>
|
|
17
|
+
<Accordion.Root type="single" collapsible>
|
|
18
|
+
<Accordion.Item value="1">
|
|
19
|
+
<Accordion.Header>
|
|
20
|
+
<Accordion.Trigger
|
|
21
|
+
className={css({
|
|
22
|
+
color: "red.100",
|
|
23
|
+
})}
|
|
24
|
+
>
|
|
25
|
+
1번
|
|
26
|
+
</Accordion.Trigger>
|
|
27
|
+
</Accordion.Header>
|
|
28
|
+
<Accordion.Content>
|
|
29
|
+
<div>내용1</div>
|
|
30
|
+
</Accordion.Content>
|
|
31
|
+
</Accordion.Item>
|
|
32
|
+
<Accordion.Item value="2">
|
|
33
|
+
<Accordion.Header>
|
|
34
|
+
<Accordion.Trigger>2번</Accordion.Trigger>
|
|
35
|
+
</Accordion.Header>
|
|
36
|
+
<Accordion.Content>
|
|
37
|
+
<div>내용1</div>
|
|
38
|
+
</Accordion.Content>
|
|
39
|
+
</Accordion.Item>
|
|
40
|
+
<Accordion.Item value="3">
|
|
41
|
+
<Accordion.Header>
|
|
42
|
+
<Accordion.Trigger>3번</Accordion.Trigger>
|
|
43
|
+
</Accordion.Header>
|
|
44
|
+
<Accordion.Content>내용3</Accordion.Content>
|
|
45
|
+
</Accordion.Item>
|
|
46
|
+
</Accordion.Root>
|
|
47
|
+
</div>
|
|
48
|
+
)
|
|
49
|
+
},
|
|
50
|
+
play: async ({ canvas }) => {
|
|
51
|
+
const Item = canvas.getByText("1번")
|
|
52
|
+
expect(Item).toBeInTheDocument()
|
|
53
|
+
//토글로 내용이 열고 닫히는지 확인
|
|
54
|
+
await userEvent.click(Item)
|
|
55
|
+
await expect(canvas.getByText("내용1")).toBeInTheDocument()
|
|
56
|
+
|
|
57
|
+
await userEvent.click(Item)
|
|
58
|
+
await waitFor(async () => {
|
|
59
|
+
const Content = canvas.queryByText("내용1")
|
|
60
|
+
expect(Content).toBeNull()
|
|
61
|
+
})
|
|
62
|
+
},
|
|
63
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
|
|
3
|
+
import * as Avatar from "../component/avatar/ui"
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: "Avatar",
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
} satisfies Meta<typeof Avatar>
|
|
9
|
+
|
|
10
|
+
type Story = StoryObj<typeof Avatar>
|
|
11
|
+
|
|
12
|
+
export const Primary: Story = {
|
|
13
|
+
args: {},
|
|
14
|
+
render: () => {
|
|
15
|
+
return (
|
|
16
|
+
<Avatar.Root>
|
|
17
|
+
<Avatar.Image src="https://encrypted-tbn3.gstatic.com/licensed-image?q=tbn:ANd9GcSDvLC5bOMlnrUBoojLDYnfS0S8G6kuUgQfcFq6d60TsnCmfNGimIc4pIgCmTHdnLaIgxGHBcdNeJ6FAoE" />
|
|
18
|
+
</Avatar.Root>
|
|
19
|
+
)
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const Fallback: Story = {
|
|
24
|
+
args: {},
|
|
25
|
+
render: () => {
|
|
26
|
+
return (
|
|
27
|
+
<Avatar.Root>
|
|
28
|
+
<Avatar.Image src="" />
|
|
29
|
+
<Avatar.Fallback>JD</Avatar.Fallback>
|
|
30
|
+
</Avatar.Root>
|
|
31
|
+
)
|
|
32
|
+
},
|
|
33
|
+
}
|