@noya-app/noya-designsystem 0.1.31 → 0.1.33

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 (61) hide show
  1. package/.turbo/turbo-build.log +20 -12
  2. package/.turbo/turbo-lint.log +2 -1
  3. package/CHANGELOG.md +14 -0
  4. package/README.md +13 -1
  5. package/dist/index.css +1 -0
  6. package/dist/index.d.ts +132 -509
  7. package/dist/index.js +4167 -2716
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +4097 -2643
  10. package/dist/index.mjs.map +1 -1
  11. package/package.json +15 -6
  12. package/src/components/ActivityIndicator.tsx +4 -36
  13. package/src/components/Avatar.tsx +63 -62
  14. package/src/components/Button.tsx +53 -172
  15. package/src/components/Chip.tsx +117 -150
  16. package/src/components/ContextMenu.tsx +13 -35
  17. package/src/components/Dialog.tsx +66 -54
  18. package/src/components/Divider.tsx +31 -41
  19. package/src/components/DraggableMenuButton.tsx +29 -30
  20. package/src/components/DropdownMenu.tsx +30 -40
  21. package/src/components/FillInputField.tsx +16 -26
  22. package/src/components/FillPreviewBackground.tsx +18 -22
  23. package/src/components/FloatingWindow.tsx +4 -7
  24. package/src/components/GridView.tsx +70 -200
  25. package/src/components/IconButton.tsx +1 -5
  26. package/src/components/InputField.tsx +191 -194
  27. package/src/components/InputFieldWithCompletions.tsx +20 -27
  28. package/src/components/InspectorContainer.tsx +4 -9
  29. package/src/components/InspectorPrimitives.tsx +135 -109
  30. package/src/components/Label.tsx +5 -36
  31. package/src/components/LabeledElementView.tsx +5 -26
  32. package/src/components/ListView.tsx +239 -167
  33. package/src/components/Popover.tsx +15 -39
  34. package/src/components/Progress.tsx +21 -44
  35. package/src/components/RadioGroup.tsx +6 -71
  36. package/src/components/ScrollArea.tsx +11 -39
  37. package/src/components/SelectMenu.tsx +31 -48
  38. package/src/components/Slider.tsx +7 -43
  39. package/src/components/Spacer.tsx +6 -18
  40. package/src/components/Switch.tsx +4 -42
  41. package/src/components/Text.tsx +31 -66
  42. package/src/components/TextArea.tsx +5 -31
  43. package/src/components/Toast.tsx +15 -57
  44. package/src/components/Tooltip.tsx +4 -13
  45. package/src/components/WorkspaceLayout.tsx +4 -14
  46. package/src/components/internal/Menu.tsx +37 -83
  47. package/src/contexts/DesignSystemConfiguration.tsx +1 -47
  48. package/src/contexts/DialogContext.tsx +2 -10
  49. package/src/hooks/useDarkMode.ts +14 -0
  50. package/src/index.css +108 -0
  51. package/src/index.tsx +3 -4
  52. package/src/theme/index.ts +4 -16
  53. package/src/utils/tailwind.ts +17 -0
  54. package/tailwind.config.ts +106 -166
  55. package/tsup.config.ts +16 -0
  56. package/dist/index.d.mts +0 -1443
  57. package/src/components/Grid.tsx +0 -54
  58. package/src/components/Stack.tsx +0 -164
  59. package/src/theme/dark.ts +0 -45
  60. package/src/theme/light.ts +0 -226
  61. package/src/utils/breakpoints.ts +0 -45
@@ -7,6 +7,7 @@ import React, {
7
7
  CSSProperties,
8
8
  ForwardedRef,
9
9
  forwardRef,
10
+ HTMLAttributes,
10
11
  isValidElement,
11
12
  memo,
12
13
  ReactElement,
@@ -21,11 +22,10 @@ import React, {
21
22
  } from "react";
22
23
  import { WindowScroller, WindowScrollerChildProps } from "react-virtualized";
23
24
  import { ListChildComponentProps, VariableSizeList } from "react-window";
24
- import styled from "styled-components";
25
25
  import { mergeEventHandlers } from "../hooks/mergeEventHandlers";
26
26
  import { useHover } from "../hooks/useHover";
27
27
  import { ContextMenu } from "./ContextMenu";
28
- import { InputField } from "./InputField";
28
+ import { InputField, InputFieldInputProps } from "./InputField";
29
29
  import { MenuItem } from "./internal/Menu";
30
30
  import { ScrollArea } from "./ScrollArea";
31
31
  import {
@@ -95,22 +95,38 @@ const ListRowContext = createContext<ListRowContextValue>({
95
95
  * RowTitle
96
96
  * ------------------------------------------------------------------------- */
97
97
 
98
- const ListViewRowTitle = styled.span(({ theme }) => ({
99
- flex: "1 1 0",
100
- overflow: "hidden",
101
- textOverflow: "ellipsis",
102
- whiteSpace: "pre",
103
- }));
98
+ const ListViewRowTitle = ({
99
+ className,
100
+ children,
101
+ ...props
102
+ }: {
103
+ className?: string;
104
+ children: React.ReactNode;
105
+ } & HTMLAttributes<HTMLSpanElement>) => (
106
+ <span
107
+ className={`flex-1 overflow-hidden text-ellipsis whitespace-pre ${className ?? ""}`}
108
+ {...props}
109
+ >
110
+ {children}
111
+ </span>
112
+ );
104
113
 
105
114
  /* ----------------------------------------------------------------------------
106
115
  * EditableRowTitle
107
116
  * ------------------------------------------------------------------------- */
108
117
 
109
- const ListViewEditableRowTitleElement = styled(InputField.Input)(
110
- ({ theme }) => ({
111
- background: theme.colors.listView.editingBackground,
112
- })
113
- ) as typeof InputField.Input;
118
+ const ListViewEditableRowTitleElement = forwardRef(
119
+ (
120
+ { className, ...props }: InputFieldInputProps,
121
+ forwardedRef: ForwardedRef<HTMLInputElement>
122
+ ) => (
123
+ <InputField.Input
124
+ ref={forwardedRef}
125
+ className={`bg-listview-editing-background ${className ?? ""}`}
126
+ {...props}
127
+ />
128
+ )
129
+ );
114
130
 
115
131
  export interface EditableRowProps {
116
132
  value: string;
@@ -164,147 +180,216 @@ function getPositionMargin(marginType: ListRowMarginType) {
164
180
  * Row
165
181
  * ------------------------------------------------------------------------- */
166
182
 
167
- const RowContainer = styled.div<{
168
- $marginType: ListRowMarginType;
169
- $selected: boolean;
170
- $selectedPosition: ListRowPosition;
171
- $disabled: boolean;
172
- $hovered: boolean;
173
- $variant: ListViewVariant;
174
- $divider: boolean;
175
- $isSectionHeader: boolean;
176
- $showsActiveState: boolean;
177
- $sectionHeaderVariant: ListViewSectionHeaderVariant;
178
- $colorScheme: ListColorScheme;
179
- $gap: number;
180
- $backgroundColor?: CSSProperties["backgroundColor"];
181
- }>(
182
- ({
183
- theme,
184
- $marginType,
185
- $selected,
186
- $selectedPosition,
187
- $disabled,
188
- $hovered,
189
- $variant,
190
- $divider,
191
- $isSectionHeader,
192
- $showsActiveState,
193
- $sectionHeaderVariant,
194
- $colorScheme,
195
- $gap,
196
- $backgroundColor,
197
- }) => {
183
+ const theme = {
184
+ colors: {
185
+ textMuted: "var(--text-muted)",
186
+ listView: {
187
+ raisedBackground: "var(--listview-raised-background)",
188
+ },
189
+ secondary: "var(--secondary)",
190
+ primary: "var(--primary)",
191
+ textDisabled: "var(--text-disabled)",
192
+ primaryLight: "var(--primary-light)",
193
+ secondaryLight: "var(--secondary-light)",
194
+ activeBackground: "var(--active-background)",
195
+ dividerSubtle: "var(--divider-subtle)",
196
+ },
197
+ };
198
+
199
+ const RowContainer = forwardRef<
200
+ HTMLDivElement,
201
+ React.HTMLAttributes<HTMLDivElement> & {
202
+ $marginType: ListRowMarginType;
203
+ $selected: boolean;
204
+ $selectedPosition: ListRowPosition;
205
+ $disabled: boolean;
206
+ $hovered: boolean;
207
+ $variant: ListViewVariant;
208
+ $divider: boolean;
209
+ $isSectionHeader: boolean;
210
+ $showsActiveState: boolean;
211
+ $sectionHeaderVariant: ListViewSectionHeaderVariant;
212
+ $colorScheme: ListColorScheme;
213
+ $gap: number;
214
+ $backgroundColor?: CSSProperties["backgroundColor"];
215
+ }
216
+ >(
217
+ (
218
+ {
219
+ className,
220
+ $marginType,
221
+ $selected,
222
+ $selectedPosition,
223
+ $disabled,
224
+ $hovered,
225
+ $variant,
226
+ $divider,
227
+ $isSectionHeader,
228
+ $showsActiveState,
229
+ $sectionHeaderVariant,
230
+ $colorScheme,
231
+ $gap,
232
+ $backgroundColor,
233
+ style,
234
+ ...props
235
+ },
236
+ ref
237
+ ) => {
198
238
  const margin = getPositionMargin($marginType);
199
239
 
200
- return {
201
- ...($isSectionHeader && $sectionHeaderVariant === "label"
202
- ? theme.textStyles.label
203
- : theme.textStyles.small),
204
- ...($isSectionHeader && { fontWeight: 500 }),
205
- gap: $gap,
206
- flex: "0 0 auto",
207
- userSelect: "none",
208
- cursor: "default",
209
- ...($variant !== "bare" && {
210
- paddingTop: "6px",
211
- paddingRight: "12px",
212
- paddingBottom: "6px",
213
- paddingLeft: "12px",
214
- ...($variant === "padded" && {
215
- borderRadius: "2px",
216
- marginLeft: "8px",
217
- marginRight: "8px",
218
- marginTop: `${margin.top}px`,
219
- marginBottom: `${margin.bottom}px`,
220
- }),
221
- }),
222
- color: theme.colors.textMuted,
223
- ...($isSectionHeader && {
224
- backgroundColor: theme.colors.listView.raisedBackground,
225
- ...($sectionHeaderVariant === "label" && {
226
- color: theme.colors.textDisabled,
227
- }),
228
- }),
229
- ...($disabled && {
230
- color: theme.colors.textDisabled,
231
- }),
232
- ...($selected && {
233
- color: "white",
234
- backgroundColor: theme.colors[$colorScheme],
235
- }),
236
- display: "flex",
237
- alignItems: "center",
238
- ...($selected &&
239
- !$isSectionHeader &&
240
- ($selectedPosition === "middle" || $selectedPosition === "last") && {
241
- borderTopRightRadius: "0px",
242
- borderTopLeftRadius: "0px",
243
- }),
244
- ...($selected &&
245
- !$isSectionHeader &&
246
- ($selectedPosition === "middle" || $selectedPosition === "first") && {
247
- borderBottomRightRadius: "0px",
248
- borderBottomLeftRadius: "0px",
249
- }),
250
- position: "relative",
251
- ...($hovered && {
252
- boxShadow: `0 0 0 1px ${theme.colors[$colorScheme]} inset`,
253
- }),
254
- ...($showsActiveState && {
255
- "&:active": {
256
- backgroundColor: $selected
257
- ? $colorScheme === "secondary"
258
- ? theme.colors.secondaryLight
259
- : theme.colors.primaryLight
260
- : theme.colors.activeBackground,
261
- },
262
- }),
263
- ...($divider && {
264
- borderBottom: `1px solid ${theme.colors.dividerSubtle}`,
265
- }),
266
- ...($backgroundColor && {
267
- backgroundColor: $backgroundColor,
268
- "&:hover": {
269
- backgroundColor: $backgroundColor,
270
- },
271
- "&:active": {
272
- backgroundColor: $backgroundColor,
273
- },
274
- }),
275
- };
240
+ return (
241
+ <div
242
+ ref={ref}
243
+ className={`${
244
+ $isSectionHeader && $sectionHeaderVariant === "label"
245
+ ? "font-sans text-label font-medium"
246
+ : "font-sans text-heading5 font-normal"
247
+ } ${className ?? ""}`}
248
+ style={{
249
+ ...($isSectionHeader && { fontWeight: 500 }),
250
+ gap: $gap,
251
+ flex: "0 0 auto",
252
+ userSelect: "none",
253
+ cursor: "default",
254
+ ...($variant !== "bare" && {
255
+ paddingTop: "6px",
256
+ paddingRight: "12px",
257
+ paddingBottom: "6px",
258
+ paddingLeft: "12px",
259
+ ...($variant === "padded" && {
260
+ borderRadius: "2px",
261
+ marginLeft: "8px",
262
+ marginRight: "8px",
263
+ marginTop: `${margin.top}px`,
264
+ marginBottom: `${margin.bottom}px`,
265
+ }),
266
+ }),
267
+ color: theme.colors.textMuted,
268
+ ...($isSectionHeader && {
269
+ backgroundColor: theme.colors.listView.raisedBackground,
270
+ ...($sectionHeaderVariant === "label" && {
271
+ color: theme.colors.textDisabled,
272
+ }),
273
+ }),
274
+ ...($disabled && {
275
+ color: theme.colors.textDisabled,
276
+ }),
277
+ ...($selected && {
278
+ color: "white",
279
+ backgroundColor: theme.colors[$colorScheme],
280
+ }),
281
+ display: "flex",
282
+ alignItems: "center",
283
+ ...($selected &&
284
+ !$isSectionHeader &&
285
+ ($selectedPosition === "middle" ||
286
+ $selectedPosition === "last") && {
287
+ borderTopRightRadius: "0px",
288
+ borderTopLeftRadius: "0px",
289
+ }),
290
+ ...($selected &&
291
+ !$isSectionHeader &&
292
+ ($selectedPosition === "middle" ||
293
+ $selectedPosition === "first") && {
294
+ borderBottomRightRadius: "0px",
295
+ borderBottomLeftRadius: "0px",
296
+ }),
297
+ position: "relative",
298
+ ...($hovered && {
299
+ boxShadow: `0 0 0 1px ${theme.colors[$colorScheme]} inset`,
300
+ }),
301
+ ...($showsActiveState && {
302
+ "&:active": {
303
+ backgroundColor: $selected
304
+ ? $colorScheme === "secondary"
305
+ ? theme.colors.secondaryLight
306
+ : theme.colors.primaryLight
307
+ : theme.colors.activeBackground,
308
+ },
309
+ }),
310
+ ...($divider && {
311
+ borderBottom: `1px solid ${theme.colors.dividerSubtle}`,
312
+ }),
313
+ ...($backgroundColor && {
314
+ backgroundColor: $backgroundColor,
315
+ "&:hover": {
316
+ backgroundColor: $backgroundColor,
317
+ },
318
+ "&:active": {
319
+ backgroundColor: $backgroundColor,
320
+ },
321
+ }),
322
+ ...style,
323
+ }}
324
+ {...props}
325
+ />
326
+ );
276
327
  }
277
328
  );
278
329
 
279
- const ListViewDragIndicatorElement = styled.div<{
280
- $relativeDropPosition: RelativeDropPosition;
281
- $gap: number;
282
- $offsetLeft: number;
283
- $colorScheme: ListColorScheme;
284
- }>(({ theme, $relativeDropPosition, $offsetLeft, $colorScheme, $gap }) => ({
285
- zIndex: 1,
286
- position: "absolute",
287
- borderRadius: "3px",
288
- ...($relativeDropPosition === "inside"
289
- ? {
290
- inset: 2,
291
- boxShadow: `0 0 0 1px ${theme.colors.sidebar.background}, 0 0 0 3px ${
292
- $colorScheme === "secondary"
293
- ? theme.colors.secondary
294
- : theme.colors.dragOutline
295
- }`,
296
- }
297
- : {
298
- top: $relativeDropPosition === "above" ? -(3 + $gap / 2) : undefined,
299
- bottom: $relativeDropPosition === "below" ? -(3 + $gap / 2) : undefined,
300
- left: $offsetLeft,
301
- right: 0,
302
- height: 6,
303
- background: theme.colors[$colorScheme],
304
- border: `2px solid white`,
305
- boxShadow: "0 0 2px rgba(0,0,0,0.5)",
306
- }),
307
- }));
330
+ const ListViewDragIndicatorElement = forwardRef<
331
+ HTMLDivElement,
332
+ React.HTMLAttributes<HTMLDivElement> & {
333
+ $relativeDropPosition: RelativeDropPosition;
334
+ $gap: number;
335
+ $offsetLeft: number;
336
+ $colorScheme: ListColorScheme;
337
+ }
338
+ >(
339
+ (
340
+ {
341
+ className,
342
+ $relativeDropPosition,
343
+ $offsetLeft,
344
+ $colorScheme,
345
+ $gap,
346
+ style,
347
+ ...props
348
+ },
349
+ ref
350
+ ) => {
351
+ return (
352
+ <div
353
+ ref={ref}
354
+ {...props}
355
+ className={className}
356
+ style={{
357
+ zIndex: 1000,
358
+ position: "absolute",
359
+ borderRadius: "3px",
360
+ ...($relativeDropPosition === "inside"
361
+ ? {
362
+ inset: 2,
363
+ boxShadow: `0 0 0 1px var(--sidebar-background), 0 0 0 3px ${
364
+ $colorScheme === "secondary"
365
+ ? "var(--secondary)"
366
+ : "var(--drag-outline)"
367
+ }`,
368
+ }
369
+ : {
370
+ top:
371
+ $relativeDropPosition === "above"
372
+ ? -(3 + $gap / 2)
373
+ : undefined,
374
+ bottom:
375
+ $relativeDropPosition === "below"
376
+ ? -(3 + $gap / 2)
377
+ : undefined,
378
+ left: $offsetLeft,
379
+ right: 0,
380
+ height: 6,
381
+ backgroundColor:
382
+ $colorScheme === "secondary"
383
+ ? "var(--secondary)"
384
+ : "var(--primary)",
385
+ border: `2px solid white`,
386
+ boxShadow: "0 0 2px rgba(0,0,0,0.5)",
387
+ }),
388
+ ...style,
389
+ }}
390
+ />
391
+ );}
392
+ );
308
393
 
309
394
  interface ListViewClickInfo {
310
395
  shiftKey: boolean;
@@ -662,18 +747,6 @@ const VirtualizedList = memo(
662
747
  * Root
663
748
  * ------------------------------------------------------------------------- */
664
749
 
665
- const RootContainer = styled.div<{
666
- $scrollable?: boolean;
667
- $gap?: number;
668
- }>(({ theme, $scrollable, $gap }) => ({
669
- flex: $scrollable ? "1 0 0" : "0 0 auto",
670
- display: "flex",
671
- flexDirection: "column",
672
- flexWrap: "nowrap",
673
- color: theme.colors.textMuted,
674
- gap: $gap,
675
- }));
676
-
677
750
  type ListViewItemInfo = {
678
751
  isDragging: boolean;
679
752
  };
@@ -943,18 +1016,17 @@ const ListViewRootInner = forwardRef(function ListViewRootInner<T>(
943
1016
  );
944
1017
 
945
1018
  const draggingContextValue = useMemo(() => ({ indentation }), [indentation]);
1019
+ const gapStyle = useMemo(() => ({ gap: `${gap}px` }), [gap]);
946
1020
 
947
1021
  return (
948
1022
  <ListViewDraggingContext.Provider value={draggingContextValue}>
949
- <RootContainer
1023
+ <div
950
1024
  id={id}
951
- className={className}
952
- style={style}
1025
+ className={`flex flex-col text-text-muted ${scrollable ? "flex-1" : "flex-none"} ${className ?? ""}`}
1026
+ style={{ ...gapStyle, ...style }}
953
1027
  {...{
954
1028
  [pressEventName]: handleClick,
955
1029
  }}
956
- $gap={gap}
957
- $scrollable={scrollable}
958
1030
  >
959
1031
  {withScrollable((scrollElementRef: HTMLDivElement | null) =>
960
1032
  withSortable(
@@ -973,7 +1045,7 @@ const ListViewRootInner = forwardRef(function ListViewRootInner<T>(
973
1045
  )
974
1046
  )
975
1047
  )}
976
- </RootContainer>
1048
+ </div>
977
1049
  </ListViewDraggingContext.Provider>
978
1050
  );
979
1051
  });
@@ -1,42 +1,13 @@
1
1
  import * as PopoverPrimitive from "@radix-ui/react-popover";
2
2
  import React, { ComponentProps } from "react";
3
- import styled from "styled-components";
4
3
  import { IconButton } from "./IconButton";
5
4
 
6
- type PopoverVariant = "normal" | "large";
7
-
8
- const ContentElement = styled(PopoverPrimitive.Content)<{
9
- variant?: PopoverVariant;
10
- }>(({ theme, variant }) => ({
11
- borderRadius: 4,
12
- fontSize: 14,
13
- backgroundColor: theme.colors.popover.background,
14
- boxShadow: "0 2px 4px rgba(0,0,0,0.2), 0 0 12px rgba(0,0,0,0.1)",
15
- maxHeight: "600px",
16
- overflowY: "auto",
17
- color: theme.colors.textMuted,
18
- ...(variant === "large" && { width: "680px" }),
19
- ...(variant === "normal" && { width: "240px" }),
20
- zIndex: 1000,
21
- }));
22
-
23
- const ArrowElement = styled(PopoverPrimitive.Arrow)(({ theme }) => ({
24
- fill: theme.colors.popover.background,
25
- }));
26
-
27
- const PopoverClose = styled(PopoverPrimitive.Close)(({ theme }) => ({
5
+ const closeStyles: React.CSSProperties = {
28
6
  all: "unset",
29
7
  fontFamily: "inherit",
30
- borderRadius: "100%",
31
- height: 25,
32
- width: 25,
33
- display: "inline-flex",
34
- alignItems: "center",
35
- justifyContent: "center",
36
- position: "absolute",
37
- top: 5,
38
- right: 5,
39
- }));
8
+ };
9
+
10
+ type PopoverVariant = "normal" | "large";
40
11
 
41
12
  interface Props
42
13
  extends Pick<
@@ -80,8 +51,8 @@ export function Popover({
80
51
  <PopoverPrimitive.Root open={open} onOpenChange={onOpenChange}>
81
52
  <PopoverPrimitive.Trigger asChild>{trigger}</PopoverPrimitive.Trigger>
82
53
  <PopoverPrimitive.Portal>
83
- <ContentElement
84
- variant={variant}
54
+ <PopoverPrimitive.Content
55
+ className={`rounded font-[14px] bg-popover-background shadow-[0_2px_4px_rgba(0,0,0,0.2),0_0_12px_rgba(0,0,0,0.1)] max-h-[600px] overflow-y-auto text-text-muted z-[1000] ${variant === "large" ? "w-[680px]" : variant === "normal" ? "w-[240px]" : ""}`}
85
56
  side={side}
86
57
  align="center"
87
58
  sideOffset={sideOffset}
@@ -101,13 +72,18 @@ export function Popover({
101
72
  // }}
102
73
  >
103
74
  {children}
104
- {showArrow && <ArrowElement />}
75
+ {showArrow && (
76
+ <PopoverPrimitive.Arrow className="fill-popover-background" />
77
+ )}
105
78
  {closable && (
106
- <PopoverClose>
79
+ <PopoverPrimitive.Close
80
+ className="rounded-full h-[25px] w-[25px] inline-flex items-center justify-center absolute top-[5px] right-[5px]"
81
+ style={closeStyles}
82
+ >
107
83
  <IconButton iconName="Cross2Icon" onClick={onClickClose} />
108
- </PopoverClose>
84
+ </PopoverPrimitive.Close>
109
85
  )}
110
- </ContentElement>
86
+ </PopoverPrimitive.Content>
111
87
  </PopoverPrimitive.Portal>
112
88
  </PopoverPrimitive.Root>
113
89
  );
@@ -1,57 +1,34 @@
1
- import { clamp } from '@noya-app/noya-utils';
2
- import * as ProgressPrimitive from '@radix-ui/react-progress';
3
- import React, { CSSProperties } from 'react';
4
- import styled from 'styled-components';
1
+ import { clamp } from "@noya-app/noya-utils";
2
+ import * as ProgressPrimitive from "@radix-ui/react-progress";
3
+ import React, { useMemo } from "react";
4
+ import { cn } from "../utils/tailwind";
5
5
 
6
- type ProgressVariant = 'normal' | 'warning' | 'primary' | 'secondary';
6
+ type ProgressVariant = "normal" | "warning" | "primary" | "secondary";
7
7
 
8
8
  export function Progress({
9
9
  value,
10
- width,
11
- height = 5,
12
- flex,
13
- variant = 'normal',
10
+ variant = "normal",
11
+ className,
14
12
  }: {
15
13
  value: number;
16
- height?: CSSProperties['height'];
17
- width?: CSSProperties['width'];
18
- flex?: CSSProperties['flex'];
19
14
  variant?: ProgressVariant;
15
+ className?: string;
20
16
  }) {
21
17
  const clampedValue = clamp(value, 0, 100);
18
+ const transformStyles = useMemo(() => ({
19
+ transform: `translateX(-${100 - clampedValue}%)`,
20
+ }), [clampedValue]);
22
21
 
23
22
  return (
24
- <ProgressRoot value={clampedValue} style={{ width, flex, height }}>
25
- <ProgressIndicator
26
- variant={variant}
27
- style={{ transform: `translateX(-${100 - clampedValue}%)` }}
23
+ <ProgressPrimitive.Root
24
+ className={`relative hidden bg-input-background h-[5px] ${className ?? ""}`}
25
+ style={{ transform: "translateZ(0)" }}
26
+ value={clampedValue}
27
+ >
28
+ <ProgressPrimitive.Indicator
29
+ className={cn(variant === 'primary' ? "bg-primary" : variant === 'secondary' ? "bg-secondary" : variant === 'warning' ? "bg-warning" : "bg-text", "transition-[transform_660ms_cubic-bezier(0.65,0,0.35,1)", "w-full h-full")}
30
+ style={transformStyles}
28
31
  />
29
- </ProgressRoot>
32
+ </ProgressPrimitive.Root>
30
33
  );
31
- }
32
-
33
- const ProgressRoot = styled(ProgressPrimitive.Root)(({ theme }) => ({
34
- position: 'relative',
35
- overflow: 'hidden',
36
- background: theme.colors.inputBackground,
37
-
38
- // Fix overflow clipping in Safari
39
- // https://gist.github.com/domske/b66047671c780a238b51c51ffde8d3a0
40
- transform: 'translateZ(0)',
41
- }));
42
-
43
- const ProgressIndicator = styled(ProgressPrimitive.Indicator)<{
44
- variant: ProgressVariant;
45
- }>(({ theme, variant }) => ({
46
- backgroundColor:
47
- variant === 'primary'
48
- ? theme.colors.primary
49
- : variant === 'secondary'
50
- ? theme.colors.secondary
51
- : variant === 'warning'
52
- ? theme.colors.warning
53
- : theme.colors.text,
54
- width: '100%',
55
- height: '100%',
56
- transition: 'transform 660ms cubic-bezier(0.65, 0, 0.35, 1)',
57
- }));
34
+ }