@crystallize/design-system 1.18.0 → 1.19.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crystallize/design-system",
3
- "version": "1.18.0",
3
+ "version": "1.19.1",
4
4
  "types": "./dist/index.d.ts",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -45,10 +45,11 @@
45
45
  "@radix-ui/react-radio-group": "1.1.0",
46
46
  "@radix-ui/react-select": "1.1.2",
47
47
  "@radix-ui/react-slider": "^1.1.0",
48
- "@radix-ui/react-tooltip": "1.0.0",
49
48
  "@radix-ui/react-switch": "^1.0.2",
49
+ "@radix-ui/react-tooltip": "1.0.0",
50
50
  "class-variance-authority": "^0.4.0",
51
51
  "lexical": "0.10.0",
52
+ "sonner": "^0.6.2",
52
53
  "use-debounce": "8.0.4"
53
54
  },
54
55
  "peerDependencies": {
@@ -1,5 +1,5 @@
1
1
  .c-action-menu {
2
- @apply flex shrink-0 rotate-0 cursor-pointer flex-col items-center justify-center gap-[2px] rounded-md border-none bg-transparent -outline-offset-1 transition;
2
+ @apply flex shrink-0 cursor-pointer flex-col items-center justify-center gap-[2px] rounded-md border-none bg-transparent -outline-offset-1 transition;
3
3
 
4
4
  &-dot {
5
5
  @apply rounded-full bg-gray;
@@ -0,0 +1,29 @@
1
+ import { forwardRef, SVGProps } from 'react';
2
+
3
+ type ArchiveProps = SVGProps<SVGSVGElement>;
4
+
5
+ type ArchiveRef = SVGSVGElement;
6
+
7
+ export const Archive = forwardRef<ArchiveRef, ArchiveProps>((delegated, ref) => {
8
+ return (
9
+ <svg ref={ref} width="22" height="22" viewBox="0 0 22 22" fill="currentColor" {...delegated}>
10
+ <svg width="23" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
11
+ <path
12
+ d="M11.0308 9.33234V12.2464L12.7792 13.8006"
13
+ stroke="#528693"
14
+ strokeWidth="0.697782"
15
+ strokeLinecap="round"
16
+ strokeLinejoin="round"
17
+ />
18
+ <path
19
+ d="M15.2861 5.20269C14.0809 4.39737 12.6759 3.94619 11.2307 3.89751L11.2307 3.48958C11.2307 2.9983 10.68 2.7082 10.2748 2.98605L7.76996 4.70378C7.41666 4.94607 7.41621 5.46738 7.7691 5.71026L10.2739 7.43428C10.679 7.71309 11.2307 7.42309 11.2307 6.93134L11.2307 6.52714C12.1561 6.57428 13.0533 6.8707 13.8264 7.38728C14.6723 7.95243 15.3315 8.7557 15.7208 9.69551C16.11 10.6353 16.2119 11.6695 16.0134 12.6671C15.815 13.6648 15.3251 14.5813 14.6058 15.3006C13.8865 16.0199 12.9701 16.5097 11.9724 16.7082C10.9747 16.9066 9.94057 16.8048 9.00076 16.4155C8.06095 16.0262 7.25768 15.367 6.69253 14.5212C6.19432 13.7756 5.90088 12.9145 5.83837 12.024C5.81857 11.742 5.7386 11.454 5.57104 11.2033C5.24004 10.7082 4.55958 10.5956 4.08671 10.9577L3.99464 11.0282C3.58114 11.3449 3.32047 11.8449 3.358 12.3849C3.44631 13.6555 3.78246 14.8951 4.50794 15.9809C5.36179 17.2588 6.5754 18.2547 7.9953 18.8429C9.4152 19.431 10.9776 19.5849 12.485 19.2851C13.9923 18.9853 15.3769 18.2452 16.4637 17.1584C17.5504 16.0717 18.2905 14.6871 18.5903 13.1797C18.8902 11.6724 18.7363 10.11 18.1481 8.69005C17.56 7.27015 16.564 6.05654 15.2861 5.20269Z"
20
+ fill="#BFF6F8"
21
+ stroke="#528693"
22
+ strokeWidth="0.523337"
23
+ />
24
+ </svg>
25
+ </svg>
26
+ );
27
+ });
28
+
29
+ Archive.displayName = 'ArchiveIcon';
@@ -1,5 +1,6 @@
1
1
  import { Add } from './add';
2
2
  import { App } from './app';
3
+ import { Archive } from './archive';
3
4
  import { Arrow } from './arrow';
4
5
  import { Atom } from './atom';
5
6
  import { Bell } from './bell';
@@ -95,6 +96,7 @@ import { Warning } from './warning';
95
96
 
96
97
  export const Icon = {
97
98
  Add,
99
+ Archive,
98
100
  App,
99
101
  BillingPayments,
100
102
  Bin,
package/src/index.ts CHANGED
@@ -24,6 +24,7 @@ export * from './spinner';
24
24
  export * from './stack-icon';
25
25
  export * from './tag';
26
26
  export * from './rich-text-editor';
27
+ export * from './toast';
27
28
  export * from './tooltip';
28
29
  export * from './switch';
29
30
 
@@ -0,0 +1,2 @@
1
+ export { Toaster } from 'sonner';
2
+ export { toast, type ToastProps } from './toast';
@@ -0,0 +1,51 @@
1
+ .c-toast {
2
+ @apply relative flex gap-2 rounded-md bg-white pl-3 pr-6 shadow-sm;
3
+
4
+ &:hover .c-toast-close {
5
+ @apply block;
6
+ }
7
+
8
+ &.c-toast-with-message {
9
+ @apply py-3;
10
+
11
+ & .c-toast-title {
12
+ @apply font-bold;
13
+ }
14
+ }
15
+
16
+ &.c-toast-title-only {
17
+ @apply items-center py-2;
18
+
19
+ & .c-toast-title {
20
+ @apply font-medium;
21
+ }
22
+ }
23
+ }
24
+
25
+ .c-toast-success {
26
+ @apply border border-solid border-cyan-300-600 bg-cyan-100-800 text-green-600-300;
27
+ }
28
+
29
+ .c-toast-error {
30
+ @apply border border-solid border-pink-200-700 bg-pink-100-800 text-pink-700-200;
31
+ }
32
+
33
+ .c-toast-warning {
34
+ @apply border border-solid border-orange-200-700 bg-orange-100-800 text-green-600-300;
35
+ }
36
+
37
+ .c-toast-info {
38
+ @apply border border-solid border-purple-200-700 bg-white text-green-600-300;
39
+ }
40
+
41
+ .c-toast-title {
42
+ @apply text-sm;
43
+ }
44
+
45
+ .c-toast-message {
46
+ @apply text-[13px] font-medium leading-4;
47
+ }
48
+
49
+ .c-toast-close {
50
+ @apply absolute right-1 top-1 hidden;
51
+ }
@@ -0,0 +1,110 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import { toast, Toaster } from '.';
4
+ import { Button } from '../button';
5
+
6
+ const meta: Meta<typeof toast> = {
7
+ title: 'Components/Toast',
8
+ };
9
+
10
+ export default meta;
11
+ type Story = StoryObj<typeof toast>;
12
+
13
+ export const SimpleToast: Story = {
14
+ name: 'Simple Toast',
15
+ render: () => (
16
+ <>
17
+ <Toaster />
18
+ <div className="flex w-1/2 gap-2">
19
+ <Button onClick={() => toast({ title: 'You did something good' })}>Success toast</Button>
20
+ <Button onClick={() => toast({ title: 'You have been warned buddy', type: 'warning' })}>Warning toast</Button>
21
+ <Button onClick={() => toast({ title: 'There was a oopsie daisy ', type: 'error' })}>Error toast</Button>
22
+ <Button onClick={() => toast({ title: 'Let me inform you about something ', type: 'info' })}>
23
+ Info toast
24
+ </Button>
25
+ </div>
26
+ </>
27
+ ),
28
+ };
29
+ export const WarningToast: Story = {
30
+ name: 'Toast with message ',
31
+ render: () => (
32
+ <>
33
+ <Toaster />
34
+ <div
35
+ className="flex w-full
36
+ gap-4"
37
+ >
38
+ <Button
39
+ onClick={() =>
40
+ toast({
41
+ title: 'You did alot of good',
42
+ message: 'So let me tell you are story about the bread and the toast',
43
+ })
44
+ }
45
+ >
46
+ Success message
47
+ </Button>
48
+
49
+ <Button
50
+ onClick={() =>
51
+ toast({
52
+ title: 'You have been warned with a explanation',
53
+ type: 'warning',
54
+ message: 'Here i could explain in detail why i am warning you.',
55
+ })
56
+ }
57
+ >
58
+ Warning message
59
+ </Button>
60
+ <Button
61
+ onClick={() =>
62
+ toast({
63
+ title: 'There was an oopsie daisy',
64
+ type: 'error',
65
+ message: 'And it happend because you clicked the button above',
66
+ })
67
+ }
68
+ >
69
+ Error message
70
+ </Button>
71
+ <Button
72
+ onClick={() =>
73
+ toast({
74
+ title: 'This is that something',
75
+ type: 'info',
76
+ message: 'And this is something with more details',
77
+ })
78
+ }
79
+ >
80
+ Info message
81
+ </Button>
82
+ </div>
83
+ </>
84
+ ),
85
+ };
86
+
87
+ export const TimeoutToast: Story = {
88
+ name: 'Timeout toast',
89
+ render: () => (
90
+ <>
91
+ <Toaster />
92
+ <div className="flex w-full gap-4">
93
+ <Button onClick={() => toast({ title: 'Can you read this? ', timeout: 500, type: 'info' })}>Quick toast</Button>
94
+
95
+ <Button
96
+ onClick={() =>
97
+ toast({
98
+ title: 'A slow message',
99
+ message: 'With with 20s duration, you can cross it out if you hover it ',
100
+ timeout: 20000,
101
+ type: 'info',
102
+ })
103
+ }
104
+ >
105
+ A slow toast
106
+ </Button>
107
+ </div>
108
+ </>
109
+ ),
110
+ };
@@ -0,0 +1,72 @@
1
+ import { cva, cx, VariantProps } from 'class-variance-authority';
2
+ import { toast as sonnerToast } from 'sonner';
3
+
4
+ import { IconButton } from '../icon-button';
5
+ import { Icon } from '../iconography';
6
+ import './toast.css';
7
+
8
+ const toastStyles = cva('c-toast', {
9
+ variants: {
10
+ type: {
11
+ info: 'c-toast-info',
12
+ error: 'c-toast-error',
13
+ success: 'c-toast-success',
14
+ warning: 'c-toast-warning',
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ type: 'success',
19
+ },
20
+ });
21
+
22
+ type ToastType = 'info' | 'error' | 'success' | 'warning';
23
+ type ToastStylesProps = VariantProps<typeof toastStyles>;
24
+ export type ToastProps = Omit<React.ComponentProps<'div'>, 'title'> &
25
+ Omit<ToastStylesProps, 'type'> & {
26
+ title: React.ReactNode;
27
+ type?: ToastType;
28
+ message?: React.ReactNode;
29
+ timeout?: number;
30
+ };
31
+
32
+ const iconMap = {
33
+ info: Icon.Info,
34
+ error: Icon.Error,
35
+ success: Icon.CheckWithCircle,
36
+ warning: Icon.Warning,
37
+ };
38
+
39
+ export const toast = ({ title, message, type = 'success', timeout = 6000 }: ToastProps) => {
40
+ const ToastIcon = iconMap[type];
41
+ const withMessage = !!message;
42
+ const toastId = Date.now().toString();
43
+
44
+ sonnerToast.custom(
45
+ id => (
46
+ <div
47
+ data-testid="toast-content"
48
+ className={cx(toastStyles({ type }), withMessage ? 'c-toast-with-message' : 'c-toast-title-only')}
49
+ >
50
+ <div>{<ToastIcon width={26} height={26} />}</div>
51
+ <div>
52
+ <div className="c-toast-title">{title}</div>
53
+ {!!message && <div className="c-toast-message">{message}</div>}
54
+ </div>
55
+ <div className="c-toast-close">
56
+ <IconButton onClick={() => sonnerToast.dismiss(id)} size="xs">
57
+ <Icon.Cancel width={12} height={12} />
58
+ </IconButton>
59
+ </div>
60
+ </div>
61
+ ),
62
+ {
63
+ id: toastId,
64
+ duration: timeout,
65
+ style: { width: '100%' },
66
+ },
67
+ );
68
+
69
+ return toastId;
70
+ };
71
+
72
+ toast.dismiss = sonnerToast.dismiss;