@nattui/react-components 0.0.1 → 0.0.3

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/.prettierrc CHANGED
@@ -1,4 +1,5 @@
1
1
  {
2
+ "cssDeclarationSorterOrder": "alphabetical",
2
3
  "jsonRecursiveSort": true,
3
4
  "plugins": [
4
5
  "prettier-plugin-css-order",
@@ -1,6 +1,6 @@
1
1
 
2
2
  
3
- > @nattui/react-components@0.0.1 build /Users/snowshift/Documents/3-github/react-components/packages/ui
3
+ > @nattui/react-components@0.0.3 build /Users/snowshift/Documents/3-github/react-components/packages/ui
4
4
  > tsup
5
5
 
6
6
  CLI Building entry: src/index.ts
@@ -11,19 +11,19 @@
11
11
  CLI Cleaning output folder
12
12
  ESM Build start
13
13
  CJS Build start
14
- ESM dist/button-spinner.module-IRIJPNSF.module.css 1.49 KB
15
- ESM dist/button.module-QR72PPSM.module.css 5.60 KB
16
- ESM dist/button-background.module-FK4ABTRO.module.css 667.00 B
17
- ESM dist/index.mjs 3.42 KB
18
- ESM dist/index.mjs.map 7.61 KB
19
- ESM ⚡️ Build success in 83ms
20
- CJS dist/button-spinner.module-IRIJPNSF.module.css 1.49 KB
21
- CJS dist/button.module-QR72PPSM.module.css 5.60 KB
22
- CJS dist/button-background.module-FK4ABTRO.module.css 667.00 B
23
- CJS dist/index.js 4.14 KB
24
- CJS dist/index.js.map 7.66 KB
25
- CJS ⚡️ Build success in 83ms
14
+ CJS dist/button-background.module-T5B7XZ2Z.module.css 702.00 B
15
+ CJS dist/button-spinner.module-4TBETQ4T.module.css 1.49 KB
16
+ CJS dist/button.module-N3Y5HX7N.module.css 5.83 KB
17
+ CJS dist/index.js 4.26 KB
18
+ CJS dist/index.js.map 7.92 KB
19
+ CJS ⚡️ Build success in 76ms
20
+ ESM dist/button.module-N3Y5HX7N.module.css 5.83 KB
21
+ ESM dist/button-background.module-T5B7XZ2Z.module.css 702.00 B
22
+ ESM dist/button-spinner.module-4TBETQ4T.module.css 1.49 KB
23
+ ESM dist/index.mjs 3.53 KB
24
+ ESM dist/index.mjs.map 7.87 KB
25
+ ESM ⚡️ Build success in 77ms
26
26
  DTS Build start
27
- DTS ⚡️ Build success in 682ms
28
- DTS dist/index.d.mts 1.31 KB
29
- DTS dist/index.d.ts 1.31 KB
27
+ DTS ⚡️ Build success in 698ms
28
+ DTS dist/index.d.mts 1.37 KB
29
+ DTS dist/index.d.ts 1.37 KB
@@ -1,14 +1,15 @@
1
1
  /* Base */
2
2
  .button_background {
3
- position: absolute;
4
- top: 0;
5
- right: 0;
6
3
  bottom: 50%;
4
+ filter: none !important;
7
5
  left: 0;
8
6
  opacity: 0.2;
7
+ position: absolute;
8
+ right: 0;
9
+ top: 0;
10
+ transition-duration: inherit;
11
+ transition-property: opacity;
9
12
  z-index: -1;
10
- filter: none !important;
11
- transition: opacity 150ms;
12
13
  }
13
14
 
14
15
  /* Rounded */
@@ -2,31 +2,39 @@
2
2
  /* Base */
3
3
  /* ===================================================== */
4
4
  .button {
5
- display: flex;
6
- position: relative;
5
+ align-items: safe center;
6
+ border-color: transparent;
7
+ border-style: solid;
8
+ border-width: 1px;
7
9
  column-gap: 8px;
10
+ cursor: pointer;
11
+ display: flex;
8
12
  flex-shrink: 0;
13
+ font-weight: 500;
9
14
  justify-content: safe center;
10
- align-items: safe center;
11
- transition-duration: 150ms;
12
- transition-property: all;
13
- cursor: pointer;
15
+ line-height: 1.5;
16
+ outline-color: var(--color-primary-9, #e93d82);
17
+ outline-offset: 2px;
18
+ outline-style: solid;
14
19
  outline-width: 0;
15
- border-width: 1px;
16
- border-style: solid;
17
- border-color: transparent;
18
20
  overflow: hidden;
19
- font-weight: 500;
20
- line-height: 1.5;
21
+ position: relative;
22
+ transition-duration: 150ms;
23
+ transition-property:
24
+ background-color, box-shadow, border-color, color, opacity;
21
25
  user-select: none;
22
26
  }
23
27
 
24
28
  .button:disabled {
25
- opacity: 0.5;
26
29
  cursor: not-allowed;
30
+ opacity: 0.5;
27
31
  }
28
32
 
29
- /* Active */
33
+ .button:focus-visible {
34
+ outline-width: 2px;
35
+ }
36
+
37
+ /* Active children */
30
38
  .button:enabled[aria-pressed="true"] > *,
31
39
  .button:enabled:active > * {
32
40
  transform: translateY(1px);
@@ -79,30 +87,30 @@
79
87
  /* ===================================================== */
80
88
  .button__size_32 {
81
89
  --size: 32px;
82
- padding: 0 8px;
83
- height: var(--size);
84
90
  font-size: 14px;
91
+ height: var(--size);
92
+ padding: 0 8px;
85
93
  }
86
94
 
87
95
  .button__size_36 {
88
96
  --size: 36px;
89
- padding: 0 12px;
90
- height: var(--size);
91
97
  font-size: 14px;
98
+ height: var(--size);
99
+ padding: 0 12px;
92
100
  }
93
101
 
94
102
  .button__size_40 {
95
103
  --size: 40px;
96
- padding: 0 16px;
97
- height: var(--size);
98
104
  font-size: 14px;
105
+ height: var(--size);
106
+ padding: 0 16px;
99
107
  }
100
108
 
101
109
  .button__size_48 {
102
110
  --size: 48px;
103
- padding: 0 20px;
104
- height: var(--size);
105
111
  font-size: 16px;
112
+ height: var(--size);
113
+ padding: 0 20px;
106
114
  }
107
115
 
108
116
  /* ===================================================== */
@@ -110,15 +118,15 @@
110
118
  /* ===================================================== */
111
119
  /* Accent */
112
120
  .button__variant_accent {
113
- box-shadow:
114
- inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
115
- inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
116
- border-color: var(--color-primary-9, #e93d82);
117
121
  background-image: linear-gradient(
118
122
  to bottom,
119
123
  var(--color-primary-9, #e93d82),
120
124
  var(--color-primary-10, #e03177)
121
125
  );
126
+ border-color: var(--color-primary-9, #e93d82);
127
+ box-shadow:
128
+ inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
129
+ inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
122
130
  color: var(--color-gray-1, #fdfcfd);
123
131
  }
124
132
 
@@ -126,7 +134,7 @@
126
134
  .button__variant_accent:enabled:active {
127
135
  box-shadow:
128
136
  inset 0 -1px 0 0 rgba(255, 255, 255, 0.25),
129
- inset 0 1px 0 0 rgba(0, 0, 0, 0.1) !important;
137
+ inset 0 1px 0 0 var(--color-primary-11, #d31e66) !important;
130
138
  }
131
139
 
132
140
  /* Ghost */
@@ -152,15 +160,15 @@
152
160
 
153
161
  /* Primary */
154
162
  .button__variant_primary {
155
- box-shadow:
156
- inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
157
- inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
158
- border-color: var(--color-gray-12, #1a1523);
159
163
  background-image: linear-gradient(
160
164
  to bottom,
161
165
  color-mix(in oklab, var(--color-gray-12, #1a1523) 90%, transparent),
162
166
  var(--color-gray-12, #1a1523)
163
167
  );
168
+ border-color: var(--color-gray-12, #1a1523);
169
+ box-shadow:
170
+ inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
171
+ inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
164
172
  color: var(--color-gray-1, #fdfcfd);
165
173
  }
166
174
 
@@ -168,20 +176,20 @@
168
176
  .button__variant_primary:enabled:active {
169
177
  box-shadow:
170
178
  inset 0 -1px 0 0 rgba(255, 255, 255, 0.25),
171
- inset 0 1px 0 0 rgba(0, 0, 0, 0.5) !important;
179
+ inset 0 1px 0 0 var(--color-gray-12, #1a1523) !important;
172
180
  }
173
181
 
174
182
  /* Secondary */
175
183
  .button__variant_secondary {
176
- box-shadow:
177
- inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
178
- inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
179
- border-color: var(--color-gray-6, #e4e2e4);
180
184
  background-image: linear-gradient(
181
185
  to bottom,
182
186
  var(--color-gray-1, #fdfcfd),
183
187
  var(--color-gray-3, #f4f2f4)
184
188
  );
189
+ border-color: var(--color-gray-6, #e4e2e4);
190
+ box-shadow:
191
+ inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
192
+ inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
185
193
  color: var(--color-gray-11, #6f6e77);
186
194
  }
187
195
 
@@ -217,8 +225,8 @@
217
225
  .button__variant_accent:enabled:hover,
218
226
  .button__variant_primary:enabled:hover,
219
227
  .button__variant_secondary:enabled:hover {
220
- filter: none;
221
228
  box-shadow: inset 0 0 0 0 transparent;
229
+ filter: none;
222
230
  }
223
231
 
224
232
  .button__variant_ghost:enabled:hover,
package/dist/index.d.mts CHANGED
@@ -1,10 +1,12 @@
1
1
  import { ComponentProps, ReactNode, JSX } from 'react';
2
2
 
3
- interface ButtonProps extends ComponentProps<"button"> {
3
+ interface ButtonProps extends Omit<ComponentProps<"button">, "disabled"> {
4
4
  fullWidth?: boolean;
5
5
  iconEnd?: ReactNode;
6
6
  iconOnly?: boolean;
7
7
  iconStart?: ReactNode;
8
+ isActive?: boolean;
9
+ isDisabled?: boolean;
8
10
  isLoading?: boolean;
9
11
  rounded?: boolean;
10
12
  size?: 32 | 36 | 40 | 48;
package/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  import { ComponentProps, ReactNode, JSX } from 'react';
2
2
 
3
- interface ButtonProps extends ComponentProps<"button"> {
3
+ interface ButtonProps extends Omit<ComponentProps<"button">, "disabled"> {
4
4
  fullWidth?: boolean;
5
5
  iconEnd?: ReactNode;
6
6
  iconOnly?: boolean;
7
7
  iconStart?: ReactNode;
8
+ isActive?: boolean;
9
+ isDisabled?: boolean;
8
10
  isLoading?: boolean;
9
11
  rounded?: boolean;
10
12
  size?: 32 | 36 | 40 | 48;
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var styles = require('./button-background.module-FK4ABTRO.module.css');
3
+ var styles = require('./button-background.module-T5B7XZ2Z.module.css');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
- var styles2 = require('./button-spinner.module-IRIJPNSF.module.css');
6
- var styles3 = require('./button.module-QR72PPSM.module.css');
5
+ var styles2 = require('./button-spinner.module-4TBETQ4T.module.css');
6
+ var styles3 = require('./button.module-N3Y5HX7N.module.css');
7
7
 
8
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
9
 
@@ -55,11 +55,12 @@ function Button(props) {
55
55
  const {
56
56
  children = "",
57
57
  className: customClassName = "",
58
- disabled = false,
59
58
  fullWidth = false,
60
59
  iconEnd = "",
61
60
  iconOnly = false,
62
61
  iconStart = "",
62
+ isActive = false,
63
+ isDisabled = false,
63
64
  isLoading = false,
64
65
  rounded = false,
65
66
  size = 36,
@@ -79,15 +80,16 @@ function Button(props) {
79
80
  return /* @__PURE__ */ jsxRuntime.jsxs(
80
81
  "button",
81
82
  {
83
+ "aria-pressed": isActive,
82
84
  className: combinedClassName,
83
- disabled: disabled || isLoading,
85
+ disabled: isDisabled || isLoading,
84
86
  type,
85
87
  ...rest,
86
88
  children: [
87
89
  /* @__PURE__ */ jsxRuntime.jsx(ButtonBackground, { rounded, variant }),
88
90
  isLoading && /* @__PURE__ */ jsxRuntime.jsx(ButtonSpinner, {}),
89
91
  !isLoading && iconStart,
90
- children,
92
+ iconOnly ? children : /* @__PURE__ */ jsxRuntime.jsx("span", { children }),
91
93
  !isLoading && iconEnd
92
94
  ]
93
95
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/button-background.tsx","../src/button-spinner.tsx","../src/button.tsx"],"names":["jsx","Fragment","styles","jsxs"],"mappings":"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","file":"index.js","sourcesContent":["import type { JSX } from \"react\"\nimport type { ButtonProps } from \"@/button\"\nimport styles from \"@/button-background.module.css\"\n\nexport interface ButtonBackgroundProps\n extends Pick<ButtonProps, \"rounded\" | \"variant\"> {}\n\nexport function ButtonBackground(props: ButtonBackgroundProps): JSX.Element {\n const { rounded = false, variant = \"primary\" } = props\n\n const combinedBackgroundStyles = `\n ${BUTTON_BACKGROUND_CLASS_NAME.BASE}\n ${rounded ? BUTTON_BACKGROUND_CLASS_NAME.ROUNDED.FULL : BUTTON_BACKGROUND_CLASS_NAME.ROUNDED.BASE}\n ${variant === \"accent\" ? BUTTON_BACKGROUND_CLASS_NAME.VARIANT.ACCENT : \"\"}\n ${variant === \"primary\" ? BUTTON_BACKGROUND_CLASS_NAME.VARIANT.PRIMARY : \"\"}\n `\n .replaceAll(/\\s+/g, \" \")\n .trim()\n\n if (!(variant === \"accent\" || variant === \"primary\")) return <></>\n\n return (\n <div\n className={combinedBackgroundStyles}\n data-element=\"button-background\"\n />\n )\n}\n\nexport const BUTTON_BACKGROUND_CLASS_NAME = {\n BASE: styles.button_background,\n ROUNDED: {\n BASE: styles.button_background__rounded_base,\n FULL: styles.button_background__rounded_full,\n },\n VARIANT: {\n ACCENT: styles.button_background__variant_accent,\n PRIMARY: styles.button_background__variant_primary,\n },\n} as const\n","import type { CSSProperties, JSX } from \"react\"\nimport styles from \"@/button-spinner.module.css\"\n\nexport interface ButtonSpinnerProps {\n size?: number\n}\n\nexport function ButtonSpinner(props: ButtonSpinnerProps): JSX.Element {\n const { size = 16 } = props\n\n return (\n <div\n className={styles.button_spinner}\n style={{ \"--size\": `${size}px` } as CSSProperties}\n >\n {Array.from({ length: 12 }).map((_, index) => (\n <div key={index} />\n ))}\n </div>\n )\n}\n","import type { ComponentProps, JSX, ReactNode } from \"react\"\nimport { ButtonBackground } from \"@/button-background\"\nimport { ButtonSpinner } from \"@/button-spinner\"\nimport styles from \"@/button.module.css\"\n\nexport interface ButtonProps extends ComponentProps<\"button\"> {\n fullWidth?: boolean\n iconEnd?: ReactNode\n iconOnly?: boolean\n iconStart?: ReactNode\n isLoading?: boolean\n rounded?: boolean\n size?: 32 | 36 | 40 | 48\n variant?: \"accent\" | \"ghost\" | \"primary\" | \"secondary\"\n}\n\ntype ButtonPropsInternal = ButtonPropsWithIcon | ButtonPropsWithText\n\ninterface ButtonPropsWithIcon extends ButtonProps {\n children?: ReactNode\n iconOnly: true\n}\n\ninterface ButtonPropsWithText extends ButtonProps {\n children?: string\n iconOnly?: false\n}\n\nexport function Button(props: ButtonPropsInternal): JSX.Element {\n const {\n children = \"\",\n className: customClassName = \"\",\n disabled = false,\n fullWidth = false,\n iconEnd = \"\",\n iconOnly = false,\n iconStart = \"\",\n isLoading = false,\n rounded = false,\n size = 36,\n type = \"button\",\n variant = \"primary\",\n ...rest\n } = props\n\n const combinedClassName = `\n ${BUTTON_CLASS_NAME.BASE}\n ${BUTTON_CLASS_NAME.SIZE[size]}\n ${BUTTON_CLASS_NAME.VARIANT[variant.toUpperCase() as keyof typeof BUTTON_CLASS_NAME.VARIANT]}\n ${fullWidth ? BUTTON_CLASS_NAME.WIDTH.FULL : BUTTON_CLASS_NAME.WIDTH.BASE}\n ${iconOnly ? BUTTON_CLASS_NAME.ICON_ONLY : \"\"}\n ${rounded ? BUTTON_CLASS_NAME.ROUNDED.FULL : BUTTON_CLASS_NAME.ROUNDED.BASE}\n ${customClassName}\n `\n .replaceAll(/\\s+/g, \" \")\n .trim()\n\n return (\n <button\n className={combinedClassName}\n disabled={disabled || isLoading}\n type={type}\n {...rest}\n >\n <ButtonBackground rounded={rounded} variant={variant} />\n {isLoading && <ButtonSpinner />}\n {!isLoading && iconStart}\n {children}\n {!isLoading && iconEnd}\n </button>\n )\n}\n\nexport const BUTTON_CLASS_NAME = {\n BASE: styles.button,\n ICON_ONLY: styles.button__icon_only,\n ROUNDED: {\n BASE: styles.button__rounded_base,\n FULL: styles.button__rounded_full,\n },\n SIZE: {\n 32: styles.button__size_32,\n 36: styles.button__size_36,\n 40: styles.button__size_40,\n 48: styles.button__size_48,\n },\n VARIANT: {\n ACCENT: styles.button__variant_accent,\n GHOST: styles.button__variant_ghost,\n PRIMARY: styles.button__variant_primary,\n SECONDARY: styles.button__variant_secondary,\n },\n WIDTH: {\n BASE: styles.button__width_base,\n FULL: styles.button__width_full,\n },\n} as const\n"]}
1
+ {"version":3,"sources":["../src/button-background.tsx","../src/button-spinner.tsx","../src/button.tsx"],"names":["jsx","Fragment","styles","jsxs"],"mappings":";;;;;;;;;;;;;;AAOO,SAAS,iBAAiB,KAA2C,EAAA;AAC1E,EAAA,MAAM,EAAE,OAAA,GAAU,KAAO,EAAA,OAAA,GAAU,WAAc,GAAA,KAAA;AAEjD,EAAA,MAAM,wBAA2B,GAAA;AAAA,IAAA,EAC7B,6BAA6B,IAAI;AAAA,IAAA,EACjC,UAAU,4BAA6B,CAAA,OAAA,CAAQ,IAAO,GAAA,4BAAA,CAA6B,QAAQ,IAAI;AAAA,IAAA,EAC/F,OAAY,KAAA,QAAA,GAAW,4BAA6B,CAAA,OAAA,CAAQ,SAAS,EAAE;AAAA,IAAA,EACvE,OAAY,KAAA,SAAA,GAAY,4BAA6B,CAAA,OAAA,CAAQ,UAAU,EAAE;AAAA,EAAA,CAAA,CAE1E,UAAW,CAAA,MAAA,EAAQ,GAAG,CAAA,CACtB,IAAK,EAAA;AAER,EAAA,IAAI,EAAE,OAAY,KAAA,QAAA,IAAY,OAAY,KAAA,SAAA,CAAA,yBAAqBA,cAAA,CAAAC,mBAAA,EAAA,EAAA,CAAA;AAE/D,EACE,uBAAAD,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAW,EAAA,wBAAA;AAAA,MACX,cAAa,EAAA;AAAA;AAAA,GACf;AAEJ;AAEO,IAAM,4BAA+B,GAAA;AAAA,EAC1C,MAAME,uBAAO,CAAA,iBAAA;AAAA,EACb,OAAS,EAAA;AAAA,IACP,MAAMA,uBAAO,CAAA,+BAAA;AAAA,IACb,MAAMA,uBAAO,CAAA;AAAA,GACf;AAAA,EACA,OAAS,EAAA;AAAA,IACP,QAAQA,uBAAO,CAAA,iCAAA;AAAA,IACf,SAASA,uBAAO,CAAA;AAAA;AAEpB,CAAA;AChCO,SAAS,cAAc,KAAwC,EAAA;AACpE,EAAM,MAAA,EAAE,IAAO,GAAA,EAAA,EAAO,GAAA,KAAA;AAEtB,EAAA,uBACEF,cAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAWE,wBAAO,CAAA,cAAA;AAAA,MAClB,KAAO,EAAA,EAAE,QAAU,EAAA,CAAA,EAAG,IAAI,CAAK,EAAA,CAAA,EAAA;AAAA,MAE9B,QAAM,EAAA,KAAA,CAAA,IAAA,CAAK,EAAE,MAAA,EAAQ,IAAI,CAAA,CAAE,GAAI,CAAA,CAAC,GAAG,KAClC,qBAAAF,cAAC,CAAA,KAAA,EAAA,EAAA,EAAS,KAAO,CAClB;AAAA;AAAA,GACH;AAEJ;ACWO,SAAS,OAAO,KAAyC,EAAA;AAC9D,EAAM,MAAA;AAAA,IACJ,QAAW,GAAA,EAAA;AAAA,IACX,WAAW,eAAkB,GAAA,EAAA;AAAA,IAC7B,SAAY,GAAA,KAAA;AAAA,IACZ,OAAU,GAAA,EAAA;AAAA,IACV,QAAW,GAAA,KAAA;AAAA,IACX,SAAY,GAAA,EAAA;AAAA,IACZ,QAAW,GAAA,KAAA;AAAA,IACX,UAAa,GAAA,KAAA;AAAA,IACb,SAAY,GAAA,KAAA;AAAA,IACZ,OAAU,GAAA,KAAA;AAAA,IACV,IAAO,GAAA,EAAA;AAAA,IACP,IAAO,GAAA,QAAA;AAAA,IACP,OAAU,GAAA,SAAA;AAAA,IACV,GAAG;AAAA,GACD,GAAA,KAAA;AAEJ,EAAA,MAAM,iBAAoB,GAAA;AAAA,IAAA,EACtB,kBAAkB,IAAI;AAAA,IACtB,EAAA,iBAAA,CAAkB,IAAK,CAAA,IAAI,CAAC;AAAA,IAAA,EAC5B,iBAAkB,CAAA,OAAA,CAAQ,OAAQ,CAAA,WAAA,EAAuD,CAAC;AAAA,IAAA,EAC1F,YAAY,iBAAkB,CAAA,KAAA,CAAM,IAAO,GAAA,iBAAA,CAAkB,MAAM,IAAI;AAAA,IACvE,EAAA,QAAA,GAAW,iBAAkB,CAAA,SAAA,GAAY,EAAE;AAAA,IAAA,EAC3C,UAAU,iBAAkB,CAAA,OAAA,CAAQ,IAAO,GAAA,iBAAA,CAAkB,QAAQ,IAAI;AAAA,IAAA,EACzE,eAAe;AAAA,EAAA,CAAA,CAEhB,UAAW,CAAA,MAAA,EAAQ,GAAG,CAAA,CACtB,IAAK,EAAA;AAER,EACE,uBAAAG,eAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,cAAc,EAAA,QAAA;AAAA,MACd,SAAW,EAAA,iBAAA;AAAA,MACX,UAAU,UAAc,IAAA,SAAA;AAAA,MACxB,IAAA;AAAA,MACC,GAAG,IAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAAH,cAAAA,CAAC,gBAAiB,EAAA,EAAA,OAAA,EAAkB,OAAkB,EAAA,CAAA;AAAA,QACrD,SAAA,oBAAaA,cAAAA,CAAC,aAAc,EAAA,EAAA,CAAA;AAAA,QAC5B,CAAC,SAAa,IAAA,SAAA;AAAA,QACd,QAAW,GAAA,QAAA,mBAAWA,cAAAA,CAAC,UAAM,QAAS,EAAA,CAAA;AAAA,QACtC,CAAC,SAAa,IAAA;AAAA;AAAA;AAAA,GACjB;AAEJ;AAEO,IAAM,iBAAoB,GAAA;AAAA,EAC/B,MAAME,wBAAO,CAAA,MAAA;AAAA,EACb,WAAWA,wBAAO,CAAA,iBAAA;AAAA,EAClB,OAAS,EAAA;AAAA,IACP,MAAMA,wBAAO,CAAA,oBAAA;AAAA,IACb,MAAMA,wBAAO,CAAA;AAAA,GACf;AAAA,EACA,IAAM,EAAA;AAAA,IACJ,IAAIA,wBAAO,CAAA,eAAA;AAAA,IACX,IAAIA,wBAAO,CAAA,eAAA;AAAA,IACX,IAAIA,wBAAO,CAAA,eAAA;AAAA,IACX,IAAIA,wBAAO,CAAA;AAAA,GACb;AAAA,EACA,OAAS,EAAA;AAAA,IACP,QAAQA,wBAAO,CAAA,sBAAA;AAAA,IACf,OAAOA,wBAAO,CAAA,qBAAA;AAAA,IACd,SAASA,wBAAO,CAAA,uBAAA;AAAA,IAChB,WAAWA,wBAAO,CAAA;AAAA,GACpB;AAAA,EACA,KAAO,EAAA;AAAA,IACL,MAAMA,wBAAO,CAAA,kBAAA;AAAA,IACb,MAAMA,wBAAO,CAAA;AAAA;AAEjB","file":"index.js","sourcesContent":["import type { JSX } from \"react\"\nimport type { ButtonProps } from \"@/button\"\nimport styles from \"@/button-background.module.css\"\n\nexport interface ButtonBackgroundProps\n extends Pick<ButtonProps, \"rounded\" | \"variant\"> {}\n\nexport function ButtonBackground(props: ButtonBackgroundProps): JSX.Element {\n const { rounded = false, variant = \"primary\" } = props\n\n const combinedBackgroundStyles = `\n ${BUTTON_BACKGROUND_CLASS_NAME.BASE}\n ${rounded ? BUTTON_BACKGROUND_CLASS_NAME.ROUNDED.FULL : BUTTON_BACKGROUND_CLASS_NAME.ROUNDED.BASE}\n ${variant === \"accent\" ? BUTTON_BACKGROUND_CLASS_NAME.VARIANT.ACCENT : \"\"}\n ${variant === \"primary\" ? BUTTON_BACKGROUND_CLASS_NAME.VARIANT.PRIMARY : \"\"}\n `\n .replaceAll(/\\s+/g, \" \")\n .trim()\n\n if (!(variant === \"accent\" || variant === \"primary\")) return <></>\n\n return (\n <div\n className={combinedBackgroundStyles}\n data-element=\"button-background\"\n />\n )\n}\n\nexport const BUTTON_BACKGROUND_CLASS_NAME = {\n BASE: styles.button_background,\n ROUNDED: {\n BASE: styles.button_background__rounded_base,\n FULL: styles.button_background__rounded_full,\n },\n VARIANT: {\n ACCENT: styles.button_background__variant_accent,\n PRIMARY: styles.button_background__variant_primary,\n },\n} as const\n","import type { CSSProperties, JSX } from \"react\"\nimport styles from \"@/button-spinner.module.css\"\n\nexport interface ButtonSpinnerProps {\n size?: number\n}\n\nexport function ButtonSpinner(props: ButtonSpinnerProps): JSX.Element {\n const { size = 16 } = props\n\n return (\n <div\n className={styles.button_spinner}\n style={{ \"--size\": `${size}px` } as CSSProperties}\n >\n {Array.from({ length: 12 }).map((_, index) => (\n <div key={index} />\n ))}\n </div>\n )\n}\n","import type { ComponentProps, JSX, ReactNode } from \"react\"\nimport { ButtonBackground } from \"@/button-background\"\nimport { ButtonSpinner } from \"@/button-spinner\"\nimport styles from \"@/button.module.css\"\n\nexport interface ButtonProps\n extends Omit<ComponentProps<\"button\">, \"disabled\"> {\n fullWidth?: boolean\n iconEnd?: ReactNode\n iconOnly?: boolean\n iconStart?: ReactNode\n isActive?: boolean\n isDisabled?: boolean\n isLoading?: boolean\n rounded?: boolean\n size?: 32 | 36 | 40 | 48\n variant?: \"accent\" | \"ghost\" | \"primary\" | \"secondary\"\n}\n\ntype ButtonPropsInternal = ButtonPropsWithIcon | ButtonPropsWithText\n\ninterface ButtonPropsWithIcon extends ButtonProps {\n children?: ReactNode\n iconOnly: true\n}\n\ninterface ButtonPropsWithText extends ButtonProps {\n children?: string\n iconOnly?: false\n}\n\nexport function Button(props: ButtonPropsInternal): JSX.Element {\n const {\n children = \"\",\n className: customClassName = \"\",\n fullWidth = false,\n iconEnd = \"\",\n iconOnly = false,\n iconStart = \"\",\n isActive = false,\n isDisabled = false,\n isLoading = false,\n rounded = false,\n size = 36,\n type = \"button\",\n variant = \"primary\",\n ...rest\n } = props\n\n const combinedClassName = `\n ${BUTTON_CLASS_NAME.BASE}\n ${BUTTON_CLASS_NAME.SIZE[size]}\n ${BUTTON_CLASS_NAME.VARIANT[variant.toUpperCase() as keyof typeof BUTTON_CLASS_NAME.VARIANT]}\n ${fullWidth ? BUTTON_CLASS_NAME.WIDTH.FULL : BUTTON_CLASS_NAME.WIDTH.BASE}\n ${iconOnly ? BUTTON_CLASS_NAME.ICON_ONLY : \"\"}\n ${rounded ? BUTTON_CLASS_NAME.ROUNDED.FULL : BUTTON_CLASS_NAME.ROUNDED.BASE}\n ${customClassName}\n `\n .replaceAll(/\\s+/g, \" \")\n .trim()\n\n return (\n <button\n aria-pressed={isActive}\n className={combinedClassName}\n disabled={isDisabled || isLoading}\n type={type}\n {...rest}\n >\n <ButtonBackground rounded={rounded} variant={variant} />\n {isLoading && <ButtonSpinner />}\n {!isLoading && iconStart}\n {iconOnly ? children : <span>{children}</span>}\n {!isLoading && iconEnd}\n </button>\n )\n}\n\nexport const BUTTON_CLASS_NAME = {\n BASE: styles.button,\n ICON_ONLY: styles.button__icon_only,\n ROUNDED: {\n BASE: styles.button__rounded_base,\n FULL: styles.button__rounded_full,\n },\n SIZE: {\n 32: styles.button__size_32,\n 36: styles.button__size_36,\n 40: styles.button__size_40,\n 48: styles.button__size_48,\n },\n VARIANT: {\n ACCENT: styles.button__variant_accent,\n GHOST: styles.button__variant_ghost,\n PRIMARY: styles.button__variant_primary,\n SECONDARY: styles.button__variant_secondary,\n },\n WIDTH: {\n BASE: styles.button__width_base,\n FULL: styles.button__width_full,\n },\n} as const\n"]}
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import styles from './button-background.module-FK4ABTRO.module.css';
1
+ import styles from './button-background.module-T5B7XZ2Z.module.css';
2
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
- import styles2 from './button-spinner.module-IRIJPNSF.module.css';
4
- import styles3 from './button.module-QR72PPSM.module.css';
3
+ import styles2 from './button-spinner.module-4TBETQ4T.module.css';
4
+ import styles3 from './button.module-N3Y5HX7N.module.css';
5
5
 
6
6
  // src/button-background.tsx
7
7
  function ButtonBackground(props) {
@@ -47,11 +47,12 @@ function Button(props) {
47
47
  const {
48
48
  children = "",
49
49
  className: customClassName = "",
50
- disabled = false,
51
50
  fullWidth = false,
52
51
  iconEnd = "",
53
52
  iconOnly = false,
54
53
  iconStart = "",
54
+ isActive = false,
55
+ isDisabled = false,
55
56
  isLoading = false,
56
57
  rounded = false,
57
58
  size = 36,
@@ -71,15 +72,16 @@ function Button(props) {
71
72
  return /* @__PURE__ */ jsxs(
72
73
  "button",
73
74
  {
75
+ "aria-pressed": isActive,
74
76
  className: combinedClassName,
75
- disabled: disabled || isLoading,
77
+ disabled: isDisabled || isLoading,
76
78
  type,
77
79
  ...rest,
78
80
  children: [
79
81
  /* @__PURE__ */ jsx(ButtonBackground, { rounded, variant }),
80
82
  isLoading && /* @__PURE__ */ jsx(ButtonSpinner, {}),
81
83
  !isLoading && iconStart,
82
- children,
84
+ iconOnly ? children : /* @__PURE__ */ jsx("span", { children }),
83
85
  !isLoading && iconEnd
84
86
  ]
85
87
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/button-background.tsx","../src/button-spinner.tsx","../src/button.tsx"],"names":["jsx","styles"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { JSX } from \"react\"\nimport type { ButtonProps } from \"@/button\"\nimport styles from \"@/button-background.module.css\"\n\nexport interface ButtonBackgroundProps\n extends Pick<ButtonProps, \"rounded\" | \"variant\"> {}\n\nexport function ButtonBackground(props: ButtonBackgroundProps): JSX.Element {\n const { rounded = false, variant = \"primary\" } = props\n\n const combinedBackgroundStyles = `\n ${BUTTON_BACKGROUND_CLASS_NAME.BASE}\n ${rounded ? BUTTON_BACKGROUND_CLASS_NAME.ROUNDED.FULL : BUTTON_BACKGROUND_CLASS_NAME.ROUNDED.BASE}\n ${variant === \"accent\" ? BUTTON_BACKGROUND_CLASS_NAME.VARIANT.ACCENT : \"\"}\n ${variant === \"primary\" ? BUTTON_BACKGROUND_CLASS_NAME.VARIANT.PRIMARY : \"\"}\n `\n .replaceAll(/\\s+/g, \" \")\n .trim()\n\n if (!(variant === \"accent\" || variant === \"primary\")) return <></>\n\n return (\n <div\n className={combinedBackgroundStyles}\n data-element=\"button-background\"\n />\n )\n}\n\nexport const BUTTON_BACKGROUND_CLASS_NAME = {\n BASE: styles.button_background,\n ROUNDED: {\n BASE: styles.button_background__rounded_base,\n FULL: styles.button_background__rounded_full,\n },\n VARIANT: {\n ACCENT: styles.button_background__variant_accent,\n PRIMARY: styles.button_background__variant_primary,\n },\n} as const\n","import type { CSSProperties, JSX } from \"react\"\nimport styles from \"@/button-spinner.module.css\"\n\nexport interface ButtonSpinnerProps {\n size?: number\n}\n\nexport function ButtonSpinner(props: ButtonSpinnerProps): JSX.Element {\n const { size = 16 } = props\n\n return (\n <div\n className={styles.button_spinner}\n style={{ \"--size\": `${size}px` } as CSSProperties}\n >\n {Array.from({ length: 12 }).map((_, index) => (\n <div key={index} />\n ))}\n </div>\n )\n}\n","import type { ComponentProps, JSX, ReactNode } from \"react\"\nimport { ButtonBackground } from \"@/button-background\"\nimport { ButtonSpinner } from \"@/button-spinner\"\nimport styles from \"@/button.module.css\"\n\nexport interface ButtonProps extends ComponentProps<\"button\"> {\n fullWidth?: boolean\n iconEnd?: ReactNode\n iconOnly?: boolean\n iconStart?: ReactNode\n isLoading?: boolean\n rounded?: boolean\n size?: 32 | 36 | 40 | 48\n variant?: \"accent\" | \"ghost\" | \"primary\" | \"secondary\"\n}\n\ntype ButtonPropsInternal = ButtonPropsWithIcon | ButtonPropsWithText\n\ninterface ButtonPropsWithIcon extends ButtonProps {\n children?: ReactNode\n iconOnly: true\n}\n\ninterface ButtonPropsWithText extends ButtonProps {\n children?: string\n iconOnly?: false\n}\n\nexport function Button(props: ButtonPropsInternal): JSX.Element {\n const {\n children = \"\",\n className: customClassName = \"\",\n disabled = false,\n fullWidth = false,\n iconEnd = \"\",\n iconOnly = false,\n iconStart = \"\",\n isLoading = false,\n rounded = false,\n size = 36,\n type = \"button\",\n variant = \"primary\",\n ...rest\n } = props\n\n const combinedClassName = `\n ${BUTTON_CLASS_NAME.BASE}\n ${BUTTON_CLASS_NAME.SIZE[size]}\n ${BUTTON_CLASS_NAME.VARIANT[variant.toUpperCase() as keyof typeof BUTTON_CLASS_NAME.VARIANT]}\n ${fullWidth ? BUTTON_CLASS_NAME.WIDTH.FULL : BUTTON_CLASS_NAME.WIDTH.BASE}\n ${iconOnly ? BUTTON_CLASS_NAME.ICON_ONLY : \"\"}\n ${rounded ? BUTTON_CLASS_NAME.ROUNDED.FULL : BUTTON_CLASS_NAME.ROUNDED.BASE}\n ${customClassName}\n `\n .replaceAll(/\\s+/g, \" \")\n .trim()\n\n return (\n <button\n className={combinedClassName}\n disabled={disabled || isLoading}\n type={type}\n {...rest}\n >\n <ButtonBackground rounded={rounded} variant={variant} />\n {isLoading && <ButtonSpinner />}\n {!isLoading && iconStart}\n {children}\n {!isLoading && iconEnd}\n </button>\n )\n}\n\nexport const BUTTON_CLASS_NAME = {\n BASE: styles.button,\n ICON_ONLY: styles.button__icon_only,\n ROUNDED: {\n BASE: styles.button__rounded_base,\n FULL: styles.button__rounded_full,\n },\n SIZE: {\n 32: styles.button__size_32,\n 36: styles.button__size_36,\n 40: styles.button__size_40,\n 48: styles.button__size_48,\n },\n VARIANT: {\n ACCENT: styles.button__variant_accent,\n GHOST: styles.button__variant_ghost,\n PRIMARY: styles.button__variant_primary,\n SECONDARY: styles.button__variant_secondary,\n },\n WIDTH: {\n BASE: styles.button__width_base,\n FULL: styles.button__width_full,\n },\n} as const\n"]}
1
+ {"version":3,"sources":["../src/button-background.tsx","../src/button-spinner.tsx","../src/button.tsx"],"names":["jsx","styles"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { JSX } from \"react\"\nimport type { ButtonProps } from \"@/button\"\nimport styles from \"@/button-background.module.css\"\n\nexport interface ButtonBackgroundProps\n extends Pick<ButtonProps, \"rounded\" | \"variant\"> {}\n\nexport function ButtonBackground(props: ButtonBackgroundProps): JSX.Element {\n const { rounded = false, variant = \"primary\" } = props\n\n const combinedBackgroundStyles = `\n ${BUTTON_BACKGROUND_CLASS_NAME.BASE}\n ${rounded ? BUTTON_BACKGROUND_CLASS_NAME.ROUNDED.FULL : BUTTON_BACKGROUND_CLASS_NAME.ROUNDED.BASE}\n ${variant === \"accent\" ? BUTTON_BACKGROUND_CLASS_NAME.VARIANT.ACCENT : \"\"}\n ${variant === \"primary\" ? BUTTON_BACKGROUND_CLASS_NAME.VARIANT.PRIMARY : \"\"}\n `\n .replaceAll(/\\s+/g, \" \")\n .trim()\n\n if (!(variant === \"accent\" || variant === \"primary\")) return <></>\n\n return (\n <div\n className={combinedBackgroundStyles}\n data-element=\"button-background\"\n />\n )\n}\n\nexport const BUTTON_BACKGROUND_CLASS_NAME = {\n BASE: styles.button_background,\n ROUNDED: {\n BASE: styles.button_background__rounded_base,\n FULL: styles.button_background__rounded_full,\n },\n VARIANT: {\n ACCENT: styles.button_background__variant_accent,\n PRIMARY: styles.button_background__variant_primary,\n },\n} as const\n","import type { CSSProperties, JSX } from \"react\"\nimport styles from \"@/button-spinner.module.css\"\n\nexport interface ButtonSpinnerProps {\n size?: number\n}\n\nexport function ButtonSpinner(props: ButtonSpinnerProps): JSX.Element {\n const { size = 16 } = props\n\n return (\n <div\n className={styles.button_spinner}\n style={{ \"--size\": `${size}px` } as CSSProperties}\n >\n {Array.from({ length: 12 }).map((_, index) => (\n <div key={index} />\n ))}\n </div>\n )\n}\n","import type { ComponentProps, JSX, ReactNode } from \"react\"\nimport { ButtonBackground } from \"@/button-background\"\nimport { ButtonSpinner } from \"@/button-spinner\"\nimport styles from \"@/button.module.css\"\n\nexport interface ButtonProps\n extends Omit<ComponentProps<\"button\">, \"disabled\"> {\n fullWidth?: boolean\n iconEnd?: ReactNode\n iconOnly?: boolean\n iconStart?: ReactNode\n isActive?: boolean\n isDisabled?: boolean\n isLoading?: boolean\n rounded?: boolean\n size?: 32 | 36 | 40 | 48\n variant?: \"accent\" | \"ghost\" | \"primary\" | \"secondary\"\n}\n\ntype ButtonPropsInternal = ButtonPropsWithIcon | ButtonPropsWithText\n\ninterface ButtonPropsWithIcon extends ButtonProps {\n children?: ReactNode\n iconOnly: true\n}\n\ninterface ButtonPropsWithText extends ButtonProps {\n children?: string\n iconOnly?: false\n}\n\nexport function Button(props: ButtonPropsInternal): JSX.Element {\n const {\n children = \"\",\n className: customClassName = \"\",\n fullWidth = false,\n iconEnd = \"\",\n iconOnly = false,\n iconStart = \"\",\n isActive = false,\n isDisabled = false,\n isLoading = false,\n rounded = false,\n size = 36,\n type = \"button\",\n variant = \"primary\",\n ...rest\n } = props\n\n const combinedClassName = `\n ${BUTTON_CLASS_NAME.BASE}\n ${BUTTON_CLASS_NAME.SIZE[size]}\n ${BUTTON_CLASS_NAME.VARIANT[variant.toUpperCase() as keyof typeof BUTTON_CLASS_NAME.VARIANT]}\n ${fullWidth ? BUTTON_CLASS_NAME.WIDTH.FULL : BUTTON_CLASS_NAME.WIDTH.BASE}\n ${iconOnly ? BUTTON_CLASS_NAME.ICON_ONLY : \"\"}\n ${rounded ? BUTTON_CLASS_NAME.ROUNDED.FULL : BUTTON_CLASS_NAME.ROUNDED.BASE}\n ${customClassName}\n `\n .replaceAll(/\\s+/g, \" \")\n .trim()\n\n return (\n <button\n aria-pressed={isActive}\n className={combinedClassName}\n disabled={isDisabled || isLoading}\n type={type}\n {...rest}\n >\n <ButtonBackground rounded={rounded} variant={variant} />\n {isLoading && <ButtonSpinner />}\n {!isLoading && iconStart}\n {iconOnly ? children : <span>{children}</span>}\n {!isLoading && iconEnd}\n </button>\n )\n}\n\nexport const BUTTON_CLASS_NAME = {\n BASE: styles.button,\n ICON_ONLY: styles.button__icon_only,\n ROUNDED: {\n BASE: styles.button__rounded_base,\n FULL: styles.button__rounded_full,\n },\n SIZE: {\n 32: styles.button__size_32,\n 36: styles.button__size_36,\n 40: styles.button__size_40,\n 48: styles.button__size_48,\n },\n VARIANT: {\n ACCENT: styles.button__variant_accent,\n GHOST: styles.button__variant_ghost,\n PRIMARY: styles.button__variant_primary,\n SECONDARY: styles.button__variant_secondary,\n },\n WIDTH: {\n BASE: styles.button__width_base,\n FULL: styles.button__width_full,\n },\n} as const\n"]}
package/eslint.config.mjs CHANGED
@@ -1,4 +1,3 @@
1
- import css from "@eslint/css"
2
1
  import js from "@eslint/js"
3
2
  import pluginPerfectionist from "eslint-plugin-perfectionist"
4
3
  import pluginReact from "eslint-plugin-react"
@@ -39,16 +38,6 @@ export default defineConfig([
39
38
  files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
40
39
  languageOptions: { globals: globals.browser },
41
40
  },
42
- // CSS configuration
43
- {
44
- extends: ["css/recommended"],
45
- files: ["**/*.css"],
46
- language: "css/css",
47
- plugins: { css },
48
- rules: {
49
- "css/use-baseline": "off",
50
- },
51
- },
52
41
  // JavaScript configuration
53
42
  {
54
43
  extends: ["js/recommended"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nattui/react-components",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "A collection of reusable React components built with TypeScript and CSS Modules",
5
5
  "keywords": [
6
6
  "components",
@@ -21,7 +21,6 @@
21
21
  "module": "./dist/index.js",
22
22
  "types": "./dist/index.d.ts",
23
23
  "devDependencies": {
24
- "@eslint/css": "^0.9.0",
25
24
  "@eslint/js": "^9.29.0",
26
25
  "@types/react": "^19.1.8",
27
26
  "eslint": "^9.29.0",
@@ -1,14 +1,15 @@
1
1
  /* Base */
2
2
  .button_background {
3
- position: absolute;
4
- top: 0;
5
- right: 0;
6
3
  bottom: 50%;
4
+ filter: none !important;
7
5
  left: 0;
8
6
  opacity: 0.2;
7
+ position: absolute;
8
+ right: 0;
9
+ top: 0;
10
+ transition-duration: inherit;
11
+ transition-property: opacity;
9
12
  z-index: -1;
10
- filter: none !important;
11
- transition: opacity 150ms;
12
13
  }
13
14
 
14
15
  /* Rounded */
@@ -1,9 +1,9 @@
1
1
  .button_spinner {
2
+ animation: spinner 1000ms steps(12, end) infinite;
3
+ height: var(--size);
2
4
  position: relative;
3
5
  scale: -1 1;
4
- animation: spinner 1000ms steps(12, end) infinite;
5
6
  width: var(--size);
6
- height: var(--size);
7
7
  }
8
8
 
9
9
  @keyframes spinner {
@@ -13,83 +13,83 @@
13
13
  }
14
14
 
15
15
  .button_spinner > div {
16
+ height: calc(var(--size) / 12);
17
+ pointer-events: none;
16
18
  position: absolute;
17
- top: 50%;
18
19
  right: 0;
20
+ top: 50%;
19
21
  transform-origin: center left;
20
- translate: 0 -50%;
21
22
  transition: all 150ms;
23
+ translate: 0 -50%;
22
24
  width: calc(var(--size) / 2);
23
- height: calc(var(--size) / 12);
24
- pointer-events: none;
25
25
  }
26
26
 
27
27
  .button_spinner > div::after {
28
+ background-color: currentColor;
29
+ border-radius: 9999px;
30
+ content: "";
31
+ height: 100%;
28
32
  position: absolute;
29
33
  right: 0;
30
- border-radius: 9999px;
31
- background-color: currentColor;
32
34
  width: 50%;
33
- height: 100%;
34
- content: "";
35
35
  }
36
36
 
37
37
  .button_spinner > div:nth-child(1) {
38
- rotate: 0deg;
39
38
  opacity: 1;
39
+ rotate: 0deg;
40
40
  }
41
41
 
42
42
  .button_spinner > div:nth-child(2) {
43
- rotate: 30deg;
44
43
  opacity: 0.925;
44
+ rotate: 30deg;
45
45
  }
46
46
 
47
47
  .button_spinner > div:nth-child(3) {
48
- rotate: 60deg;
49
48
  opacity: 0.85;
49
+ rotate: 60deg;
50
50
  }
51
51
 
52
52
  .button_spinner > div:nth-child(4) {
53
- rotate: 90deg;
54
53
  opacity: 0.775;
54
+ rotate: 90deg;
55
55
  }
56
56
 
57
57
  .button_spinner > div:nth-child(5) {
58
- rotate: 120deg;
59
58
  opacity: 0.7;
59
+ rotate: 120deg;
60
60
  }
61
61
 
62
62
  .button_spinner > div:nth-child(6) {
63
- rotate: 150deg;
64
63
  opacity: 0.625;
64
+ rotate: 150deg;
65
65
  }
66
66
 
67
67
  .button_spinner > div:nth-child(7) {
68
- rotate: 180deg;
69
68
  opacity: 0.55;
69
+ rotate: 180deg;
70
70
  }
71
71
 
72
72
  .button_spinner > div:nth-child(8) {
73
- rotate: 210deg;
74
73
  opacity: 0.475;
74
+ rotate: 210deg;
75
75
  }
76
76
 
77
77
  .button_spinner > div:nth-child(9) {
78
- rotate: 240deg;
79
78
  opacity: 0.4;
79
+ rotate: 240deg;
80
80
  }
81
81
 
82
82
  .button_spinner > div:nth-child(10) {
83
- rotate: 270deg;
84
83
  opacity: 0.325;
84
+ rotate: 270deg;
85
85
  }
86
86
 
87
87
  .button_spinner > div:nth-child(11) {
88
- rotate: 300deg;
89
88
  opacity: 0.25;
89
+ rotate: 300deg;
90
90
  }
91
91
 
92
92
  .button_spinner > div:nth-child(12) {
93
- rotate: 330deg;
94
93
  opacity: 0.15;
94
+ rotate: 330deg;
95
95
  }
@@ -2,31 +2,39 @@
2
2
  /* Base */
3
3
  /* ===================================================== */
4
4
  .button {
5
- display: flex;
6
- position: relative;
5
+ align-items: safe center;
6
+ border-color: transparent;
7
+ border-style: solid;
8
+ border-width: 1px;
7
9
  column-gap: 8px;
10
+ cursor: pointer;
11
+ display: flex;
8
12
  flex-shrink: 0;
13
+ font-weight: 500;
9
14
  justify-content: safe center;
10
- align-items: safe center;
11
- transition-duration: 150ms;
12
- transition-property: all;
13
- cursor: pointer;
15
+ line-height: 1.5;
16
+ outline-color: var(--color-primary-9, #e93d82);
17
+ outline-offset: 2px;
18
+ outline-style: solid;
14
19
  outline-width: 0;
15
- border-width: 1px;
16
- border-style: solid;
17
- border-color: transparent;
18
20
  overflow: hidden;
19
- font-weight: 500;
20
- line-height: 1.5;
21
+ position: relative;
22
+ transition-duration: 150ms;
23
+ transition-property:
24
+ background-color, box-shadow, border-color, color, opacity;
21
25
  user-select: none;
22
26
  }
23
27
 
24
28
  .button:disabled {
25
- opacity: 0.5;
26
29
  cursor: not-allowed;
30
+ opacity: 0.5;
27
31
  }
28
32
 
29
- /* Active */
33
+ .button:focus-visible {
34
+ outline-width: 2px;
35
+ }
36
+
37
+ /* Active children */
30
38
  .button:enabled[aria-pressed="true"] > *,
31
39
  .button:enabled:active > * {
32
40
  transform: translateY(1px);
@@ -79,30 +87,30 @@
79
87
  /* ===================================================== */
80
88
  .button__size_32 {
81
89
  --size: 32px;
82
- padding: 0 8px;
83
- height: var(--size);
84
90
  font-size: 14px;
91
+ height: var(--size);
92
+ padding: 0 8px;
85
93
  }
86
94
 
87
95
  .button__size_36 {
88
96
  --size: 36px;
89
- padding: 0 12px;
90
- height: var(--size);
91
97
  font-size: 14px;
98
+ height: var(--size);
99
+ padding: 0 12px;
92
100
  }
93
101
 
94
102
  .button__size_40 {
95
103
  --size: 40px;
96
- padding: 0 16px;
97
- height: var(--size);
98
104
  font-size: 14px;
105
+ height: var(--size);
106
+ padding: 0 16px;
99
107
  }
100
108
 
101
109
  .button__size_48 {
102
110
  --size: 48px;
103
- padding: 0 20px;
104
- height: var(--size);
105
111
  font-size: 16px;
112
+ height: var(--size);
113
+ padding: 0 20px;
106
114
  }
107
115
 
108
116
  /* ===================================================== */
@@ -110,15 +118,15 @@
110
118
  /* ===================================================== */
111
119
  /* Accent */
112
120
  .button__variant_accent {
113
- box-shadow:
114
- inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
115
- inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
116
- border-color: var(--color-primary-9, #e93d82);
117
121
  background-image: linear-gradient(
118
122
  to bottom,
119
123
  var(--color-primary-9, #e93d82),
120
124
  var(--color-primary-10, #e03177)
121
125
  );
126
+ border-color: var(--color-primary-9, #e93d82);
127
+ box-shadow:
128
+ inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
129
+ inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
122
130
  color: var(--color-gray-1, #fdfcfd);
123
131
  }
124
132
 
@@ -126,7 +134,7 @@
126
134
  .button__variant_accent:enabled:active {
127
135
  box-shadow:
128
136
  inset 0 -1px 0 0 rgba(255, 255, 255, 0.25),
129
- inset 0 1px 0 0 rgba(0, 0, 0, 0.1) !important;
137
+ inset 0 1px 0 0 var(--color-primary-11, #d31e66) !important;
130
138
  }
131
139
 
132
140
  /* Ghost */
@@ -152,15 +160,15 @@
152
160
 
153
161
  /* Primary */
154
162
  .button__variant_primary {
155
- box-shadow:
156
- inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
157
- inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
158
- border-color: var(--color-gray-12, #1a1523);
159
163
  background-image: linear-gradient(
160
164
  to bottom,
161
165
  color-mix(in oklab, var(--color-gray-12, #1a1523) 90%, transparent),
162
166
  var(--color-gray-12, #1a1523)
163
167
  );
168
+ border-color: var(--color-gray-12, #1a1523);
169
+ box-shadow:
170
+ inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
171
+ inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
164
172
  color: var(--color-gray-1, #fdfcfd);
165
173
  }
166
174
 
@@ -168,20 +176,20 @@
168
176
  .button__variant_primary:enabled:active {
169
177
  box-shadow:
170
178
  inset 0 -1px 0 0 rgba(255, 255, 255, 0.25),
171
- inset 0 1px 0 0 rgba(0, 0, 0, 0.5) !important;
179
+ inset 0 1px 0 0 var(--color-gray-12, #1a1523) !important;
172
180
  }
173
181
 
174
182
  /* Secondary */
175
183
  .button__variant_secondary {
176
- box-shadow:
177
- inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
178
- inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
179
- border-color: var(--color-gray-6, #e4e2e4);
180
184
  background-image: linear-gradient(
181
185
  to bottom,
182
186
  var(--color-gray-1, #fdfcfd),
183
187
  var(--color-gray-3, #f4f2f4)
184
188
  );
189
+ border-color: var(--color-gray-6, #e4e2e4);
190
+ box-shadow:
191
+ inset 0 1px 0 0 rgba(255, 255, 255, 0.25),
192
+ inset 0 -1px 0 0 rgba(0, 0, 0, 0.1);
185
193
  color: var(--color-gray-11, #6f6e77);
186
194
  }
187
195
 
@@ -217,8 +225,8 @@
217
225
  .button__variant_accent:enabled:hover,
218
226
  .button__variant_primary:enabled:hover,
219
227
  .button__variant_secondary:enabled:hover {
220
- filter: none;
221
228
  box-shadow: inset 0 0 0 0 transparent;
229
+ filter: none;
222
230
  }
223
231
 
224
232
  .button__variant_ghost:enabled:hover,
package/src/button.tsx CHANGED
@@ -3,11 +3,14 @@ import { ButtonBackground } from "@/button-background"
3
3
  import { ButtonSpinner } from "@/button-spinner"
4
4
  import styles from "@/button.module.css"
5
5
 
6
- export interface ButtonProps extends ComponentProps<"button"> {
6
+ export interface ButtonProps
7
+ extends Omit<ComponentProps<"button">, "disabled"> {
7
8
  fullWidth?: boolean
8
9
  iconEnd?: ReactNode
9
10
  iconOnly?: boolean
10
11
  iconStart?: ReactNode
12
+ isActive?: boolean
13
+ isDisabled?: boolean
11
14
  isLoading?: boolean
12
15
  rounded?: boolean
13
16
  size?: 32 | 36 | 40 | 48
@@ -30,11 +33,12 @@ export function Button(props: ButtonPropsInternal): JSX.Element {
30
33
  const {
31
34
  children = "",
32
35
  className: customClassName = "",
33
- disabled = false,
34
36
  fullWidth = false,
35
37
  iconEnd = "",
36
38
  iconOnly = false,
37
39
  iconStart = "",
40
+ isActive = false,
41
+ isDisabled = false,
38
42
  isLoading = false,
39
43
  rounded = false,
40
44
  size = 36,
@@ -57,15 +61,16 @@ export function Button(props: ButtonPropsInternal): JSX.Element {
57
61
 
58
62
  return (
59
63
  <button
64
+ aria-pressed={isActive}
60
65
  className={combinedClassName}
61
- disabled={disabled || isLoading}
66
+ disabled={isDisabled || isLoading}
62
67
  type={type}
63
68
  {...rest}
64
69
  >
65
70
  <ButtonBackground rounded={rounded} variant={variant} />
66
71
  {isLoading && <ButtonSpinner />}
67
72
  {!isLoading && iconStart}
68
- {children}
73
+ {iconOnly ? children : <span>{children}</span>}
69
74
  {!isLoading && iconEnd}
70
75
  </button>
71
76
  )
@@ -1,9 +1,9 @@
1
1
  .button_spinner {
2
+ animation: spinner 1000ms steps(12, end) infinite;
3
+ height: var(--size);
2
4
  position: relative;
3
5
  scale: -1 1;
4
- animation: spinner 1000ms steps(12, end) infinite;
5
6
  width: var(--size);
6
- height: var(--size);
7
7
  }
8
8
 
9
9
  @keyframes spinner {
@@ -13,83 +13,83 @@
13
13
  }
14
14
 
15
15
  .button_spinner > div {
16
+ height: calc(var(--size) / 12);
17
+ pointer-events: none;
16
18
  position: absolute;
17
- top: 50%;
18
19
  right: 0;
20
+ top: 50%;
19
21
  transform-origin: center left;
20
- translate: 0 -50%;
21
22
  transition: all 150ms;
23
+ translate: 0 -50%;
22
24
  width: calc(var(--size) / 2);
23
- height: calc(var(--size) / 12);
24
- pointer-events: none;
25
25
  }
26
26
 
27
27
  .button_spinner > div::after {
28
+ background-color: currentColor;
29
+ border-radius: 9999px;
30
+ content: "";
31
+ height: 100%;
28
32
  position: absolute;
29
33
  right: 0;
30
- border-radius: 9999px;
31
- background-color: currentColor;
32
34
  width: 50%;
33
- height: 100%;
34
- content: "";
35
35
  }
36
36
 
37
37
  .button_spinner > div:nth-child(1) {
38
- rotate: 0deg;
39
38
  opacity: 1;
39
+ rotate: 0deg;
40
40
  }
41
41
 
42
42
  .button_spinner > div:nth-child(2) {
43
- rotate: 30deg;
44
43
  opacity: 0.925;
44
+ rotate: 30deg;
45
45
  }
46
46
 
47
47
  .button_spinner > div:nth-child(3) {
48
- rotate: 60deg;
49
48
  opacity: 0.85;
49
+ rotate: 60deg;
50
50
  }
51
51
 
52
52
  .button_spinner > div:nth-child(4) {
53
- rotate: 90deg;
54
53
  opacity: 0.775;
54
+ rotate: 90deg;
55
55
  }
56
56
 
57
57
  .button_spinner > div:nth-child(5) {
58
- rotate: 120deg;
59
58
  opacity: 0.7;
59
+ rotate: 120deg;
60
60
  }
61
61
 
62
62
  .button_spinner > div:nth-child(6) {
63
- rotate: 150deg;
64
63
  opacity: 0.625;
64
+ rotate: 150deg;
65
65
  }
66
66
 
67
67
  .button_spinner > div:nth-child(7) {
68
- rotate: 180deg;
69
68
  opacity: 0.55;
69
+ rotate: 180deg;
70
70
  }
71
71
 
72
72
  .button_spinner > div:nth-child(8) {
73
- rotate: 210deg;
74
73
  opacity: 0.475;
74
+ rotate: 210deg;
75
75
  }
76
76
 
77
77
  .button_spinner > div:nth-child(9) {
78
- rotate: 240deg;
79
78
  opacity: 0.4;
79
+ rotate: 240deg;
80
80
  }
81
81
 
82
82
  .button_spinner > div:nth-child(10) {
83
- rotate: 270deg;
84
83
  opacity: 0.325;
84
+ rotate: 270deg;
85
85
  }
86
86
 
87
87
  .button_spinner > div:nth-child(11) {
88
- rotate: 300deg;
89
88
  opacity: 0.25;
89
+ rotate: 300deg;
90
90
  }
91
91
 
92
92
  .button_spinner > div:nth-child(12) {
93
- rotate: 330deg;
94
93
  opacity: 0.15;
94
+ rotate: 330deg;
95
95
  }