@crystallize/design-system 0.2.0 → 1.0.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/CHANGELOG.md +10 -0
- package/dist/index.css +1319 -827
- package/dist/index.d.ts +98 -43
- package/dist/index.js +982 -578
- package/dist/index.mjs +973 -573
- package/package.json +40 -23
- package/readme.md +9 -0
- package/src/Tokens.stories.tsx +18 -0
- package/src/action-menu/ActionMenu.stories.tsx +3 -1
- package/src/action-menu/action-item.tsx +1 -9
- package/src/action-menu/action-menu.css +38 -0
- package/src/action-menu/action-menu.tsx +4 -13
- package/src/action-menu/index.tsx +2 -0
- package/src/avatar/Avatar.stories.tsx +20 -0
- package/src/avatar/avatar.css +23 -0
- package/src/avatar/avatar.tsx +34 -0
- package/src/avatar/get-initials.ts +5 -0
- package/src/avatar/index.ts +1 -0
- package/src/button/Button.stories.tsx +64 -22
- package/src/button/button.css +116 -0
- package/src/button/button.tsx +119 -33
- package/src/button/index.ts +1 -1
- package/src/card/card.css +7 -0
- package/src/card/card.stories.tsx +2 -2
- package/src/card/card.tsx +6 -4
- package/src/card/index.ts +2 -0
- package/src/checkbox/checkbox.css +30 -0
- package/src/checkbox/checkbox.tsx +6 -14
- package/src/colors/Colors.stories.tsx +127 -0
- package/src/colors/color-defaults.json +15 -0
- package/src/colors/color-pairing.json +12 -0
- package/src/colors/colors.json +158 -0
- package/src/colors/index.ts +1 -0
- package/src/colors/old-to-new.txt +19 -0
- package/src/colors/types.ts +29 -0
- package/src/dialog/Dialog.stories.tsx +9 -6
- package/src/dialog/confirm-dialog.tsx +5 -2
- package/src/dialog/dialog.css +27 -0
- package/src/dialog/dialog.tsx +18 -20
- package/src/dialog/types.ts +4 -1
- package/src/dropdown-menu/DropdownMenu.stories.tsx +6 -14
- package/src/dropdown-menu/dropdown-menu-item.tsx +1 -10
- package/src/dropdown-menu/dropdown-menu-label.tsx +1 -8
- package/src/dropdown-menu/dropdown-menu-root.tsx +9 -5
- package/src/dropdown-menu/dropdown-menu.css +20 -0
- package/src/dropdown-menu/index.ts +2 -0
- package/src/icon-button/IconButton.stories.tsx +9 -6
- package/src/icon-button/icon-button.css +40 -0
- package/src/icon-button/icon-button.tsx +14 -22
- package/src/iconography/Icon.stories.tsx +47 -0
- package/src/{icons → iconography}/arrow.tsx +0 -0
- package/src/iconography/atom.tsx +59 -0
- package/src/{icons → iconography}/cancel.tsx +0 -0
- package/src/iconography/copy.tsx +24 -0
- package/src/iconography/crystal.tsx +93 -0
- package/src/iconography/edit.tsx +30 -0
- package/src/iconography/error.tsx +40 -0
- package/src/{icons → iconography}/glasses.tsx +0 -0
- package/src/{icons → iconography}/graphQL.tsx +0 -0
- package/src/{icons → iconography}/index.ts +10 -2
- package/src/iconography/info.tsx +41 -0
- package/src/{icons → iconography}/nail-polish.tsx +0 -0
- package/src/iconography/particle.tsx +88 -0
- package/src/iconography/triangle.tsx +27 -0
- package/src/iconography/warning.tsx +51 -0
- package/src/index.css +11 -0
- package/src/index.ts +12 -2
- package/src/inline-radio/inline-radio.css +20 -0
- package/src/inline-radio/inline-radio.stories.tsx +1 -1
- package/src/inline-radio/inline-radio.tsx +4 -14
- package/src/input/Input.stories.tsx +8 -1
- package/src/input/input.css +7 -0
- package/src/input/input.tsx +8 -21
- package/src/input-with-label/InputWithLabel.stories.tsx +98 -0
- package/src/input-with-label/index.ts +3 -0
- package/src/input-with-label/input-with-label.css +35 -0
- package/src/input-with-label/input-with-label.tsx +59 -0
- package/src/label/label.css +3 -0
- package/src/label/label.tsx +3 -1
- package/src/progress/progress.css +7 -0
- package/src/progress/progress.tsx +8 -7
- package/src/radio/radio.css +20 -0
- package/src/radio/radio.tsx +4 -11
- package/src/select/select-item.tsx +1 -10
- package/src/select/select-root.tsx +5 -12
- package/src/select/select.css +28 -0
- package/src/select/select.stories.tsx +12 -0
- package/src/select/select.ts +2 -0
- package/src/spinner/Spinner.stories.tsx +19 -0
- package/src/spinner/index.tsx +48 -0
- package/src/spinner/spinner.css +11 -0
- package/tailwind.config.cjs +51 -0
- package/src/button copy/ButtonCopy.stories.tsx +0 -86
- package/src/button copy/button.tsx +0 -61
- package/src/button copy/index.ts +0 -3
- package/src/colors/Colors.stories.mdx +0 -33
- package/src/icons/Iconography.stories.mdx +0 -45
- package/src/icons/dots.tsx +0 -24
- package/src/icons/error.tsx +0 -43
- package/src/icons/info.tsx +0 -46
- package/src/icons/warning.tsx +0 -55
- package/src/text-field/TextField.stories.tsx +0 -20
- package/src/text-field/index.ts +0 -1
- package/src/text-field/text-field.tsx +0 -60
|
@@ -15,9 +15,9 @@ export default meta;
|
|
|
15
15
|
type Story = StoryObj<typeof Dialog>;
|
|
16
16
|
|
|
17
17
|
const Lorem = () => (
|
|
18
|
-
<p className="
|
|
18
|
+
<p className="leading-6">
|
|
19
19
|
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Reiciendis neque id, blanditiis exercitationem doloremque
|
|
20
|
-
quam ab minima architecto culpa
|
|
20
|
+
quam ab minima architecto culpa.
|
|
21
21
|
</p>
|
|
22
22
|
);
|
|
23
23
|
|
|
@@ -54,10 +54,13 @@ export const ComponentWithDangerAction: Story = {
|
|
|
54
54
|
<Dialog.Content>
|
|
55
55
|
<Dialog.Title>A Dialog</Dialog.Title>
|
|
56
56
|
<div>
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
<Dialog.Description>
|
|
58
|
+
<Lorem />
|
|
59
|
+
</Dialog.Description>
|
|
60
|
+
|
|
61
|
+
<div className="mt-8 flex justify-end gap-4">
|
|
62
|
+
<Button>Cancel</Button>
|
|
63
|
+
<Button intent="danger">Delete</Button>
|
|
61
64
|
</div>
|
|
62
65
|
</div>
|
|
63
66
|
</Dialog.Content>
|
|
@@ -11,6 +11,7 @@ export function ConfirmDialog({
|
|
|
11
11
|
content,
|
|
12
12
|
okCancel,
|
|
13
13
|
okText = 'OK',
|
|
14
|
+
okButtonIntent = 'default',
|
|
14
15
|
onOk,
|
|
15
16
|
onCancel,
|
|
16
17
|
cancelText = 'Cancel',
|
|
@@ -18,10 +19,10 @@ export function ConfirmDialog({
|
|
|
18
19
|
onInteractOutside,
|
|
19
20
|
onPointerDownOutside,
|
|
20
21
|
type,
|
|
22
|
+
closable,
|
|
21
23
|
}: ConfirmDialogProps) {
|
|
22
24
|
const cancelButton = okCancel && (
|
|
23
25
|
<Button
|
|
24
|
-
variant="secondary"
|
|
25
26
|
onClick={() => {
|
|
26
27
|
onCancel?.();
|
|
27
28
|
close();
|
|
@@ -38,13 +39,15 @@ export function ConfirmDialog({
|
|
|
38
39
|
onInteractOutside={onInteractOutside}
|
|
39
40
|
onPointerDownOutside={onPointerDownOutside}
|
|
40
41
|
type={type}
|
|
42
|
+
closable={closable}
|
|
41
43
|
>
|
|
42
44
|
{title && <Dialog.Title>{title}</Dialog.Title>}
|
|
43
45
|
{description && <Dialog.Description>{description}</Dialog.Description>}
|
|
44
46
|
{content}
|
|
45
|
-
<div className="flex items-center
|
|
47
|
+
<div className="mt-4 flex items-center justify-end gap-4">
|
|
46
48
|
{cancelButton}
|
|
47
49
|
<Button
|
|
50
|
+
intent={okButtonIntent}
|
|
48
51
|
onClick={() => {
|
|
49
52
|
onOk?.();
|
|
50
53
|
close();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
.c-dialog {
|
|
2
|
+
@apply fixed top-1/2 left-1/2 z-20 w-auto min-w-[25%] max-w-xl rounded-lg bg-elevate p-14 leading-6 text-gray-500-400 shadow;
|
|
3
|
+
transform: translate(-50%, -50%);
|
|
4
|
+
&-overlay {
|
|
5
|
+
@apply fixed inset-0 z-10 bg-overlay;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
&-icon {
|
|
9
|
+
@apply my-1 shrink-0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
&-title {
|
|
13
|
+
@apply m-0 font-serif text-xl font-bold text-gray;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&-description {
|
|
17
|
+
@apply mt-1 mb-5 font-medium;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
&-close-button {
|
|
21
|
+
@apply absolute top-0 right-0 inline-flex h-12 w-12 items-center justify-center rounded-none rounded-tr-lg border !bg-transparent !p-0 !drop-shadow-none hover:!bg-gray-50-900 focus:!bg-gray-50-900;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
&-with-icon {
|
|
25
|
+
@apply flex items-start gap-6 pl-6;
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/dialog/dialog.tsx
CHANGED
|
@@ -3,9 +3,11 @@ import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
|
3
3
|
import { cva, cx, VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
import { Button } from '../button';
|
|
6
|
-
import { Icon } from '../
|
|
6
|
+
import { Icon } from '../iconography';
|
|
7
7
|
import type { DialogFuncProps } from './types';
|
|
8
8
|
|
|
9
|
+
import './dialog.css';
|
|
10
|
+
|
|
9
11
|
const IconMap = {
|
|
10
12
|
error: Icon.Error,
|
|
11
13
|
info: Icon.Info,
|
|
@@ -13,16 +15,13 @@ const IconMap = {
|
|
|
13
15
|
};
|
|
14
16
|
|
|
15
17
|
type DialogContentStylesProps = VariantProps<typeof dialogContentStyles>;
|
|
16
|
-
const dialogContentStyles = cva(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
withIcon: {
|
|
21
|
-
true: 'flex gap-4 items-start',
|
|
22
|
-
},
|
|
18
|
+
const dialogContentStyles = cva('c-dialog', {
|
|
19
|
+
variants: {
|
|
20
|
+
withIcon: {
|
|
21
|
+
true: 'c-dialog-with-icon',
|
|
23
22
|
},
|
|
24
23
|
},
|
|
25
|
-
);
|
|
24
|
+
});
|
|
26
25
|
|
|
27
26
|
type DialogContentProps = DialogContentStylesProps & {
|
|
28
27
|
children: ReactNode;
|
|
@@ -40,13 +39,17 @@ function DialogContent({ children, closable = true, type, className, container,
|
|
|
40
39
|
|
|
41
40
|
return (
|
|
42
41
|
<DialogPrimitive.Portal container={container}>
|
|
43
|
-
<DialogPrimitive.Overlay className="
|
|
42
|
+
<DialogPrimitive.Overlay className="c-dialog-overlay" />
|
|
44
43
|
<DialogPrimitive.Content className={dialogContentStyles({ withIcon, class: className })} {...delegated}>
|
|
45
|
-
{IconComponent &&
|
|
44
|
+
{IconComponent && (
|
|
45
|
+
<div className="flex h-[44px] w-[44px] min-w-[44px] items-center justify-center rounded-lg bg-gray-50-900 p-[5px]">
|
|
46
|
+
<IconComponent className="c-dialog-icon" width={34} height={34} />
|
|
47
|
+
</div>
|
|
48
|
+
)}
|
|
46
49
|
{closable && (
|
|
47
50
|
<DialogClose asChild>
|
|
48
|
-
<Button className="
|
|
49
|
-
<Icon.Cancel color="density" aria-label="Close" height={
|
|
51
|
+
<Button className="c-dialog-close-button">
|
|
52
|
+
<Icon.Cancel color="density" aria-label="Close" height={16} width={16} />
|
|
50
53
|
</Button>
|
|
51
54
|
</DialogClose>
|
|
52
55
|
)}
|
|
@@ -59,12 +62,7 @@ function DialogContent({ children, closable = true, type, className, container,
|
|
|
59
62
|
type DialogTitleProps = JSX.IntrinsicAttributes & DialogPrimitive.DialogTitleProps & RefAttributes<HTMLHeadingElement>;
|
|
60
63
|
|
|
61
64
|
function DialogTitle({ className, ...delegated }: DialogTitleProps) {
|
|
62
|
-
return (
|
|
63
|
-
<DialogPrimitive.Title
|
|
64
|
-
className={cx('m-0 font-medium text-xl font-sans text-black-text', className)}
|
|
65
|
-
{...delegated}
|
|
66
|
-
/>
|
|
67
|
-
);
|
|
65
|
+
return <DialogPrimitive.Title className={cx('c-dialog-title', className)} {...delegated} />;
|
|
68
66
|
}
|
|
69
67
|
|
|
70
68
|
type DialogDescriptionProps = JSX.IntrinsicAttributes &
|
|
@@ -72,7 +70,7 @@ type DialogDescriptionProps = JSX.IntrinsicAttributes &
|
|
|
72
70
|
RefAttributes<HTMLParagraphElement>;
|
|
73
71
|
|
|
74
72
|
function DialogDescription(delegated: DialogDescriptionProps) {
|
|
75
|
-
return <DialogPrimitive.Description className="
|
|
73
|
+
return <DialogPrimitive.Description className="c-dialog-description" {...delegated} />;
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
const DialogTrigger = DialogPrimitive.Trigger;
|
package/src/dialog/types.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
1
|
+
import type { ReactNode, ComponentProps } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { Button } from '../button';
|
|
2
4
|
|
|
3
5
|
export type DialogFuncProps = {
|
|
4
6
|
afterClose?: () => void;
|
|
@@ -9,6 +11,7 @@ export type DialogFuncProps = {
|
|
|
9
11
|
description?: ReactNode;
|
|
10
12
|
okCancel?: boolean;
|
|
11
13
|
okText?: ReactNode;
|
|
14
|
+
okButtonIntent?: ComponentProps<typeof Button>['intent'];
|
|
12
15
|
onCancel?: (...args: unknown[]) => void;
|
|
13
16
|
onEscapeKeyDown?: (event: Event) => void;
|
|
14
17
|
onInteractOutside?: (event: Event) => void;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { Meta } from '@storybook/react';
|
|
2
|
-
import { useState } from 'react';
|
|
3
2
|
|
|
4
3
|
import { DropdownMenu } from '.';
|
|
5
4
|
import { Button } from '../button';
|
|
6
|
-
import { Icon } from '../
|
|
5
|
+
import { Icon } from '../iconography';
|
|
7
6
|
|
|
8
7
|
export default {
|
|
9
8
|
title: 'Components/DropdownMenu',
|
|
@@ -15,15 +14,15 @@ function ContentWithIcon() {
|
|
|
15
14
|
<>
|
|
16
15
|
<DropdownMenu.Label>View</DropdownMenu.Label>
|
|
17
16
|
<DropdownMenu.Item>
|
|
18
|
-
<div className="flex items-center">
|
|
17
|
+
<div className="flex items-center font-sans">
|
|
19
18
|
<Icon.Glasses width={24} height={24} />
|
|
20
|
-
<span className="px-
|
|
19
|
+
<span className="px-3">Nerdy</span>
|
|
21
20
|
</div>
|
|
22
21
|
</DropdownMenu.Item>
|
|
23
22
|
<DropdownMenu.Item>
|
|
24
23
|
<div className="flex items-center">
|
|
25
24
|
<Icon.GraphQL width={24} height={24} />
|
|
26
|
-
<span className="px-
|
|
25
|
+
<span className="px-3 font-sans">Developer</span>
|
|
27
26
|
</div>
|
|
28
27
|
</DropdownMenu.Item>
|
|
29
28
|
</>
|
|
@@ -31,16 +30,9 @@ function ContentWithIcon() {
|
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
export const WithOpenState = () => {
|
|
34
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
35
|
-
|
|
36
33
|
return (
|
|
37
|
-
<DropdownMenu.Root content={<ContentWithIcon />}
|
|
38
|
-
<Button>
|
|
39
|
-
<div className="flex items-center">
|
|
40
|
-
<Icon.NailPolish width={20} height={20} /> <span className="pl-4 pr-8">Pretty</span>
|
|
41
|
-
<Icon.Arrow className={isOpen ? 'rotate-180' : ''} />
|
|
42
|
-
</div>
|
|
43
|
-
</Button>
|
|
34
|
+
<DropdownMenu.Root content={<ContentWithIcon />}>
|
|
35
|
+
<Button prepend={<Icon.NailPolish width={20} height={20} />}>Pretty</Button>
|
|
44
36
|
</DropdownMenu.Root>
|
|
45
37
|
);
|
|
46
38
|
};
|
|
@@ -8,16 +8,7 @@ type DropdownMenuItemProps = DropdownMenuPrimitive.MenuItemProps & {
|
|
|
8
8
|
|
|
9
9
|
export function DropdownMenuItem({ children, className, ...delegated }: DropdownMenuItemProps) {
|
|
10
10
|
return (
|
|
11
|
-
<DropdownMenuPrimitive.Item
|
|
12
|
-
{...delegated}
|
|
13
|
-
className={cx(
|
|
14
|
-
'text-xs font-medium text-black-text',
|
|
15
|
-
'flex h-10 cursor-pointer items-center bg-white px-4 outline-asteroid',
|
|
16
|
-
'hover:bg-[#F8F8F9] hover:outline-none hover:focus-visible:outline-none',
|
|
17
|
-
'first:rounded-tr first:rounded-tl last:rounded-br last:rounded-bl',
|
|
18
|
-
className,
|
|
19
|
-
)}
|
|
20
|
-
>
|
|
11
|
+
<DropdownMenuPrimitive.Item {...delegated} className={cx('c-dropdown-menu-item', className)}>
|
|
21
12
|
{children}
|
|
22
13
|
</DropdownMenuPrimitive.Item>
|
|
23
14
|
);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
2
|
-
import { cx } from 'class-variance-authority';
|
|
3
2
|
import type { ReactNode } from 'react';
|
|
4
3
|
|
|
5
4
|
type DropdownMenuLabelProps = {
|
|
@@ -7,11 +6,5 @@ type DropdownMenuLabelProps = {
|
|
|
7
6
|
};
|
|
8
7
|
|
|
9
8
|
export function DropdownMenuLabel({ children }: DropdownMenuLabelProps) {
|
|
10
|
-
return
|
|
11
|
-
<DropdownMenuPrimitive.Label
|
|
12
|
-
className={cx('bg-white px-4 py-2 text-xs text-label', 'first:rounded-tl first:rounded-tr')}
|
|
13
|
-
>
|
|
14
|
-
{children}
|
|
15
|
-
</DropdownMenuPrimitive.Label>
|
|
16
|
-
);
|
|
9
|
+
return <DropdownMenuPrimitive.Label className="c-dropdown-menu-label">{children}</DropdownMenuPrimitive.Label>;
|
|
17
10
|
}
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
3
3
|
|
|
4
|
-
type DropdownMenuRootProps = {
|
|
4
|
+
type DropdownMenuRootProps = DropdownMenuPrimitive.MenuContentProps & {
|
|
5
5
|
children: ReactNode;
|
|
6
6
|
content: ReactNode;
|
|
7
7
|
alignContent?: 'start' | 'center' | 'end';
|
|
8
|
-
onOpenChange?: (isOpen: boolean) => void;
|
|
9
8
|
};
|
|
10
9
|
|
|
11
|
-
export function DropdownMenuRoot({ children, content,
|
|
10
|
+
export function DropdownMenuRoot({ children, content, alignContent = 'start', ...delegated }: DropdownMenuRootProps) {
|
|
12
11
|
return (
|
|
13
|
-
<DropdownMenuPrimitive.Root
|
|
12
|
+
<DropdownMenuPrimitive.Root>
|
|
14
13
|
<DropdownMenuPrimitive.Trigger asChild>{children}</DropdownMenuPrimitive.Trigger>
|
|
15
|
-
<DropdownMenuPrimitive.Content
|
|
14
|
+
<DropdownMenuPrimitive.Content
|
|
15
|
+
align={alignContent}
|
|
16
|
+
sideOffset={5}
|
|
17
|
+
className="c-dropdown-menu-content"
|
|
18
|
+
{...delegated}
|
|
19
|
+
>
|
|
16
20
|
{content}
|
|
17
21
|
</DropdownMenuPrimitive.Content>
|
|
18
22
|
</DropdownMenuPrimitive.Root>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.c-dropdown-menu-content {
|
|
2
|
+
@apply shadow;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.c-dropdown-menu-label {
|
|
6
|
+
@apply bg-elevate px-4 pt-2 font-sans text-xs font-bold text-gray-500-400;
|
|
7
|
+
@apply first:rounded-tl first:rounded-tr;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.c-dropdown-menu-item {
|
|
11
|
+
@apply flex h-10 cursor-pointer items-center bg-elevate px-3 font-sans text-xs font-medium text-gray-700-200;
|
|
12
|
+
|
|
13
|
+
&:hover,
|
|
14
|
+
&:focus,
|
|
15
|
+
&:focus-visible {
|
|
16
|
+
@apply bg-gray-50-900 outline-none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@apply first:rounded-tr first:rounded-tl last:rounded-br last:rounded-bl;
|
|
20
|
+
}
|
|
@@ -2,6 +2,8 @@ import { DropdownMenuRoot } from './dropdown-menu-root';
|
|
|
2
2
|
import { DropdownMenuItem } from './dropdown-menu-item';
|
|
3
3
|
import { DropdownMenuLabel } from './dropdown-menu-label';
|
|
4
4
|
|
|
5
|
+
import './dropdown-menu.css';
|
|
6
|
+
|
|
5
7
|
export const DropdownMenu = {
|
|
6
8
|
Root: DropdownMenuRoot,
|
|
7
9
|
Item: DropdownMenuItem,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { StoryObj, Meta } from '@storybook/react';
|
|
2
2
|
import { IconButton } from '.';
|
|
3
|
-
import {
|
|
3
|
+
import { Card } from '../card';
|
|
4
|
+
import { Icon } from '../iconography';
|
|
4
5
|
|
|
5
6
|
const meta: Meta<typeof IconButton> = {
|
|
6
7
|
title: 'Components/IconButton',
|
|
@@ -11,17 +12,19 @@ const meta: Meta<typeof IconButton> = {
|
|
|
11
12
|
export default meta;
|
|
12
13
|
type Story = StoryObj<typeof IconButton>;
|
|
13
14
|
|
|
14
|
-
const sizes = ['xs', 'sm', 'md', 'lg'
|
|
15
|
+
const sizes = ['xxs', 'xs', 'sm', 'md', 'lg'] as const;
|
|
15
16
|
|
|
16
17
|
export const AllButton: Story = {
|
|
17
18
|
name: 'All Buttons',
|
|
18
19
|
render: () => {
|
|
19
20
|
return (
|
|
20
|
-
<div className="grid grid-cols-5
|
|
21
|
+
<div className="grid grid-cols-5 justify-items-center gap-6">
|
|
21
22
|
{sizes.map(size => (
|
|
22
|
-
<
|
|
23
|
-
<
|
|
24
|
-
|
|
23
|
+
<Card>
|
|
24
|
+
<IconButton size={size}>
|
|
25
|
+
<Icon.Cancel width={16} height={16} />
|
|
26
|
+
</IconButton>
|
|
27
|
+
</Card>
|
|
25
28
|
))}
|
|
26
29
|
</div>
|
|
27
30
|
);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
.c-icon-button {
|
|
2
|
+
@apply flex cursor-pointer appearance-none items-center justify-center rounded-md border-none bg-transparent font-medium;
|
|
3
|
+
|
|
4
|
+
&:not(:disabled):active {
|
|
5
|
+
transform: scale(0.95);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
&:disabled {
|
|
9
|
+
@apply scale-100 cursor-default shadow-none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
&:focus,
|
|
13
|
+
&:hover {
|
|
14
|
+
@apply bg-elevate shadow;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
&:focus-visible {
|
|
18
|
+
@apply outline outline-1 outline-offset-1 outline-inherit;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&-xxs {
|
|
22
|
+
@apply h-5 w-5;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
&-xs {
|
|
26
|
+
@apply h-6 w-6;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&-sm {
|
|
30
|
+
@apply h-9 w-9;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&-md {
|
|
34
|
+
@apply h-11 w-11;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&-lg {
|
|
38
|
+
@apply h-14 w-14;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,31 +1,23 @@
|
|
|
1
1
|
import { ComponentPropsWithRef, forwardRef } from 'react';
|
|
2
2
|
import { cva, VariantProps } from 'class-variance-authority';
|
|
3
3
|
|
|
4
|
+
import './icon-button.css';
|
|
5
|
+
|
|
4
6
|
type IconButtonStylesProps = VariantProps<typeof buttonStyles>;
|
|
5
|
-
const buttonStyles = cva(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
],
|
|
14
|
-
{
|
|
15
|
-
variants: {
|
|
16
|
-
size: {
|
|
17
|
-
xs: 'h-8 w-8',
|
|
18
|
-
sm: 'h-9 w-9',
|
|
19
|
-
md: 'h-10 w-10',
|
|
20
|
-
lg: 'h-10 w-10',
|
|
21
|
-
xl: 'h-11 w-11',
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
defaultVariants: {
|
|
25
|
-
size: 'sm',
|
|
7
|
+
const buttonStyles = cva(['c-icon-button'], {
|
|
8
|
+
variants: {
|
|
9
|
+
size: {
|
|
10
|
+
xxs: 'c-icon-button-xxs',
|
|
11
|
+
xs: 'c-icon-button-xs',
|
|
12
|
+
sm: 'c-icon-button-sm',
|
|
13
|
+
md: 'c-icon-button-md',
|
|
14
|
+
lg: 'c-icon-button-lg',
|
|
26
15
|
},
|
|
27
16
|
},
|
|
28
|
-
|
|
17
|
+
defaultVariants: {
|
|
18
|
+
size: 'sm',
|
|
19
|
+
},
|
|
20
|
+
});
|
|
29
21
|
|
|
30
22
|
export type IconButtonProps = ComponentPropsWithRef<'button'> & IconButtonStylesProps;
|
|
31
23
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { StoryObj, Meta } from '@storybook/react';
|
|
2
|
+
import { Icon } from '.';
|
|
3
|
+
import { Card } from '../card';
|
|
4
|
+
|
|
5
|
+
function Dummy() {
|
|
6
|
+
return <div>🤓</div>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const meta: Meta<typeof Dummy> = {
|
|
10
|
+
title: 'Components/Icon',
|
|
11
|
+
component: Dummy,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof Icon>;
|
|
16
|
+
|
|
17
|
+
export const AllIcons: Story = {
|
|
18
|
+
name: 'All icons',
|
|
19
|
+
render: () => {
|
|
20
|
+
return (
|
|
21
|
+
<div>
|
|
22
|
+
<div className="grid grid-cols-6 justify-items-center gap-6">
|
|
23
|
+
{Object.keys(Icon).map(iconName => {
|
|
24
|
+
// @ts-expect-error
|
|
25
|
+
const Cmp = Icon[iconName];
|
|
26
|
+
const cmpString = `<Icon.${iconName} />`;
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
className="cursor-pointer text-center active:scale-95"
|
|
30
|
+
onClick={() => {
|
|
31
|
+
const type = 'text/plain';
|
|
32
|
+
const blob = new Blob([cmpString], { type });
|
|
33
|
+
navigator.clipboard.write([new ClipboardItem({ [type]: blob })]);
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<Card title={cmpString}>
|
|
37
|
+
<Cmp width={25} height={25} />
|
|
38
|
+
</Card>
|
|
39
|
+
<div className="mt-2 whitespace-nowrap text-xs text-gray-700-200">{cmpString}</div>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
})}
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
},
|
|
47
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { forwardRef, SVGProps } from 'react';
|
|
2
|
+
|
|
3
|
+
type AtomProps = SVGProps<SVGSVGElement>;
|
|
4
|
+
|
|
5
|
+
type AtomRef = SVGSVGElement;
|
|
6
|
+
|
|
7
|
+
export const Atom = forwardRef<AtomRef, AtomProps>((delegated, ref) => {
|
|
8
|
+
return (
|
|
9
|
+
<svg
|
|
10
|
+
ref={ref}
|
|
11
|
+
width="24"
|
|
12
|
+
height="27"
|
|
13
|
+
viewBox="0 0 24 27"
|
|
14
|
+
fill="none"
|
|
15
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
16
|
+
{...delegated}
|
|
17
|
+
>
|
|
18
|
+
<path
|
|
19
|
+
fill="#528693"
|
|
20
|
+
d="M18.068 3.103c.935 0 .938-1.5 0-1.5s-.938 1.5 0 1.5ZM5.911 2.928c.641 0 .643-1.027 0-1.027-.642 0-.643 1.027 0 1.027ZM4.294 8.862c.577 0 .578-.925 0-.925s-.578.925 0 .925ZM6.03 23.058a.39.39 0 0 0 .265-.126.413.413 0 0 0 0-.558.39.39 0 0 0-.264-.126.39.39 0 0 0-.264.126.413.413 0 0 0 0 .558.39.39 0 0 0 .264.126ZM16.93 23.13c.674 0 .675-1.078 0-1.078s-.675 1.078 0 1.078ZM18.966 17.685c.885 0 .887-1.418 0-1.418-.886 0-.886 1.418 0 1.418ZM11.6 23.619a.217.217 0 0 0 .15-.069.23.23 0 0 0 0-.315.216.216 0 0 0-.15-.068.216.216 0 0 0-.15.068.23.23 0 0 0 0 .315c.039.042.093.067.15.069ZM22.291 13.446l.043.031a.903.903 0 0 0 1.263-.344.972.972 0 0 0 0-.952.936.936 0 0 0-.34-.348.902.902 0 0 0-.924.004l-.042.03a.905.905 0 0 0-.319.33.937.937 0 0 0 0 .922c.077.136.187.25.319.329v-.002ZM11.496 26.097c3.17 0 5.738-.359 5.738-.8 0-.443-2.569-.802-5.738-.802-3.17 0-5.738.359-5.738.801 0 .442 2.569.8 5.738.8Z"
|
|
21
|
+
opacity=".05"
|
|
22
|
+
/>
|
|
23
|
+
<path
|
|
24
|
+
fill="#FF99DB"
|
|
25
|
+
d="M11.496 16.417c1.95 0 3.531-1.629 3.531-3.638 0-2.01-1.581-3.638-3.531-3.638-1.95 0-3.531 1.629-3.531 3.638 0 2.01 1.58 3.638 3.53 3.638Z"
|
|
26
|
+
/>
|
|
27
|
+
<path
|
|
28
|
+
fill="#528693"
|
|
29
|
+
d="M8.252 12.78c0-.689.207-1.36.591-1.923.385-.563.929-.99 1.557-1.222a3.153 3.153 0 0 1 1.956-.076 3.236 3.236 0 0 1 1.642 1.096 3.424 3.424 0 0 1 .285 3.834 3.278 3.278 0 0 1-1.46 1.341 3.156 3.156 0 0 1-1.945.232A3.259 3.259 0 0 1 9 14.9a3.437 3.437 0 0 1-.748-2.122.3.3 0 0 0-.088-.202.283.283 0 0 0-.398 0 .3.3 0 0 0-.088.202c0 .81.243 1.602.695 2.265a3.834 3.834 0 0 0 1.834 1.439c.74.273 1.545.305 2.304.09a3.81 3.81 0 0 0 1.934-1.293 4.03 4.03 0 0 0 .33-4.516 3.859 3.859 0 0 0-1.723-1.577 3.715 3.715 0 0 0-2.29-.268 3.85 3.85 0 0 0-2.203 1.37 4.059 4.059 0 0 0-.881 2.49.3.3 0 0 0 .088.202.283.283 0 0 0 .398 0 .3.3 0 0 0 .088-.202Z"
|
|
30
|
+
/>
|
|
31
|
+
<path
|
|
32
|
+
fill="#528693"
|
|
33
|
+
d="M9.025 12.946a2.787 2.787 0 0 1 .78-1.91 2.626 2.626 0 0 1 1.854-.803.157.157 0 0 0 .113-.048.167.167 0 0 0 0-.232.157.157 0 0 0-.113-.048c-.783 0-1.533.32-2.087.891a3.093 3.093 0 0 0-.866 2.15c0 .044.017.086.047.116a.157.157 0 0 0 .225 0 .167.167 0 0 0 .047-.116ZM8.972 13.854c.033 0 .066-.01.094-.029a.17.17 0 0 0 .062-.079.137.137 0 0 0 .014-.068l-.006-.046a.176.176 0 0 0-.044-.078l-.034-.027a.167.167 0 0 0-.086-.025.174.174 0 0 0-.12.053.183.183 0 0 0-.05.123l.005.046c.008.03.024.056.044.078l.035.028a.166.166 0 0 0 .086.023v.001ZM12.136 10.204v.004a.112.112 0 0 0 .026.051c.01.016.024.03.04.039l.036.015a.145.145 0 0 0 .077 0l.034-.015a.112.112 0 0 0 .041-.039.076.076 0 0 0 .019-.033.118.118 0 0 0 .012-.057l-.005-.04-.014-.035a.113.113 0 0 0-.038-.042.107.107 0 0 0-.05-.027.109.109 0 0 0-.057-.003.104.104 0 0 0-.054.018l-.03.024a.148.148 0 0 0-.037.065v.004a.136.136 0 0 0 0 .07Z"
|
|
34
|
+
/>
|
|
35
|
+
<path
|
|
36
|
+
fill="#528693"
|
|
37
|
+
d="M6.023 12.779a23.383 23.383 0 0 1 1.024-7.096c.517-1.608 1.283-3.336 2.601-4.417.989-.81 2.233-.962 3.322-.27 1.369.87 2.196 2.529 2.747 4.027a21.916 21.916 0 0 1 1.234 6.778 24.482 24.482 0 0 1-.779 7.302c-.471 1.725-1.178 3.543-2.437 4.827-.881.898-2.097 1.4-3.294.86-1.407-.632-2.294-2.18-2.89-3.56-.883-2.039-1.303-4.3-1.46-6.515a27.856 27.856 0 0 1-.068-1.936.278.278 0 0 0-.082-.187.262.262 0 0 0-.369 0 .278.278 0 0 0-.081.187c.004 2.518.314 5.078 1.117 7.465.567 1.685 1.403 3.46 2.818 4.559a3.229 3.229 0 0 0 3.73.283c1.471-.883 2.37-2.582 2.98-4.158.88-2.267 1.261-4.74 1.347-7.17a24.885 24.885 0 0 0-.84-7.606c-.509-1.799-1.28-3.699-2.628-5.008C12.998.158 11.617-.328 10.28.247 8.781.892 7.8 2.46 7.15 3.92c-.951 2.138-1.408 4.494-1.582 6.829-.05.675-.074 1.352-.075 2.03.002.07.032.138.081.187a.262.262 0 0 0 .369 0 .278.278 0 0 0 .081-.187Z"
|
|
38
|
+
/>
|
|
39
|
+
<path
|
|
40
|
+
fill="#528693"
|
|
41
|
+
d="M8.64 7.969c2.066-1.293 4.315-2.336 6.686-2.86 1.61-.357 3.548-.57 5.086.197.576.27 1.048.73 1.34 1.309.24.543.327 1.145.25 1.737-.164 1.605-1.1 3.108-2.06 4.333a21.318 21.318 0 0 1-4.85 4.42 22.562 22.562 0 0 1-6.661 3.155c-1.718.468-3.69.777-5.416.176-1.207-.422-2.038-1.42-2.049-2.758-.012-1.547.808-3.03 1.665-4.243a19.773 19.773 0 0 1 4.556-4.482c.474-.345.958-.673 1.454-.984.29-.184.024-.657-.269-.473a22.835 22.835 0 0 0-5.39 4.61C1.87 13.438.81 15.035.512 16.801c-.235 1.395.136 2.779 1.293 3.62 1.41 1.023 3.364.982 4.994.743 2.442-.36 4.8-1.342 6.944-2.575a23.78 23.78 0 0 0 5.757-4.55c1.223-1.345 2.372-2.932 2.86-4.732.359-1.328.254-2.821-.758-3.823-1.204-1.192-3.091-1.326-4.666-1.182-2.378.218-4.688 1.076-6.806 2.183-.599.313-1.183.651-1.757 1.01-.293.183-.026.657.268.473Z"
|
|
42
|
+
/>
|
|
43
|
+
<path
|
|
44
|
+
fill="#528693"
|
|
45
|
+
d="M14.62 7.496c-2.17-1.357-4.551-2.454-7.05-2.966-1.725-.353-3.736-.512-5.352.35a3.343 3.343 0 0 0-1.39 1.404 3.481 3.481 0 0 0-.38 1.967c.135 1.715 1.061 3.29 2.067 4.615a21.487 21.487 0 0 0 5.078 4.687 22.835 22.835 0 0 0 7.03 3.29c1.783.463 3.854.752 5.624.074 1.321-.507 2.24-1.618 2.306-3.095.074-1.64-.756-3.25-1.652-4.546-1.285-1.86-2.956-3.421-4.755-4.742a24.734 24.734 0 0 0-1.526-1.037c-.293-.185-.56.289-.269.473a22.565 22.565 0 0 1 5.134 4.347c1.078 1.26 2.095 2.754 2.443 4.424.258 1.237-.018 2.535-1.092 3.266-1.361.927-3.228.846-4.768.588-2.321-.389-4.55-1.322-6.593-2.502a23.435 23.435 0 0 1-5.472-4.295c-1.187-1.278-2.314-2.784-2.819-4.501-.351-1.197-.326-2.555.618-3.46C2.94 4.75 4.755 4.716 6.204 4.867c2.261.235 4.469 1.078 6.48 2.139.567.3 1.123.623 1.668.964.06.032.131.04.197.02a.267.267 0 0 0 .155-.126.282.282 0 0 0-.084-.367Z"
|
|
46
|
+
/>
|
|
47
|
+
<path
|
|
48
|
+
fill="#fff"
|
|
49
|
+
d="M11.963 14.285h.003c.2-.04.384-.14.53-.287.175-.111.317-.27.41-.46l.159-.388c.065-.21.075-.434.028-.649a1.234 1.234 0 0 0-.188-.604l-.246-.329-.32-.254a1.152 1.152 0 0 0-.585-.193 1.164 1.164 0 0 0-.63.03l-.377.163c-.343.228-.6.571-.725.971l-.056.433c-.01.217.037.433.136.626.036.136.106.26.203.359.11.176.263.32.442.418l.377.164c.275.078.564.078.84 0h-.001Z"
|
|
50
|
+
/>
|
|
51
|
+
<path
|
|
52
|
+
fill="#FF99DB"
|
|
53
|
+
d="m11.172 13.1.017.019.105.083c.057.038.124.06.192.063a.253.253 0 0 0 .138 0 .379.379 0 0 0 .191-.063l.105-.083.08-.108a.403.403 0 0 0 .062-.199.414.414 0 0 0-.009-.212l-.002-.026a.548.548 0 0 0-.135-.24.524.524 0 0 0-.232-.139l-.14-.019a.513.513 0 0 0-.265.074.605.605 0 0 0-.243.324.562.562 0 0 0 .136.527Z"
|
|
54
|
+
/>
|
|
55
|
+
</svg>
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
Atom.displayName = 'AtomIcon';
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { forwardRef, SVGProps } from 'react';
|
|
2
|
+
|
|
3
|
+
type CopyProps = SVGProps<SVGSVGElement>;
|
|
4
|
+
|
|
5
|
+
type CopyRef = SVGSVGElement;
|
|
6
|
+
|
|
7
|
+
export const Copy = forwardRef<CopyRef, CopyProps>((delegated, ref) => {
|
|
8
|
+
return (
|
|
9
|
+
<svg
|
|
10
|
+
ref={ref}
|
|
11
|
+
width="14"
|
|
12
|
+
height="16"
|
|
13
|
+
viewBox="0 0 14 16"
|
|
14
|
+
fill="none"
|
|
15
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
16
|
+
{...delegated}
|
|
17
|
+
>
|
|
18
|
+
<rect x=".5" y="3.5" width="9" height="12" rx="2.5" fill="#EAEBEE" stroke="#80878D" strokeDasharray="3 2" />
|
|
19
|
+
<rect x="4.5" y=".5" width="9" height="12" rx="2.5" fill="#EAEBEE" stroke="#80878D" />
|
|
20
|
+
</svg>
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
Copy.displayName = 'CopyIcon';
|