@noya-app/noya-designsystem 0.1.48 → 0.1.50

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 (55) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/CHANGELOG.md +19 -0
  3. package/dist/index.css +1 -1
  4. package/dist/index.d.mts +347 -173
  5. package/dist/index.d.ts +347 -173
  6. package/dist/index.js +3602 -2811
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +4761 -3993
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +6 -5
  11. package/src/__tests__/validateDropIndicator.test.ts +4 -4
  12. package/src/components/ActionMenu.tsx +15 -4
  13. package/src/components/Avatar.tsx +2 -2
  14. package/src/components/Banner.tsx +29 -0
  15. package/src/components/BaseToolbar.tsx +2 -2
  16. package/src/components/Button.tsx +2 -2
  17. package/src/components/Checkbox.tsx +2 -2
  18. package/src/components/Chip.tsx +15 -14
  19. package/src/components/Collection.tsx +25 -2
  20. package/src/components/Combobox.tsx +22 -23
  21. package/src/components/ComboboxMenu.tsx +1 -1
  22. package/src/components/Dialog.tsx +2 -2
  23. package/src/components/DimensionInput.tsx +14 -12
  24. package/src/components/EditableText.tsx +3 -1
  25. package/src/components/FillInputField.tsx +2 -2
  26. package/src/components/Grid.tsx +131 -113
  27. package/src/components/GridView.tsx +36 -18
  28. package/src/components/InputField.tsx +116 -171
  29. package/src/components/Label.tsx +14 -73
  30. package/src/components/LabeledField.tsx +13 -2
  31. package/src/components/List.tsx +106 -47
  32. package/src/components/ListView.tsx +52 -31
  33. package/src/components/MediaThumbnail.tsx +14 -6
  34. package/src/components/Message.tsx +8 -8
  35. package/src/components/NoyaLogo.tsx +41 -0
  36. package/src/components/Popover.tsx +9 -6
  37. package/src/components/Section.tsx +172 -0
  38. package/src/components/SegmentedControl.tsx +1 -1
  39. package/src/components/SelectMenu.tsx +9 -4
  40. package/src/components/Slider.tsx +16 -7
  41. package/src/components/Sortable.tsx +186 -47
  42. package/src/components/UserPointer.tsx +1 -1
  43. package/src/components/ai-assistant/AIAssistantLayout.tsx +102 -0
  44. package/src/components/connected-users-menu/ConnectedUsersMenuLayout.tsx +71 -0
  45. package/src/components/file-explorer/FileExplorerLayout.tsx +71 -0
  46. package/src/components/internal/Menu.tsx +20 -10
  47. package/src/components/internal/SelectItem.tsx +3 -2
  48. package/src/components/pipeline/PipelineResultLayout.tsx +32 -0
  49. package/src/index.css +118 -112
  50. package/src/index.tsx +9 -0
  51. package/src/theme/index.ts +2 -0
  52. package/src/utils/classNames.ts +76 -3
  53. package/src/utils/inputs.ts +21 -0
  54. package/src/utils/moveTreeItem.ts +99 -0
  55. package/tailwind.config.ts +82 -75
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noya-app/noya-designsystem",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -22,10 +22,10 @@
22
22
  "dependencies": {
23
23
  "@dnd-kit/core": "6.3.1",
24
24
  "@dnd-kit/sortable": "10.0.0",
25
- "@noya-app/noya-colorpicker": "0.1.18",
26
- "@noya-app/noya-utils": "0.1.4",
27
- "@noya-app/noya-geometry": "0.1.8",
28
- "@noya-app/noya-icons": "0.1.6",
25
+ "@noya-app/noya-colorpicker": "0.1.19",
26
+ "@noya-app/noya-utils": "0.1.5",
27
+ "@noya-app/noya-geometry": "0.1.10",
28
+ "@noya-app/noya-icons": "0.1.7",
29
29
  "@noya-app/noya-keymap": "0.1.3",
30
30
  "@radix-ui/primitive": "^1.0.0",
31
31
  "@radix-ui/react-avatar": "^1.0.1",
@@ -50,6 +50,7 @@
50
50
  "vscode-fuzzy-scorer": "^0.0.4"
51
51
  },
52
52
  "devDependencies": {
53
+ "@tailwindcss/container-queries": "^0.1.1",
53
54
  "@types/react": "*",
54
55
  "@types/react-dom": "*",
55
56
  "@types/react-virtualized": "^9.21.21",
@@ -49,7 +49,7 @@ describe("defaultAcceptsDrop", () => {
49
49
  describe("validateDropIndicator", () => {
50
50
  const mockAcceptsDrop = (
51
51
  sourceIndex: number,
52
- destinationIndex: number,
52
+ targetIndex: number,
53
53
  position: "above" | "below" | "inside"
54
54
  ) => {
55
55
  // Mock that only allows dropping inside
@@ -59,7 +59,7 @@ describe("validateDropIndicator", () => {
59
59
 
60
60
  const mockAcceptsDropAboveBelow = (
61
61
  sourceIndex: number,
62
- destinationIndex: number,
62
+ targetIndex: number,
63
63
  position: "above" | "below" | "inside"
64
64
  ) => {
65
65
  // Mock that only allows dropping above/below
@@ -69,7 +69,7 @@ describe("validateDropIndicator", () => {
69
69
 
70
70
  const mockAcceptsAll = (
71
71
  sourceIndex: number,
72
- destinationIndex: number,
72
+ targetIndex: number,
73
73
  position: "above" | "below" | "inside"
74
74
  ) => {
75
75
  // Mock that allows all drop positions
@@ -78,7 +78,7 @@ describe("validateDropIndicator", () => {
78
78
 
79
79
  const mockAcceptsAboveAndInside = (
80
80
  sourceIndex: number,
81
- destinationIndex: number,
81
+ targetIndex: number,
82
82
  position: "above" | "below" | "inside"
83
83
  ) => {
84
84
  // Mock that allows dropping above and inside, but not below
@@ -10,19 +10,29 @@ type ActionMenuProps<TMenu extends string> = {
10
10
  onSelect: (action: TMenu) => void;
11
11
  selected: boolean;
12
12
  onOpenChange: (open: boolean) => void;
13
+ className?: string;
14
+ style?: React.CSSProperties;
13
15
  };
14
16
 
15
17
  export const ActionMenu = memoGeneric(function ActionMenu<
16
18
  TMenu extends string,
17
- >({ menuItems, onSelect, selected, onOpenChange }: ActionMenuProps<TMenu>) {
18
- const style = useMemo(() => {
19
+ >({
20
+ menuItems,
21
+ onSelect,
22
+ selected,
23
+ onOpenChange,
24
+ className,
25
+ style,
26
+ }: ActionMenuProps<TMenu>) {
27
+ const internalStyle = useMemo(() => {
19
28
  return {
20
29
  backgroundColor: selected
21
30
  ? cssVars.colors.primaryPastel
22
31
  : cssVars.colors.inputBackground,
23
32
  padding: "4px",
33
+ ...style,
24
34
  };
25
- }, [selected]);
35
+ }, [selected, style]);
26
36
 
27
37
  return (
28
38
  <DropdownMenu
@@ -31,7 +41,8 @@ export const ActionMenu = memoGeneric(function ActionMenu<
31
41
  onOpenChange={onOpenChange}
32
42
  >
33
43
  <IconButton
34
- style={style}
44
+ style={internalStyle}
45
+ className={className}
35
46
  iconName="DotsVerticalIcon"
36
47
  color={selected ? cssVars.colors.primary : undefined}
37
48
  />
@@ -181,8 +181,8 @@ const OverflowAvatar = React.memo(function OverflowAvatar({
181
181
  count: number;
182
182
  }) {
183
183
  return (
184
- <AvatarRoot size={size} backgroundColor="var(--text-disabled)" disabled>
185
- <AvatarFallback backgroundColor="var(--text-disabled)" size={size}>
184
+ <AvatarRoot size={size} backgroundColor="var(--n-text-disabled)" disabled>
185
+ <AvatarFallback backgroundColor="var(--n-text-disabled)" size={size}>
186
186
  +{count}
187
187
  </AvatarFallback>
188
188
  </AvatarRoot>
@@ -0,0 +1,29 @@
1
+ import React, { CSSProperties } from "react";
2
+ import { cssVars } from "../theme";
3
+ import { cx } from "../utils/classNames";
4
+ import { Small } from "./Text";
5
+
6
+ const bannerStyles = {
7
+ backgroundColor: cssVars.colors.inputBackground,
8
+ color: cssVars.colors.textDisabled,
9
+ };
10
+
11
+ export type BannerProps = {
12
+ label?: string;
13
+ className?: string;
14
+ style?: CSSProperties;
15
+ };
16
+
17
+ export function Banner({ label = "No items", className, style }: BannerProps) {
18
+ return (
19
+ <div
20
+ className={cx(
21
+ "flex p-1 items-center justify-center select-none rounded",
22
+ className
23
+ )}
24
+ style={{ ...bannerStyles, ...style }}
25
+ >
26
+ <Small color="textDisabled">{label}</Small>
27
+ </div>
28
+ );
29
+ }
@@ -21,7 +21,7 @@ export function BaseToolbar({
21
21
  return (
22
22
  <div className="flex flex-col">
23
23
  <div
24
- className="flex items-center pr-2.5 bg-sidebar-background flex-none relative"
24
+ className="flex items-center pr-2.5 bg-sidebar-background flex-none relative @container/toolbar"
25
25
  style={{
26
26
  flex: `0 0 ${cssVars.spacing.toolbarHeight}`,
27
27
  }}
@@ -39,7 +39,7 @@ export function BaseToolbar({
39
39
  <Spacer.Horizontal size={10} />
40
40
  </>
41
41
  )}
42
- <div className="flex items-center justify-center text-text-muted pointer-events-none lg:absolute inset-0">
42
+ <div className="flex items-center justify-center text-text-muted pointer-events-none @2xl/toolbar:absolute inset-0">
43
43
  <div
44
44
  style={{
45
45
  display: "flex",
@@ -5,8 +5,8 @@ import React, {
5
5
  ReactNode,
6
6
  useCallback,
7
7
  } from "react";
8
- import { Tooltip } from "./Tooltip";
9
8
  import { cx } from "../utils/classNames";
9
+ import { Tooltip } from "./Tooltip";
10
10
 
11
11
  type ButtonVariant =
12
12
  | "normal"
@@ -87,7 +87,7 @@ export const Button = forwardRef(function Button(
87
87
  ref={forwardedRef}
88
88
  id={id}
89
89
  className={cx(
90
- "no-underline leading-[1] relative border-0 outline-none select-none text-left rounded flex items-center justify-center [&>*]:pointer-events-none [-webkit-app-region:no-drag] focus:ring-2 focus:ring-primary focus:shadow-[0_0_0_1px_var(--popover-background)_inset] transition-all",
90
+ "no-underline leading-[1] relative border-0 outline-none select-none text-left rounded flex items-center justify-center [&>*]:pointer-events-none [-webkit-app-region:no-drag] focus:ring-2 focus:ring-primary focus:shadow-[0_0_0_1px_var(--n-popover-background)_inset] transition-all",
91
91
  disabled ? "opacity-25" : "",
92
92
  !className?.includes("flex") ? "flex-none" : "",
93
93
  active
@@ -58,8 +58,8 @@ export const Checkbox = React.memo(
58
58
  className={`
59
59
  absolute
60
60
  inset-0
61
- h-[27px]
62
- w-[27px]
61
+ h-input-height
62
+ w-input-height
63
63
  pointer-events-none
64
64
  stroke-white
65
65
  opacity-0
@@ -19,32 +19,32 @@ const SIZE_STYLES = {
19
19
  } as const;
20
20
 
21
21
  const SHADOW_STYLES = {
22
- primary: "shadow-[0_0_0_1px_var(--chip-primary-shadow)_inset]",
23
- secondary: "shadow-[0_0_0_1px_var(--chip-secondary-shadow)_inset]",
24
- error: "shadow-[0_0_0_1px_var(--chip-error-shadow)_inset]",
25
- default: "shadow-[0_0_0_1px_var(--chip-default-shadow)_inset]",
22
+ primary: "shadow-[0_0_0_1px_var(--n-chip-primary-shadow)_inset]",
23
+ secondary: "shadow-[0_0_0_1px_var(--n-chip-secondary-shadow)_inset]",
24
+ error: "shadow-[0_0_0_1px_var(--n-chip-error-shadow)_inset]",
25
+ default: "shadow-[0_0_0_1px_var(--n-chip-default-shadow)_inset]",
26
26
  } as const;
27
27
 
28
28
  const COLOR_STYLES = {
29
29
  primary: {
30
30
  text: "text-primary",
31
31
  bg: "bg-primary-pastel",
32
- subtle: "bg-[var(--chip-primary-bg)]",
32
+ subtle: "bg-[var(--n-chip-primary-bg)]",
33
33
  },
34
34
  secondary: {
35
35
  text: "text-secondary",
36
36
  bg: "bg-secondary-pastel",
37
- subtle: "bg-[var(--chip-secondary-bg)]",
37
+ subtle: "bg-[var(--n-chip-secondary-bg)]",
38
38
  },
39
39
  error: {
40
40
  text: "text-text",
41
41
  bg: "bg-[rgb(255,219,219)]",
42
- subtle: "bg-[var(--chip-error-bg)]",
42
+ subtle: "bg-[var(--n-chip-error-bg)]",
43
43
  },
44
44
  default: {
45
45
  text: "text-text",
46
46
  bg: "bg-input-background",
47
- subtle: "bg-[var(--chip-default-bg)]",
47
+ subtle: "bg-[var(--n-chip-default-bg)]",
48
48
  },
49
49
  } as const;
50
50
 
@@ -52,16 +52,16 @@ const ICON_BASE_STYLES = "relative opacity-50 cursor-pointer hover:opacity-85";
52
52
 
53
53
  const ICON_SIZE_STYLES = {
54
54
  large: {
55
- add: "ml-[-2px] mr-[2px] -top-[1px] scale-75",
56
- delete: "mr-[-2px] ml-[2px] scale-75",
55
+ add: "ml-[-2px] mr-[2px] -top-[1px] scale-[0.75]",
56
+ delete: "mr-[-2px] ml-[2px] scale-[0.75]",
57
57
  },
58
58
  medium: {
59
- add: "ml-[-2px] mr-[-2px] scale-60",
60
- delete: "mr-[-2px] scale-60",
59
+ add: "ml-[-2px] mr-[-2px] scale-[0.60]",
60
+ delete: "mr-[-2px] scale-[0.60]",
61
61
  },
62
62
  small: {
63
- add: "ml-[-2px] mr-[-2px] scale-60",
64
- delete: "mr-[-2px] scale-60",
63
+ add: "ml-[-2px] mr-[-2px] scale-[0.60]",
64
+ delete: "mr-[-2px] scale-[0.60]",
65
65
  },
66
66
  } as const;
67
67
 
@@ -82,6 +82,7 @@ export interface ChipProps {
82
82
  onHoverDeleteChange?: (hovering: boolean) => void;
83
83
  style?: React.CSSProperties;
84
84
  tabIndex?: number;
85
+ role?: string;
85
86
  }
86
87
 
87
88
  export const Chip = memo(
@@ -2,11 +2,17 @@ import React from "react";
2
2
  import { forwardRefGeneric } from "../../../noya-react-utils/src/utils/reactGenerics";
3
3
  import { Grid, GridViewSize } from "../components/Grid";
4
4
  import { MenuItem } from "../components/internal/Menu";
5
- import { ListView, ListViewRootProps } from "../components/ListView";
5
+ import {
6
+ ListView,
7
+ ListViewRootProps,
8
+ ListViewRowProps,
9
+ } from "../components/ListView";
6
10
  import { List } from "./List";
7
11
 
8
12
  export type CollectionViewType = "grid" | "list";
9
13
 
14
+ export type CollectionThumbnailSize = "auto" | "custom";
15
+
10
16
  export type CollectionRef = {
11
17
  editName: (id: string) => void;
12
18
  };
@@ -16,12 +22,19 @@ export type CollectionThumbnailProps<T> = {
16
22
  selected: boolean;
17
23
  };
18
24
 
25
+ export type CollectionRenderActionProps<T> = {
26
+ item: T;
27
+ selected: boolean;
28
+ onOpenChange: (open: boolean) => void;
29
+ };
30
+
19
31
  export interface CollectionProps<T, M extends string = string> {
20
32
  className?: string;
21
33
  items: T[];
22
34
  getId: (item: T) => string;
23
35
  getName: (item: T) => string;
24
36
  getExpanded?: (item: T) => boolean | undefined;
37
+ getPlaceholder?: (item: T) => string;
25
38
  /**
26
39
  * Whether directories should be expandable.
27
40
  * @default true
@@ -39,7 +52,9 @@ export interface CollectionProps<T, M extends string = string> {
39
52
  item,
40
53
  selected,
41
54
  }: CollectionThumbnailProps<T>) => React.ReactNode;
42
- renderAction?: "menu" | ((item: T, selected: boolean) => React.ReactNode);
55
+ renderAction?:
56
+ | "menu"
57
+ | ((props: CollectionRenderActionProps<T>) => React.ReactNode);
43
58
  renderDetail?: (item: T, selected: boolean) => React.ReactNode;
44
59
  /** Callback when selection changes. If not provided, selection will be disabled. */
45
60
  onSelectionChange?: (
@@ -52,13 +67,18 @@ export interface CollectionProps<T, M extends string = string> {
52
67
  detailPosition?: "end" | "below";
53
68
  /** Size of the list items. Defaults to 'medium'. */
54
69
  size?: GridViewSize;
70
+ /** Size of the thumbnail. Defaults to 'auto', which will be based on the size prop. */
71
+ thumbnailSize?: CollectionThumbnailSize;
55
72
  /** For testing: Override the hover state with a specific item ID */
56
73
  testHoveredId?: string;
57
74
  /** For testing: Override the renaming state with a specific item ID */
58
75
  testRenamingId?: string;
76
+ /** For testing: Override the drop indicator state with a specific item ID */
77
+ testShowDropIndicatorId?: string;
59
78
  setExpanded?: (item: T, expanded: boolean) => void;
60
79
  acceptsDrop?: ListViewRootProps["acceptsDrop"];
61
80
  onMoveItem?: ListViewRootProps["onMoveItem"];
81
+ getDropTargetParentIndex?: ListViewRootProps["getDropTargetParentIndex"];
62
82
  getDepth?: (item: T) => number;
63
83
  onFilesDrop?: (event: React.DragEvent<Element>) => void;
64
84
  getRenamable?: (item: T) => boolean;
@@ -68,6 +88,9 @@ export interface CollectionProps<T, M extends string = string> {
68
88
  onClickItem?: (itemId: string) => void;
69
89
  onDoubleClickItem?: (itemId: string) => void;
70
90
  renderEmptyState?: () => React.ReactElement;
91
+ /** @default false */
92
+ sortable?: boolean;
93
+ dragIndicatorStyle?: ListViewRowProps<M>["dragIndicatorStyle"];
71
94
  }
72
95
 
73
96
  export const Collection = forwardRefGeneric(function Collection<
@@ -27,10 +27,6 @@ import {
27
27
  import { ListView } from "./ListView";
28
28
  import { Small } from "./Text";
29
29
 
30
- const comboboxButtonStyle = {
31
- right: "2px",
32
- };
33
-
34
30
  export type BaseComboboxProps<T extends string> = {
35
31
  id?: string;
36
32
  loading?: boolean;
@@ -454,6 +450,28 @@ export const Combobox = memoGeneric(
454
450
  id={id}
455
451
  size={size}
456
452
  sideOffset={6}
453
+ end={
454
+ <>
455
+ {loading && (
456
+ <div className="pr-1.5">
457
+ <ActivityIndicator />
458
+ </div>
459
+ )}
460
+ {!readOnly && (
461
+ <InputField.Button
462
+ variant="floating"
463
+ onClick={handleChevronClick}
464
+ >
465
+ <DropdownChevronIcon
466
+ className={cx(
467
+ "transition-transform duration-100",
468
+ shouldShowMenu ? "rotate-180" : "rotate-0"
469
+ )}
470
+ />
471
+ </InputField.Button>
472
+ )}
473
+ </>
474
+ }
457
475
  renderPopoverContent={({ width }) => {
458
476
  const height = Math.min(
459
477
  ListView.calculateHeight({
@@ -528,25 +546,6 @@ export const Combobox = memoGeneric(
528
546
  />
529
547
  )}
530
548
  {children}
531
- {loading && (
532
- <InputField.Label htmlFor={id}>
533
- <ActivityIndicator />
534
- </InputField.Label>
535
- )}
536
- {!readOnly && (
537
- <InputField.Button
538
- variant="floating"
539
- onClick={handleChevronClick}
540
- style={comboboxButtonStyle}
541
- >
542
- <DropdownChevronIcon
543
- className={cx(
544
- "transition-transform duration-100",
545
- shouldShowMenu ? "rotate-180" : "rotate-0"
546
- )}
547
- />
548
- </InputField.Button>
549
- )}
550
549
  </InputField.Root>
551
550
  );
552
551
  })
@@ -92,7 +92,7 @@ export const ComboboxMenu = memoGeneric(
92
92
  <div className="flex flex-1 min-w-0 items-center">
93
93
  {indented && <Spacer.Horizontal size={CHECKBOX_INDENT_WIDTH} />}
94
94
  {item.checked ? (
95
- <div className={styles.itemIndicatorStyle}>
95
+ <div {...styles.itemIndicator}>
96
96
  <CheckIcon />
97
97
  </div>
98
98
  ) : indented ? (
@@ -138,8 +138,8 @@ export const Dialog = forwardRef(function Dialog(
138
138
  className="z-[1]"
139
139
  style={{
140
140
  position: "absolute",
141
- top: "var(--dialog-padding)",
142
- right: "var(--dialog-padding)",
141
+ top: "var(--n-dialog-padding)",
142
+ right: "var(--n-dialog-padding)",
143
143
  }}
144
144
  />
145
145
  </DialogPrimitive.Close>
@@ -1,6 +1,7 @@
1
1
  import { round } from "@noya-app/noya-utils";
2
2
  import * as React from "react";
3
3
  import { InputField } from "./InputField";
4
+ import { LabeledField } from "./LabeledField";
4
5
 
5
6
  export type SetNumberMode = "replace" | "adjust";
6
7
 
@@ -50,17 +51,18 @@ export const DimensionInput = React.memo(function DimensionInput({
50
51
  );
51
52
 
52
53
  return (
53
- <InputField.Root id={id} width={size}>
54
- <InputField.NumberInput
55
- value={value === undefined ? value : round(value, 2)}
56
- placeholder={value === undefined ? placeholder : undefined}
57
- onNudge={handleNudgeValue}
58
- disabled={disabled}
59
- {...(trigger === "change"
60
- ? { onChange: handleSetValue }
61
- : { onSubmit: handleSetValue })}
62
- />
63
- {label && <InputField.Label>{label}</InputField.Label>}
64
- </InputField.Root>
54
+ <LabeledField label={label} labelPosition="inset">
55
+ <InputField.Root id={id} width={size}>
56
+ <InputField.NumberInput
57
+ value={value === undefined ? value : round(value, 2)}
58
+ placeholder={value === undefined ? placeholder : undefined}
59
+ onNudge={handleNudgeValue}
60
+ disabled={disabled}
61
+ {...(trigger === "change"
62
+ ? { onChange: handleSetValue }
63
+ : { onSubmit: handleSetValue })}
64
+ />
65
+ </InputField.Root>
66
+ </LabeledField>
65
67
  );
66
68
  });
@@ -35,6 +35,7 @@ type Props = {
35
35
  textClassName?: string;
36
36
  readOnly?: boolean;
37
37
  onBlur?: () => void;
38
+ tabIndex?: number;
38
39
  /**
39
40
  * If true, will render an unfocused input. This should only be used for visual regression tests.
40
41
  */
@@ -66,6 +67,7 @@ export const EditableText = memo(
66
67
  readOnly,
67
68
  onBlur,
68
69
  testFocused = false,
70
+ tabIndex = 0,
69
71
  ...props
70
72
  }: Props,
71
73
  ref: React.ForwardedRef<EditableTextRef>
@@ -136,7 +138,7 @@ export const EditableText = memo(
136
138
  children: displayValue,
137
139
  onClick: () => setFocused(true),
138
140
  ref: previewRef,
139
- tabIndex: 0,
141
+ tabIndex,
140
142
  onKeyDown: (e: React.KeyboardEvent) => {
141
143
  if (e.key === "Enter" || e.key === " ") {
142
144
  setFocused(true);
@@ -1,8 +1,8 @@
1
1
  import { Sketch } from "@noya-app/noya-file-format";
2
2
  import React, { forwardRef, memo } from "react";
3
+ import { cx } from "../utils/classNames";
3
4
  import { SketchPattern } from "../utils/sketchPattern";
4
5
  import { FillPreviewBackground } from "./FillPreviewBackground";
5
- import { cx } from "../utils/classNames";
6
6
 
7
7
  const FillButton = forwardRef<
8
8
  HTMLButtonElement,
@@ -11,7 +11,7 @@ const FillButton = forwardRef<
11
11
  <button
12
12
  ref={ref}
13
13
  className={cx(
14
- `outline-none p-0 w-[50px] h-[27px] rounded overflow-hidden border-none shadow-[0_0_0_1px_var(--divider)_inset] bg-transparent relative focus:shadow-[0_0_0_1px_var(--sidebar-background),0_0_0_3px_var(--primary)] `,
14
+ `outline-none p-0 w-[50px] h-input-height rounded overflow-hidden border-none shadow-[0_0_0_1px_var(--n-divider)_inset] bg-transparent relative focus:shadow-[0_0_0_1px_var(--n-sidebar-background),0_0_0_3px_var(--n-primary)] `,
15
15
  className
16
16
  )}
17
17
  {...props}