@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.
Files changed (104) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/index.css +1319 -827
  3. package/dist/index.d.ts +98 -43
  4. package/dist/index.js +982 -578
  5. package/dist/index.mjs +973 -573
  6. package/package.json +40 -23
  7. package/readme.md +9 -0
  8. package/src/Tokens.stories.tsx +18 -0
  9. package/src/action-menu/ActionMenu.stories.tsx +3 -1
  10. package/src/action-menu/action-item.tsx +1 -9
  11. package/src/action-menu/action-menu.css +38 -0
  12. package/src/action-menu/action-menu.tsx +4 -13
  13. package/src/action-menu/index.tsx +2 -0
  14. package/src/avatar/Avatar.stories.tsx +20 -0
  15. package/src/avatar/avatar.css +23 -0
  16. package/src/avatar/avatar.tsx +34 -0
  17. package/src/avatar/get-initials.ts +5 -0
  18. package/src/avatar/index.ts +1 -0
  19. package/src/button/Button.stories.tsx +64 -22
  20. package/src/button/button.css +116 -0
  21. package/src/button/button.tsx +119 -33
  22. package/src/button/index.ts +1 -1
  23. package/src/card/card.css +7 -0
  24. package/src/card/card.stories.tsx +2 -2
  25. package/src/card/card.tsx +6 -4
  26. package/src/card/index.ts +2 -0
  27. package/src/checkbox/checkbox.css +30 -0
  28. package/src/checkbox/checkbox.tsx +6 -14
  29. package/src/colors/Colors.stories.tsx +127 -0
  30. package/src/colors/color-defaults.json +15 -0
  31. package/src/colors/color-pairing.json +12 -0
  32. package/src/colors/colors.json +158 -0
  33. package/src/colors/index.ts +1 -0
  34. package/src/colors/old-to-new.txt +19 -0
  35. package/src/colors/types.ts +29 -0
  36. package/src/dialog/Dialog.stories.tsx +9 -6
  37. package/src/dialog/confirm-dialog.tsx +5 -2
  38. package/src/dialog/dialog.css +27 -0
  39. package/src/dialog/dialog.tsx +18 -20
  40. package/src/dialog/types.ts +4 -1
  41. package/src/dropdown-menu/DropdownMenu.stories.tsx +6 -14
  42. package/src/dropdown-menu/dropdown-menu-item.tsx +1 -10
  43. package/src/dropdown-menu/dropdown-menu-label.tsx +1 -8
  44. package/src/dropdown-menu/dropdown-menu-root.tsx +9 -5
  45. package/src/dropdown-menu/dropdown-menu.css +20 -0
  46. package/src/dropdown-menu/index.ts +2 -0
  47. package/src/icon-button/IconButton.stories.tsx +9 -6
  48. package/src/icon-button/icon-button.css +40 -0
  49. package/src/icon-button/icon-button.tsx +14 -22
  50. package/src/iconography/Icon.stories.tsx +47 -0
  51. package/src/{icons → iconography}/arrow.tsx +0 -0
  52. package/src/iconography/atom.tsx +59 -0
  53. package/src/{icons → iconography}/cancel.tsx +0 -0
  54. package/src/iconography/copy.tsx +24 -0
  55. package/src/iconography/crystal.tsx +93 -0
  56. package/src/iconography/edit.tsx +30 -0
  57. package/src/iconography/error.tsx +40 -0
  58. package/src/{icons → iconography}/glasses.tsx +0 -0
  59. package/src/{icons → iconography}/graphQL.tsx +0 -0
  60. package/src/{icons → iconography}/index.ts +10 -2
  61. package/src/iconography/info.tsx +41 -0
  62. package/src/{icons → iconography}/nail-polish.tsx +0 -0
  63. package/src/iconography/particle.tsx +88 -0
  64. package/src/iconography/triangle.tsx +27 -0
  65. package/src/iconography/warning.tsx +51 -0
  66. package/src/index.css +11 -0
  67. package/src/index.ts +12 -2
  68. package/src/inline-radio/inline-radio.css +20 -0
  69. package/src/inline-radio/inline-radio.stories.tsx +1 -1
  70. package/src/inline-radio/inline-radio.tsx +4 -14
  71. package/src/input/Input.stories.tsx +8 -1
  72. package/src/input/input.css +7 -0
  73. package/src/input/input.tsx +8 -21
  74. package/src/input-with-label/InputWithLabel.stories.tsx +98 -0
  75. package/src/input-with-label/index.ts +3 -0
  76. package/src/input-with-label/input-with-label.css +35 -0
  77. package/src/input-with-label/input-with-label.tsx +59 -0
  78. package/src/label/label.css +3 -0
  79. package/src/label/label.tsx +3 -1
  80. package/src/progress/progress.css +7 -0
  81. package/src/progress/progress.tsx +8 -7
  82. package/src/radio/radio.css +20 -0
  83. package/src/radio/radio.tsx +4 -11
  84. package/src/select/select-item.tsx +1 -10
  85. package/src/select/select-root.tsx +5 -12
  86. package/src/select/select.css +28 -0
  87. package/src/select/select.stories.tsx +12 -0
  88. package/src/select/select.ts +2 -0
  89. package/src/spinner/Spinner.stories.tsx +19 -0
  90. package/src/spinner/index.tsx +48 -0
  91. package/src/spinner/spinner.css +11 -0
  92. package/tailwind.config.cjs +51 -0
  93. package/src/button copy/ButtonCopy.stories.tsx +0 -86
  94. package/src/button copy/button.tsx +0 -61
  95. package/src/button copy/index.ts +0 -3
  96. package/src/colors/Colors.stories.mdx +0 -33
  97. package/src/icons/Iconography.stories.mdx +0 -45
  98. package/src/icons/dots.tsx +0 -24
  99. package/src/icons/error.tsx +0 -43
  100. package/src/icons/info.tsx +0 -46
  101. package/src/icons/warning.tsx +0 -55
  102. package/src/text-field/TextField.stories.tsx +0 -20
  103. package/src/text-field/index.ts +0 -1
  104. package/src/text-field/text-field.tsx +0 -60
@@ -0,0 +1,98 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import { InputWithLabel } from '.';
4
+
5
+ const meta: Meta<typeof InputWithLabel> = {
6
+ title: 'Components/InputWithLabel',
7
+ component: InputWithLabel,
8
+ argTypes: {
9
+ variant: {
10
+ defaultValue: '',
11
+ },
12
+ },
13
+ };
14
+
15
+ export default meta;
16
+
17
+ type Story = StoryObj<typeof InputWithLabel>;
18
+
19
+ export const Default: Story = {
20
+ args: {
21
+ placeholder: 'Luke Skywalker',
22
+ label: 'Name',
23
+ value: 'Luke Skywalker',
24
+ },
25
+ };
26
+
27
+ export const Error: Story = {
28
+ args: {
29
+ placeholder: 'Luke Skywalker',
30
+ label: 'Name',
31
+ status: 'error',
32
+ },
33
+ };
34
+
35
+ export const ErrorWithMessage: Story = {
36
+ args: {
37
+ placeholder: 'Luke Skywalker',
38
+ label: 'Name',
39
+ status: 'error',
40
+ errorMessage: 'You are not my father',
41
+ },
42
+ };
43
+
44
+ export const Elevated: Story = {
45
+ args: {
46
+ placeholder: 'Luke Skywalker',
47
+ label: 'Name',
48
+ variant: 'elevated',
49
+ },
50
+ };
51
+
52
+ export const ElevatedError: Story = {
53
+ args: {
54
+ placeholder: 'Luke Skywalker',
55
+ label: 'Name',
56
+ variant: 'elevated',
57
+ status: 'error',
58
+ errorMessage: 'Something went no no',
59
+ },
60
+ };
61
+
62
+ export const WithAppend: Story = {
63
+ args: {
64
+ placeholder: 'Luke Skywalker',
65
+ label: 'Name',
66
+ variant: 'elevated',
67
+ append: <div className="self-end">🍩</div>,
68
+ id: 'my-id',
69
+ },
70
+ };
71
+
72
+ export const Disabled: Story = {
73
+ args: {
74
+ placeholder: 'Luke Skywalker',
75
+ label: 'Name',
76
+ disabled: true,
77
+ },
78
+ };
79
+
80
+ export const Readonly: Story = {
81
+ args: {
82
+ placeholder: 'Luke Skywalker',
83
+ label: 'Name',
84
+ readOnly: true,
85
+ value: 'Darth Vader',
86
+ },
87
+ };
88
+
89
+ export const PassingPropsToLabel: Story = {
90
+ args: {
91
+ placeholder: 'Luke Skywalker',
92
+ label: 'Name',
93
+ value: 'Darth Vader',
94
+ labelProps: {
95
+ className: 'bg-elevated',
96
+ },
97
+ },
98
+ };
@@ -0,0 +1,3 @@
1
+ import './input-with-label.css';
2
+
3
+ export { InputWithLabel } from './input-with-label';
@@ -0,0 +1,35 @@
1
+ .c-input-with-label {
2
+ @apply relative block rounded border border-solid border-transparent p-3;
3
+
4
+ &-input-wrap {
5
+ @apply mt-3 flex;
6
+ }
7
+
8
+ &-input {
9
+ @apply flex-1 overflow-hidden text-ellipsis text-base;
10
+ }
11
+
12
+ &-append {
13
+ @apply -mr-3 flex flex-shrink-0 items-center px-3;
14
+ }
15
+
16
+ &-elevated {
17
+ @apply bg-elevate shadow;
18
+ }
19
+
20
+ &.c-input-with-label--error {
21
+ @apply text-error;
22
+ }
23
+
24
+ &-error {
25
+ @apply !mt-1 text-xs text-error;
26
+ }
27
+
28
+ &-sm {
29
+ @apply text-sm;
30
+ }
31
+
32
+ &-lg {
33
+ @apply text-lg;
34
+ }
35
+ }
@@ -0,0 +1,59 @@
1
+ import { ComponentPropsWithoutRef, ComponentPropsWithRef, forwardRef, ReactNode } from 'react';
2
+ import { cva, cx, VariantProps } from 'class-variance-authority';
3
+
4
+ import { Input } from '../input';
5
+ import { Label } from '../label';
6
+ import { Triangle } from '../iconography/triangle';
7
+
8
+ const inputWithLabelStyles = cva(['c-input-with-label'], {
9
+ variants: {
10
+ variant: {
11
+ default: '',
12
+ elevated: 'c-input-with-label-elevated',
13
+ outlined: 'c-input-with-label-outlined',
14
+ },
15
+ status: {
16
+ error: 'c-input-with-label--error',
17
+ },
18
+ },
19
+ defaultVariants: {},
20
+ });
21
+
22
+ type InputWithLabelStylesProps = VariantProps<typeof inputWithLabelStyles>;
23
+
24
+ export type InputWithLabelProps = InputWithLabelStylesProps & {
25
+ label: string;
26
+ append?: ReactNode;
27
+ errorMessage?: string;
28
+ labelProps?: ComponentPropsWithoutRef<'label'>;
29
+ } & ComponentPropsWithRef<'input'>;
30
+
31
+ export type InputWithLabelRef = HTMLInputElement;
32
+
33
+ export const InputWithLabel = forwardRef<InputWithLabelRef, InputWithLabelProps>(
34
+ ({ className, label, append, errorMessage, status, variant, id, labelProps, ...delegated }, ref) => {
35
+ const { className: labelClassName, ...labelPropsRest } = labelProps ?? {};
36
+
37
+ return (
38
+ <>
39
+ <Label
40
+ className={inputWithLabelStyles({ status, variant, className: labelClassName })}
41
+ htmlFor={id}
42
+ {...labelPropsRest}
43
+ >
44
+ {label}
45
+ <span className="c-input-with-label-input-wrap">
46
+ <Input className={cx('c-input-with-label-input', className)} ref={ref} id={id} {...delegated} />
47
+ {!append && !errorMessage ? null : (
48
+ <div className="c-input-with-label-append" title={errorMessage}>
49
+ {errorMessage ? <Triangle /> : append}
50
+ </div>
51
+ )}
52
+ </span>
53
+ </Label>
54
+ </>
55
+ );
56
+ },
57
+ );
58
+
59
+ InputWithLabel.displayName = 'InputWithLabel';
@@ -0,0 +1,3 @@
1
+ .c-label {
2
+ @apply text-sm font-medium text-gray-500-400;
3
+ }
@@ -1,11 +1,13 @@
1
1
  import { forwardRef, LabelHTMLAttributes } from 'react';
2
2
  import { cx } from 'class-variance-authority';
3
3
 
4
+ import './label.css';
5
+
4
6
  type LabelRef = HTMLLabelElement;
5
7
  type LabelProps = LabelHTMLAttributes<LabelRef>;
6
8
 
7
9
  export const Label = forwardRef<LabelRef, LabelProps>(({ className, ...delegated }, ref) => {
8
- return <label ref={ref} className={cx('text-xs font-medium text-gray-400', className)} {...delegated} />;
10
+ return <label ref={ref} className={cx('c-label', className)} {...delegated} />;
9
11
  });
10
12
 
11
13
  Label.displayName = 'Label';
@@ -0,0 +1,7 @@
1
+ .c-progress-root {
2
+ @apply relative h-4 w-full overflow-hidden rounded-full bg-gray-50-900;
3
+ }
4
+
5
+ .c-progress-indicator {
6
+ @apply h-full w-full transform bg-cyan-300-600 duration-500 ease-linear;
7
+ }
@@ -1,15 +1,16 @@
1
1
  import * as ProgressPrimitives from '@radix-ui/react-progress';
2
+ import { cx } from 'class-variance-authority';
2
3
 
3
- type ProgressProps = {
4
- value: number;
5
- };
4
+ import './progress.css';
6
5
 
7
- export function Progress({ value }: ProgressProps) {
6
+ type ProgressProps = ProgressPrimitives.ProgressProps;
7
+
8
+ export function Progress({ className, value }: ProgressProps) {
8
9
  return (
9
- <ProgressPrimitives.Root className="relative overflow-hidden rounded-full w-full h-6 bg-neutral-200" value={value}>
10
+ <ProgressPrimitives.Root className={cx(className, 'c-progress-root')} value={value}>
10
11
  <ProgressPrimitives.Indicator
11
- className="bg-[#50dbdc] w-full h-full transform ease-linear duration-500"
12
- style={{ transform: `translateX(-${100 - value}%)` }}
12
+ className="c-progress-indicator"
13
+ style={{ transform: `translateX(-${100 - (value ?? 0)}%)` }}
13
14
  />
14
15
  </ProgressPrimitives.Root>
15
16
  );
@@ -0,0 +1,20 @@
1
+ .c-radio-item {
2
+ @apply flex h-3 w-3 flex-shrink-0 items-center justify-center rounded-full border border-solid border-gray-200-700 bg-gray-50-900 p-0;
3
+
4
+ &:focus,
5
+ &:focus-visible {
6
+ @apply outline-none;
7
+ }
8
+
9
+ &:disabled {
10
+ @apply bg-gray-100-800 opacity-40;
11
+ }
12
+
13
+ &[aria-checked='true'] {
14
+ @apply border-cyan-700-200 bg-cyan-200-700;
15
+ }
16
+ }
17
+
18
+ .c-radio-indicator {
19
+ @apply block h-[6px] w-[6px] rounded-full bg-cyan-700-200;
20
+ }
@@ -1,21 +1,14 @@
1
1
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
2
- import { cx } from 'class-variance-authority';
3
2
  import type { ComponentProps } from 'react';
4
3
 
4
+ import './radio.css';
5
+
5
6
  type RadioGroupItemProps = ComponentProps<typeof RadioGroupPrimitive.Item>;
6
7
 
7
8
  function RadioGroupItem(props: RadioGroupItemProps) {
8
9
  return (
9
- <RadioGroupPrimitive.Item
10
- {...props}
11
- className={cx(
12
- 'flex h-3 w-3 flex-shrink-0 items-center justify-center rounded-full border border-solid border-[#ddd] bg-white p-0',
13
- 'focus:outline-none',
14
- 'disabled:bg-[#ddd]/20',
15
- 'radix-state-checked:border-[#528693] radix-state-checked:bg-neptune',
16
- )}
17
- >
18
- <RadioGroupPrimitive.Indicator className={cx('block h-[6px] w-[6px] rounded-full bg-[#528693]')} />
10
+ <RadioGroupPrimitive.Item {...props} className="c-radio-item">
11
+ <RadioGroupPrimitive.Indicator className="c-radio-indicator" />
19
12
  </RadioGroupPrimitive.Item>
20
13
  );
21
14
  }
@@ -1,6 +1,5 @@
1
1
  import { ComponentProps, forwardRef } from 'react';
2
2
  import * as SelectPrimitives from '@radix-ui/react-select';
3
- import { cx } from 'class-variance-authority';
4
3
 
5
4
  export type SelectItemRef = HTMLDivElement;
6
5
  export type SelectItemProps = ComponentProps<typeof SelectPrimitives.Item>;
@@ -9,15 +8,7 @@ export const SelectItem = forwardRef<SelectItemRef, SelectItemProps>((props, ref
9
8
  const { children, ...delegated } = props;
10
9
 
11
10
  return (
12
- <SelectPrimitives.Item
13
- className={cx(
14
- 'flex cursor-pointer items-center whitespace-nowrap px-6 py-2 font-medium',
15
- 'focus:bg-neptune/20',
16
- 'hover:bg-neptune/20',
17
- )}
18
- ref={ref}
19
- {...delegated}
20
- >
11
+ <SelectPrimitives.Item className="c-select-item" ref={ref} {...delegated}>
21
12
  <SelectPrimitives.ItemText>{children}</SelectPrimitives.ItemText>
22
13
  <SelectPrimitives.ItemIndicator />
23
14
  </SelectPrimitives.Item>
@@ -1,7 +1,7 @@
1
1
  import { ComponentProps, forwardRef } from 'react';
2
2
  import * as SelectPrimitives from '@radix-ui/react-select';
3
3
 
4
- import { Icon } from '../icons';
4
+ import { Icon } from '../iconography';
5
5
 
6
6
  export type SelectRef = HTMLButtonElement;
7
7
  export type SelectProps = ComponentProps<typeof SelectPrimitives.Root> & {
@@ -14,22 +14,15 @@ export const SelectContainer = forwardRef<SelectRef, SelectProps>(
14
14
  ({ children, id, placeholder, disabled, ...delegated }, ref) => {
15
15
  return (
16
16
  <SelectPrimitives.Root {...delegated}>
17
- <SelectPrimitives.Trigger
18
- ref={ref}
19
- className="inline-flex cursor-pointer items-center justify-center gap-4 whitespace-nowrap rounded border-0 bg-white px-4 py-3 text-sm font-medium text-black-text shadow disabled:cursor-default disabled:opacity-50"
20
- disabled={disabled}
21
- id={id}
22
- >
23
- <SelectPrimitives.Value
24
- placeholder={<span className="italic text-label">{placeholder ?? 'Select...'}</span>}
25
- />
17
+ <SelectPrimitives.Trigger ref={ref} className="c-select-trigger" disabled={disabled} id={id}>
18
+ <SelectPrimitives.Value placeholder={<span className="c-select-value">{placeholder ?? 'Select...'}</span>} />
26
19
  <Icon.Arrow />
27
20
  </SelectPrimitives.Trigger>
28
21
 
29
22
  <SelectPrimitives.Portal>
30
- <SelectPrimitives.Content className="overflow-hidden rounded bg-white text-black-text shadow">
23
+ <SelectPrimitives.Content className="c-select-content">
31
24
  <SelectPrimitives.ScrollUpButton />
32
- <SelectPrimitives.Viewport className="py-2">{children}</SelectPrimitives.Viewport>
25
+ <SelectPrimitives.Viewport className="c-select-viewport">{children}</SelectPrimitives.Viewport>
33
26
  <SelectPrimitives.ScrollDownButton />
34
27
  </SelectPrimitives.Content>
35
28
  </SelectPrimitives.Portal>
@@ -0,0 +1,28 @@
1
+ .c-select-trigger {
2
+ @apply inline-flex cursor-pointer items-center justify-center gap-4 whitespace-nowrap rounded border-0 bg-elevate px-4 py-3 text-sm font-medium text-gray shadow;
3
+
4
+ &:disabled {
5
+ @apply cursor-default opacity-50;
6
+ }
7
+ }
8
+
9
+ .c-select-value {
10
+ @apply italic text-gray-500-400;
11
+ }
12
+
13
+ .c-select-content {
14
+ @apply overflow-hidden rounded bg-elevate text-gray shadow;
15
+ }
16
+
17
+ .c-select-viewport {
18
+ @apply py-2;
19
+ }
20
+
21
+ .c-select-item {
22
+ @apply flex cursor-pointer items-center whitespace-nowrap px-6 py-2 font-medium text-gray;
23
+
24
+ &:hover,
25
+ &:focus {
26
+ @apply bg-gray-50-900 outline-none;
27
+ }
28
+ }
@@ -1,5 +1,6 @@
1
1
  import { useState } from 'react';
2
2
  import type { Meta } from '@storybook/react';
3
+
3
4
  import { Select } from './select';
4
5
  import { Label } from '../label';
5
6
 
@@ -60,3 +61,14 @@ export const WithLabel = () => {
60
61
  </div>
61
62
  );
62
63
  };
64
+
65
+ export const Disabled = () => {
66
+ return (
67
+ <Select.Container disabled>
68
+ <Select.Item value="react">React</Select.Item>
69
+ <Select.Item value="vue">Vue</Select.Item>
70
+ <Select.Item value="svelte">Svelte</Select.Item>
71
+ <Select.Item value="angular">Angular</Select.Item>
72
+ </Select.Container>
73
+ );
74
+ };
@@ -1,6 +1,8 @@
1
1
  import { SelectItem } from './select-item';
2
2
  import { SelectContainer } from './select-root';
3
3
 
4
+ import './select.css';
5
+
4
6
  export const Select = {
5
7
  Container: SelectContainer,
6
8
  Item: SelectItem,
@@ -0,0 +1,19 @@
1
+ import type { StoryObj, Meta } from '@storybook/react';
2
+ import { Spinner } from '.';
3
+
4
+ const meta: Meta<typeof Spinner> = {
5
+ title: 'Components/Spinner',
6
+ component: Spinner,
7
+ argTypes: {
8
+ size: {
9
+ defaultValue: 30,
10
+ },
11
+ },
12
+ };
13
+
14
+ export default meta;
15
+ type Story = StoryObj<typeof Spinner>;
16
+
17
+ export const Default: Story = {
18
+ args: {},
19
+ };
@@ -0,0 +1,48 @@
1
+ import { cx } from 'class-variance-authority';
2
+ import { ComponentPropsWithRef, forwardRef, ReactNode } from 'react';
3
+
4
+ import './spinner.css';
5
+
6
+ const realSize = 40;
7
+
8
+ type SpinnerProps = ComponentPropsWithRef<'div'> & {
9
+ children?: ReactNode;
10
+ className?: string;
11
+ color?: string;
12
+ size?: number;
13
+ strokeSize?: number;
14
+ };
15
+
16
+ export const Spinner = forwardRef<HTMLDivElement, SpinnerProps>(
17
+ ({ children, className, color = 'currentColor', size = 30, strokeSize, ...delegated }, ref) => {
18
+ const viewSize = size || realSize;
19
+ const sizeHalf = realSize / 2;
20
+
21
+ return (
22
+ <div ref={ref} className={cx('c-spinner', className)} data-testid="loading-spinner" {...delegated}>
23
+ <svg viewBox={`0 0 ${realSize} ${realSize}`} x="0px" y="0px" style={{ width: viewSize, height: viewSize }}>
24
+ <circle
25
+ cx="20"
26
+ cy="20"
27
+ r="18"
28
+ style={{
29
+ stroke: color,
30
+ strokeWidth: strokeSize ? strokeSize : viewSize / 10,
31
+ strokeLinecap: 'round',
32
+ strokeDasharray: size < 16 ? size * 6 : size * 3.5,
33
+ transformOrigin: `${sizeHalf}px ${sizeHalf}px 0`,
34
+ }}
35
+ className="c-spinner-artifact"
36
+ />
37
+ </svg>
38
+ {children && (
39
+ <span className="c-spinner-children" style={{ fontSize: size ? `${size * 0.75}px` : '1em' }}>
40
+ {children}
41
+ </span>
42
+ )}
43
+ </div>
44
+ );
45
+ },
46
+ );
47
+
48
+ Spinner.displayName = 'Spinner';
@@ -0,0 +1,11 @@
1
+ .c-spinner {
2
+ @apply inline-flex items-center;
3
+
4
+ &-artifact {
5
+ @apply animate-spin fill-transparent;
6
+ }
7
+
8
+ &-children {
9
+ @apply ml-[15px] inline-block;
10
+ }
11
+ }
@@ -0,0 +1,51 @@
1
+ /* eslint-disable @typescript-eslint/no-var-requires */
2
+ const defaultTheme = require('tailwindcss/defaultTheme');
3
+ const colorsPlugin = require('./plugins/colors');
4
+
5
+ /** @type {import("tailwindcss").Config} */
6
+ module.exports = {
7
+ content: ['./src/**/*.tsx'],
8
+ safelist: ['c-dark'],
9
+ experimental: {
10
+ optimizeUniversalDefaults: true,
11
+ },
12
+ corePlugins: {
13
+ preflight: false,
14
+ },
15
+ theme: {
16
+ extend: {
17
+ fontFamily: {
18
+ sans: ['Roboto', ...defaultTheme.fontFamily.sans],
19
+ serif: ["'Roboto Slab'", ...defaultTheme.fontFamily.serif],
20
+ },
21
+ colors: {
22
+ // Some nice-to-have colors
23
+ transparent: 'transparent',
24
+ inherit: 'inherit',
25
+ },
26
+ keyframes: {
27
+ spin: {
28
+ '0%': {
29
+ transform: 'rotate(0deg)',
30
+ strokeDashoffset: 26.4, // 40 * 0.66
31
+ },
32
+ '50%': {
33
+ transform: 'rotate(720deg)',
34
+ strokeDashoffset: 125.6, // 40 * 3.14
35
+ },
36
+ '100%': {
37
+ transform: 'rotate(1080deg)',
38
+ strokeDashoffset: 26.4, // 40 * 0.66
39
+ },
40
+ },
41
+ },
42
+ animation: {
43
+ spin: 'spin 2s linear infinite',
44
+ },
45
+ boxShadow: {
46
+ DEFAULT: '0 2px 4px rgba(130,138,144,0.15)',
47
+ },
48
+ },
49
+ },
50
+ plugins: [colorsPlugin],
51
+ };
@@ -1,86 +0,0 @@
1
- import type { StoryObj, Meta } from '@storybook/react';
2
- import { Button } from '.';
3
-
4
- const meta: Meta<typeof Button> = {
5
- title: 'Components/ButtonCopy',
6
- component: Button,
7
- argTypes: {},
8
- };
9
-
10
- export default meta;
11
- type Story = StoryObj<typeof Button>;
12
-
13
- const variants = ['contained', 'outline', 'link', 'text'] as const;
14
- const intent = ['default', 'primary', 'success', 'danger'] as const;
15
- const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const;
16
-
17
- export const AllButton: Story = {
18
- name: 'All Buttons',
19
- render: () => {
20
- return (
21
- <div className="grid grid-cols-4 gap-6 justify-items-center">
22
- {sizes.map(size =>
23
- variants.map(variant =>
24
- intent.map(intent => (
25
- <Button variant={variant} size={size} intent={intent}>
26
- Click me
27
- </Button>
28
- )),
29
- ),
30
- )}
31
- </div>
32
- );
33
- },
34
- };
35
-
36
- export const Contained: Story = {
37
- args: {
38
- variant: 'contained',
39
- children: 'Button',
40
- },
41
- };
42
-
43
- export const Outline: Story = {
44
- args: {
45
- variant: 'outline',
46
- children: 'Button',
47
- },
48
- };
49
-
50
- export const Link: Story = {
51
- args: {
52
- variant: 'link',
53
- children: 'Button',
54
- },
55
- };
56
-
57
- export const Text: Story = {
58
- args: {
59
- variant: 'text',
60
- children: 'Button',
61
- },
62
- };
63
-
64
- export const Primary: Story = {
65
- args: {
66
- variant: 'contained',
67
- children: 'Button',
68
- intent: 'primary',
69
- },
70
- };
71
-
72
- export const Success: Story = {
73
- args: {
74
- variant: 'contained',
75
- children: 'Button',
76
- intent: 'success',
77
- },
78
- };
79
-
80
- export const Danger: Story = {
81
- args: {
82
- variant: 'contained',
83
- children: 'Button',
84
- intent: 'danger',
85
- },
86
- };