@12-apps/ui 1.22.0 → 2.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 (88) hide show
  1. package/package.json +3 -1
  2. package/src/components/data-display/Alert/Alert.types.ts +2 -1
  3. package/src/components/data-display/Avatar/Avatar.types.ts +10 -2
  4. package/src/components/data-display/Badge/Badge.types.ts +3 -2
  5. package/src/components/data-display/Carousel/Carousel.parts.tsx +12 -10
  6. package/src/components/data-display/Carousel/Carousel.styles.ts +4 -3
  7. package/src/components/data-display/Carousel/Carousel.tsx +2 -1
  8. package/src/components/data-display/Carousel/Carousel.types.ts +7 -6
  9. package/src/components/data-display/Chart/Chart.tsx +2 -1
  10. package/src/components/data-display/Chart/Chart.types.ts +3 -2
  11. package/src/components/data-display/Chart/ChartSpec.types.ts +6 -7
  12. package/src/components/data-display/Chart/SpecChart.tsx +2 -1
  13. package/src/components/data-display/Chart/chart-internals.ts +3 -2
  14. package/src/components/data-display/Chart/chart-spec.ts +11 -1
  15. package/src/components/data-display/Chip/Chip.tsx +23 -3
  16. package/src/components/data-display/Chip/Chip.types.ts +37 -3
  17. package/src/components/data-display/Chip/chip.md +7 -3
  18. package/src/components/data-display/Chip/index.ts +1 -1
  19. package/src/components/data-display/DataViews/DataViewsGrid.tsx +10 -0
  20. package/src/components/data-display/DataViews/DataViewsTableBase.tsx +3 -0
  21. package/src/components/data-display/DataViews/RESPONSIVE-BEHAVIOUR.md +37 -3
  22. package/src/components/data-display/DataViews/data-views-day-input.tsx +22 -3
  23. package/src/components/data-display/DataViews/data-views-display-panel.tsx +4 -2
  24. package/src/components/data-display/DataViews/data-views-grid-bodies.tsx +113 -62
  25. package/src/components/data-display/DataViews/data-views-grid-parts.tsx +17 -1
  26. package/src/components/data-display/DataViews/data-views-more-fields.tsx +16 -23
  27. package/src/components/data-display/DataViews/data-views-more-filters.tsx +7 -2
  28. package/src/components/data-display/DataViews/data-views-number-input.tsx +14 -4
  29. package/src/components/data-display/DataViews/data-views-overflow-costs.ts +87 -16
  30. package/src/components/data-display/DataViews/data-views-overflow.ts +104 -71
  31. package/src/components/data-display/DataViews/index.ts +4 -0
  32. package/src/components/data-display/DataViews/list-card-rails.tsx +29 -0
  33. package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.tsx +8 -5
  34. package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.types.ts +2 -1
  35. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.types.ts +2 -1
  36. package/src/components/data-display/LoadingState/LoadingState.types.ts +2 -1
  37. package/src/components/data-display/Progress/Progress.types.ts +3 -2
  38. package/src/components/data-display/Sheet/Sheet.body.tsx +2 -1
  39. package/src/components/data-display/Sheet/Sheet.styles.ts +3 -2
  40. package/src/components/data-display/Sheet/Sheet.types.ts +7 -2
  41. package/src/components/data-display/Stepper/Stepper.types.ts +2 -1
  42. package/src/components/data-display/Table/Table.styles.ts +1 -1
  43. package/src/components/data-display/Table/Table.types.ts +3 -1
  44. package/src/components/data-display/Tooltip/Tooltip.types.ts +2 -1
  45. package/src/components/feedback/Dialog/Dialog.types.ts +2 -1
  46. package/src/components/feedback/Modal/Modal.types.ts +2 -1
  47. package/src/components/form/Button/Button.types.ts +3 -2
  48. package/src/components/form/Command/Command.styles.ts +8 -7
  49. package/src/components/form/Command/Command.types.ts +3 -2
  50. package/src/components/form/CreatableSelect/CreatableSelect.types.ts +2 -1
  51. package/src/components/form/Input/Input.types.ts +2 -1
  52. package/src/components/form/InputOTP/InputOTP.types.ts +3 -2
  53. package/src/components/form/Label/Label.styles.ts +8 -5
  54. package/src/components/form/Label/Label.tsx +1 -1
  55. package/src/components/form/Label/Label.types.ts +3 -2
  56. package/src/components/form/Menubar/Menubar.styles.ts +10 -8
  57. package/src/components/form/Menubar/Menubar.tsx +2 -1
  58. package/src/components/form/Menubar/Menubar.types.ts +7 -6
  59. package/src/components/form/RadioGroup/RadioGroup.types.ts +3 -2
  60. package/src/components/form/Select/Select.tsx +13 -1
  61. package/src/components/form/Select/Select.types.ts +5 -2
  62. package/src/components/form/Slider/Slider.types.ts +3 -2
  63. package/src/components/form/Switch/Switch.types.ts +3 -2
  64. package/src/components/form/Textarea/Textarea.types.ts +3 -2
  65. package/src/components/form/Toggle/Toggle.types.ts +3 -2
  66. package/src/components/form/ToggleGroup/ToggleGroup.types.ts +3 -2
  67. package/src/components/layout/Separator/Separator.types.ts +2 -1
  68. package/src/components/layout/Spacer/Spacer.types.ts +2 -1
  69. package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +1 -1
  70. package/src/components/navigation/Breadcrumbs/Breadcrumbs.types.ts +7 -2
  71. package/src/components/navigation/ContextMenu/ContextMenu.types.ts +3 -2
  72. package/src/components/navigation/DropdownMenu/DropdownMenu.tsx +1 -0
  73. package/src/components/navigation/DropdownMenu/DropdownMenu.types.ts +12 -2
  74. package/src/components/navigation/NavigationMenu/NavigationMenu.types.ts +7 -2
  75. package/src/components/navigation/Pagination/Pagination.tsx +3 -1
  76. package/src/components/navigation/Pagination/Pagination.types.ts +5 -3
  77. package/src/components/navigation/Tabs/Tabs.types.ts +3 -2
  78. package/src/components/typography/Blockquote/Blockquote.types.ts +2 -1
  79. package/src/components/typography/Code/Code.types.ts +2 -1
  80. package/src/components/typography/Heading/Heading.types.ts +2 -1
  81. package/src/components/typography/Paragraph/Paragraph.types.ts +3 -2
  82. package/src/components/typography/Text/Text.types.ts +3 -2
  83. package/src/components/utility/AnimatedIcon/AnimatedIcon.types.ts +2 -1
  84. package/src/components/utility/Overflow/index.ts +6 -0
  85. package/src/components/utility/Overflow/overflow.ts +125 -0
  86. package/src/components/utility/WorkflowStep/WorkflowStep.types.ts +3 -2
  87. package/src/components/utility/index.ts +1 -0
  88. package/src/tokens/scales.ts +153 -0
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
 
2
3
  export interface InputOTPProps {
3
4
  /**
@@ -8,12 +9,12 @@ export interface InputOTPProps {
8
9
  /**
9
10
  * The color theme of the OTP input
10
11
  */
11
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral';
12
+ color?: Exclude<ColorValue, 'info'>;
12
13
 
13
14
  /**
14
15
  * The size of the OTP input
15
16
  */
16
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
17
+ size?: SizeValue;
17
18
 
18
19
  /**
19
20
  * Number of OTP digits
@@ -2,6 +2,7 @@ import { alpha } from '@mui/material';
2
2
  import type { CSSObject, Theme } from '@mui/material';
3
3
 
4
4
  import type { LabelProps } from './Label.types';
5
+ import { accentFor} from '../../../tokens/scales';
5
6
 
6
7
  type Size = NonNullable<LabelProps['size']>;
7
8
  type Variant = NonNullable<LabelProps['variant']>;
@@ -53,8 +54,8 @@ export interface LabelStyleFlags {
53
54
  export const textColor = (theme: Theme, flags: LabelStyleFlags): string => {
54
55
  if (flags.error) return theme.palette.error.main;
55
56
  if (flags.disabled) return theme.palette.text.disabled;
56
- if (flags.color === 'default') return theme.palette.text.primary;
57
- return theme.palette[flags.color].main;
57
+ if (flags.color === 'neutral') return theme.palette.text.primary;
58
+ return accentFor(theme, flags.color).main;
58
59
  };
59
60
 
60
61
  /** The ripple that expands from the centre on press, for clickable labels. */
@@ -119,7 +120,9 @@ const SURFACES: Record<Variant, (input: SurfaceInput) => CSSObject> = {
119
120
  }),
120
121
 
121
122
  gradient: ({ theme, flags }) => {
122
- const key = flags.color === 'default' ? 'primary' : flags.color;
123
+ // `neutral` has no accent of its own in the gradient; it borrows primary,
124
+ // which is what this branch already did before the vocabulary was named.
125
+ const accent = accentFor(theme, flags.color === 'neutral' ? 'primary' : flags.color);
123
126
  // The gradient paints the glyphs themselves rather than the box behind them.
124
127
  const clip = {
125
128
  WebkitBackgroundClip: 'text',
@@ -128,11 +131,11 @@ const SURFACES: Record<Variant, (input: SurfaceInput) => CSSObject> = {
128
131
  };
129
132
 
130
133
  return {
131
- background: `linear-gradient(135deg, ${theme.palette[key].light}, ${theme.palette[key].main})`,
134
+ background: `linear-gradient(135deg, ${accent.light}, ${accent.main})`,
132
135
  ...clip,
133
136
  '&:hover': flags.clickable
134
137
  ? {
135
- background: `linear-gradient(135deg, ${theme.palette[key].main}, ${theme.palette[key].dark})`,
138
+ background: `linear-gradient(135deg, ${accent.main}, ${accent.dark})`,
136
139
  ...clip,
137
140
  }
138
141
  : {},
@@ -14,7 +14,7 @@ const DEFAULTS = {
14
14
  error: false,
15
15
  variant: 'default',
16
16
  size: 'md',
17
- color: 'default',
17
+ color: 'neutral',
18
18
  glow: false,
19
19
  pulse: false,
20
20
  ripple: false,
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { CSSProperties, HTMLAttributes,ReactNode } from 'react';
2
3
 
3
4
  export interface LabelProps extends HTMLAttributes<globalThis.HTMLLabelElement> {
@@ -7,8 +8,8 @@ export interface LabelProps extends HTMLAttributes<globalThis.HTMLLabelElement>
7
8
  disabled?: boolean;
8
9
  error?: boolean;
9
10
  variant?: 'default' | 'filled' | 'outlined' | 'glass' | 'gradient' | 'minimal';
10
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
11
- color?: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' | 'default';
11
+ size?: SizeValue;
12
+ color?: ColorValue;
12
13
  glow?: boolean;
13
14
  pulse?: boolean;
14
15
  glass?: boolean;
@@ -2,6 +2,7 @@ import { alpha } from '@mui/material';
2
2
  import type { CSSObject, Theme } from '@mui/material';
3
3
 
4
4
  import type { MenubarProps } from './Menubar.types';
5
+ import { accentFor} from '../../../tokens/scales';
5
6
 
6
7
  type Size = NonNullable<MenubarProps['size']>;
7
8
  type Variant = NonNullable<MenubarProps['variant']>;
@@ -20,13 +21,13 @@ export const sizeStyles = (theme: Theme, size: Size): CSSObject =>
20
21
 
21
22
  /** `default` is not a palette entry — it means the paper surface and its text. */
22
23
  const accentOf = (theme: Theme, color: Color) =>
23
- color === 'default' ? theme.palette.primary.main : theme.palette[color].main;
24
+ color === 'neutral' ? theme.palette.primary.main : accentFor(theme, color).main;
24
25
 
25
26
  const colorStyles = (theme: Theme, color: Color, transparent: boolean): CSSObject => {
26
27
  const surface =
27
- color === 'default'
28
+ color === 'neutral'
28
29
  ? { backgroundColor: theme.palette.background.paper, color: theme.palette.text.primary }
29
- : { backgroundColor: theme.palette[color].main, color: theme.palette[color].contrastText };
30
+ : { backgroundColor: accentFor(theme, color).main, color: accentFor(theme, color).contrastText };
30
31
 
31
32
  return transparent ? { ...surface, backgroundColor: 'transparent' } : surface;
32
33
  };
@@ -57,12 +58,13 @@ const SURFACES: Record<Variant, (theme: Theme, flags: MenubarStyleFlags) => CSSO
57
58
  }),
58
59
 
59
60
  gradient: (theme, { color, gradient }) => {
60
- const key = color === 'default' ? 'primary' : color;
61
+ // `neutral` borrows primary for the gradient, as this branch always did.
62
+ const accent = accentFor(theme, color === 'neutral' ? 'primary' : color);
61
63
  return {
62
64
  background: gradient
63
- ? `linear-gradient(135deg, ${theme.palette[key].light}, ${theme.palette[key].dark})`
64
- : theme.palette[key].main,
65
- color: theme.palette[key].contrastText,
65
+ ? `linear-gradient(135deg, ${accent.light}, ${accent.dark})`
66
+ : accent.main,
67
+ color: accent.contrastText,
66
68
  };
67
69
  },
68
70
 
@@ -80,7 +82,7 @@ const SURFACES: Record<Variant, (theme: Theme, flags: MenubarStyleFlags) => CSSO
80
82
  bordered: (theme, { blur, color }) => ({
81
83
  ...(blur && { backdropFilter: 'blur(10px)' }),
82
84
  borderBottom: `2px solid ${
83
- color === 'default' ? theme.palette.divider : theme.palette[color].main
85
+ color === 'neutral' ? theme.palette.divider : accentFor(theme, color).main
84
86
  }`,
85
87
  }),
86
88
 
@@ -18,6 +18,7 @@ import { withDefaults } from '../../../utils/withDefaults';
18
18
  import { useMenubarMenus } from './Menubar.hooks';
19
19
  import { barStyles } from './Menubar.styles';
20
20
  import { MenubarToolbar } from './Menubar.toolbar';
21
+
21
22
  import type {
22
23
  MenubarGroupProps,
23
24
  MenubarItem,
@@ -27,7 +28,7 @@ import type {
27
28
  const DEFAULTS = {
28
29
  variant: 'default',
29
30
  size: 'md',
30
- color: 'default',
31
+ color: 'neutral',
31
32
  orientation: 'horizontal',
32
33
  glow: false,
33
34
  pulse: false,
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { CSSProperties,ReactNode } from 'react';
2
3
 
3
4
  export interface MenubarItem {
@@ -14,8 +15,8 @@ export interface MenubarItem {
14
15
  export interface MenubarProps {
15
16
  items: MenubarItem[];
16
17
  variant?: 'default' | 'glass' | 'gradient' | 'elevated' | 'minimal' | 'bordered';
17
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
18
- color?: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' | 'default';
18
+ size?: SizeValue;
19
+ color?: ColorValue;
19
20
  orientation?: 'horizontal' | 'vertical';
20
21
  glow?: boolean;
21
22
  pulse?: boolean;
@@ -47,8 +48,8 @@ export interface MenubarGroupProps {
47
48
  open?: boolean;
48
49
  onOpenChange?: (open: boolean) => void;
49
50
  onClick?: (item: MenubarItem) => void;
50
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
51
- color?: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' | 'default';
51
+ size?: SizeValue;
52
+ color?: ColorValue;
52
53
  className?: string;
53
54
  style?: CSSProperties;
54
55
  }
@@ -56,8 +57,8 @@ export interface MenubarGroupProps {
56
57
  export interface MenubarItemProps extends MenubarItem {
57
58
  selected?: boolean;
58
59
  onClick?: () => void;
59
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
60
- color?: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' | 'default';
60
+ size?: SizeValue;
61
+ color?: ColorValue;
61
62
  showShortcut?: boolean;
62
63
  ripple?: boolean;
63
64
  className?: string;
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { RadioGroupProps as MuiRadioGroupProps } from '@mui/material';
2
3
  import type React from 'react';
3
4
 
@@ -18,12 +19,12 @@ export interface RadioGroupProps extends Omit<MuiRadioGroupProps, 'color'> {
18
19
  /**
19
20
  * The color theme of the radio group
20
21
  */
21
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral';
22
+ color?: Exclude<ColorValue, 'info'>;
22
23
 
23
24
  /**
24
25
  * The size of the radio group
25
26
  */
26
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
27
+ size?: SizeValue;
27
28
 
28
29
  /**
29
30
  * Array of radio options
@@ -172,6 +172,18 @@ function renderMenuItems(
172
172
  return items;
173
173
  }
174
174
 
175
+ /**
176
+ * The house scale as a FormControl size.
177
+ *
178
+ * Not `muiSize`: that collapses five onto MUI's three, and a FormControl takes
179
+ * only two. This component's scale is already narrowed to `sm | md`, so the map
180
+ * is exact rather than lossy.
181
+ */
182
+ const formControlSize = (size: SelectProps['size']): 'small' | 'medium' | undefined => {
183
+ if (size === undefined) return undefined;
184
+ return size === 'sm' ? 'small' : 'medium';
185
+ };
186
+
175
187
  export const Select = React.forwardRef<HTMLDivElement, SelectProps>(
176
188
  (
177
189
  {
@@ -202,7 +214,7 @@ export const Select = React.forwardRef<HTMLDivElement, SelectProps>(
202
214
  return (
203
215
  <StyledFormControl
204
216
  fullWidth={fullWidth}
205
- size={size}
217
+ size={formControlSize(size)}
206
218
  error={error}
207
219
  customVariant={variant}
208
220
  glow={glow}
@@ -1,3 +1,4 @@
1
+ import type { SizeValue } from '../../../tokens/scales';
1
2
  import type { SelectProps as MuiSelectProps } from '@mui/material';
2
3
 
3
4
  export type SelectVariant = 'default' | 'glass' | 'gradient';
@@ -8,7 +9,9 @@ export interface SelectOption {
8
9
  disabled?: boolean;
9
10
  }
10
11
 
11
- export interface SelectProps extends Omit<MuiSelectProps, 'variant'> {
12
+ // `size` is omitted alongside `variant`: MUI declares it in its own words
13
+ // (`small | medium`), and this component speaks the house scale.
14
+ export interface SelectProps extends Omit<MuiSelectProps, 'variant' | 'size'> {
12
15
  /**
13
16
  * Visual variant of the select component
14
17
  * @default 'default'
@@ -35,7 +38,7 @@ export interface SelectProps extends Omit<MuiSelectProps, 'variant'> {
35
38
  * Size of the select component
36
39
  * @default 'medium'
37
40
  */
38
- size?: 'small' | 'medium';
41
+ size?: Extract<SizeValue, 'sm' | 'md'>;
39
42
  /**
40
43
  * Placeholder text when no option is selected
41
44
  */
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { SliderProps as MuiSliderProps } from '@mui/material';
2
3
 
3
4
  export interface SliderProps extends Omit<MuiSliderProps, 'color' | 'size'> {
@@ -9,12 +10,12 @@ export interface SliderProps extends Omit<MuiSliderProps, 'color' | 'size'> {
9
10
  /**
10
11
  * The color theme of the slider
11
12
  */
12
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral';
13
+ color?: Exclude<ColorValue, 'info'>;
13
14
 
14
15
  /**
15
16
  * The size of the slider
16
17
  */
17
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
18
+ size?: SizeValue;
18
19
 
19
20
  /**
20
21
  * Label for the slider
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { SwitchProps as MuiSwitchProps } from '@mui/material';
2
3
  import type { FocusEventHandler,MouseEventHandler, ReactNode } from 'react';
3
4
 
@@ -10,12 +11,12 @@ export interface SwitchProps extends Omit<MuiSwitchProps, 'color' | 'size'> {
10
11
  /**
11
12
  * The color theme of the switch
12
13
  */
13
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral';
14
+ color?: Exclude<ColorValue, 'info'>;
14
15
 
15
16
  /**
16
17
  * The size of the switch
17
18
  */
18
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
19
+ size?: SizeValue;
19
20
 
20
21
  /**
21
22
  * Label text for the switch
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { TextareaAutosizeProps } from '@mui/material';
2
3
  import type React from 'react';
3
4
 
@@ -10,12 +11,12 @@ export interface TextareaProps extends Omit<TextareaAutosizeProps, 'variant' | '
10
11
  /**
11
12
  * The color theme of the textarea
12
13
  */
13
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral';
14
+ color?: Exclude<ColorValue, 'info'>;
14
15
 
15
16
  /**
16
17
  * The size of the textarea
17
18
  */
18
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
19
+ size?: SizeValue;
19
20
 
20
21
  /**
21
22
  * Whether the textarea has an error
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { ToggleButtonProps } from '@mui/material';
2
3
  import type React from 'react';
3
4
 
@@ -10,12 +11,12 @@ export interface ToggleProps extends Omit<ToggleButtonProps, 'color' | 'size'> {
10
11
  /**
11
12
  * The color theme of the toggle
12
13
  */
13
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral';
14
+ color?: Exclude<ColorValue, 'info'>;
14
15
 
15
16
  /**
16
17
  * The size of the toggle
17
18
  */
18
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
19
+ size?: SizeValue;
19
20
 
20
21
  /**
21
22
  * Icon for the toggle
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { ToggleButtonGroupProps } from '@mui/material';
2
3
  import type React from 'react';
3
4
 
@@ -17,12 +18,12 @@ export interface ToggleGroupProps extends Omit<ToggleButtonGroupProps, 'color' |
17
18
  /**
18
19
  * The color theme of the toggle group
19
20
  */
20
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral';
21
+ color?: Exclude<ColorValue, 'info'>;
21
22
 
22
23
  /**
23
24
  * The size of the toggle group
24
25
  */
25
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
26
+ size?: SizeValue;
26
27
 
27
28
  /**
28
29
  * Array of toggle options
@@ -1,8 +1,9 @@
1
+ import type { SizeValue } from '../../../tokens/scales';
1
2
  import type { ReactNode } from 'react';
2
3
 
3
4
  export type SeparatorVariant = 'solid' | 'dashed' | 'dotted' | 'gradient';
4
5
  export type SeparatorOrientation = 'horizontal' | 'vertical';
5
- export type SeparatorSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
6
+ export type SeparatorSize = SizeValue;
6
7
 
7
8
  export interface SeparatorProps {
8
9
  variant?: SeparatorVariant;
@@ -1,4 +1,5 @@
1
- export type SpacerSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
1
+ import type { SizeValue } from '../../../tokens/scales';
2
+ export type SpacerSize = SizeValue;
2
3
  export type SpacerDirection = 'horizontal' | 'vertical' | 'both';
3
4
 
4
5
  export interface SpacerProps {
@@ -114,7 +114,7 @@ const BREADCRUMBS_DEFAULTS: Pick<BreadcrumbsProps, BreadcrumbsDefaultedKeys> = {
114
114
  maxItems: 8,
115
115
  showHomeIcon: true,
116
116
  size: 'md',
117
- color: 'default',
117
+ color: 'neutral',
118
118
  elevation: 1,
119
119
  collapseBehavior: 'menu',
120
120
  mobileMaxItems: 3 };
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { BreadcrumbsProps as MuiBreadcrumbsProps } from '@mui/material';
2
3
  import type { ReactNode } from 'react';
3
4
 
@@ -105,13 +106,17 @@ export interface BreadcrumbsProps extends Omit<MuiBreadcrumbsProps, 'separator'>
105
106
  * Size of the breadcrumbs
106
107
  * @default 'md'
107
108
  */
108
- size?: 'sm' | 'md' | 'lg';
109
+ size?: Extract<SizeValue, 'sm' | 'md' | 'lg'>;
109
110
 
110
111
  /**
111
112
  * Color scheme for separators and accents
112
113
  * @default 'default'
113
114
  */
114
- color?: 'default' | 'primary' | 'secondary';
115
+ /**
116
+ * `neutral` is what this called `default`: the unaccented state, renamed to
117
+ * the house word rather than kept as a third spelling of the same idea.
118
+ */
119
+ color?: Extract<ColorValue, 'primary' | 'secondary' | 'neutral'>;
115
120
 
116
121
  /**
117
122
  * Elevation level for glass and elevated variants (0-5)
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { MenuProps } from '@mui/material';
2
3
  import type { ReactNode } from 'react';
3
4
 
@@ -40,7 +41,7 @@ export interface ContextMenuItem {
40
41
  /**
41
42
  * Color variant for the item
42
43
  */
43
- color?: 'default' | 'primary' | 'secondary' | 'error' | 'warning' | 'info' | 'success';
44
+ color?: ColorValue;
44
45
 
45
46
  /**
46
47
  * Whether the item is dangerous/destructive
@@ -82,7 +83,7 @@ export interface ContextMenuProps extends Omit<MenuProps, 'open' | 'anchorEl' |
82
83
  /**
83
84
  * Size of the menu items
84
85
  */
85
- size?: 'sm' | 'md' | 'lg';
86
+ size?: Extract<SizeValue, 'sm' | 'md' | 'lg'>;
86
87
 
87
88
  /**
88
89
  * Custom className for the trigger element
@@ -189,6 +189,7 @@ const renderLeafMenuItem = (
189
189
  onClick={!item.disabled ? () => handleItemClick(item) : undefined} // ← change
190
190
  color={item.color}
191
191
  showIconSpace={showIconSpace && !hasIcon}
192
+ data-testid={item.dataTestId}
192
193
  >
193
194
  {hasIcon && (
194
195
  <ListItemIcon sx={{ minWidth: size === 'sm' ? 32 : 40 }}>{item.icon}</ListItemIcon>
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { MenuProps } from '@mui/material';
2
3
  import type { ReactNode } from 'react';
3
4
 
@@ -55,7 +56,16 @@ export interface DropdownMenuItem {
55
56
  /**
56
57
  * Color variant for the item
57
58
  */
58
- color?: 'default' | 'primary' | 'secondary' | 'error' | 'warning' | 'info' | 'success';
59
+ color?: ColorValue;
60
+
61
+ /**
62
+ * Test ID for the rendered item.
63
+ *
64
+ * Needed by any surface where an action MOVES into this menu when the row
65
+ * runs out of room: the action's id has to survive the move, or a suite that
66
+ * drives it by id passes on a wide screen and fails on a narrow one.
67
+ */
68
+ dataTestId?: string;
59
69
  }
60
70
 
61
71
  export interface DropdownMenuProps extends Omit<MenuProps, 'open' | 'variant'> {
@@ -92,7 +102,7 @@ export interface DropdownMenuProps extends Omit<MenuProps, 'open' | 'variant'> {
92
102
  /**
93
103
  * Size of the menu items
94
104
  */
95
- size?: 'sm' | 'md' | 'lg';
105
+ size?: Extract<SizeValue, 'sm' | 'md' | 'lg'>;
96
106
 
97
107
  /**
98
108
  * Maximum height of the menu
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { ReactNode } from 'react';
2
3
 
3
4
  export interface NavigationMenuItem {
@@ -76,12 +77,16 @@ export interface NavigationMenuProps {
76
77
  /**
77
78
  * Color scheme of the menu
78
79
  */
79
- color?: 'default' | 'primary' | 'secondary';
80
+ /**
81
+ * `neutral` is what this called `default`: the unaccented state, renamed to
82
+ * the house word rather than kept as a third spelling of the same idea.
83
+ */
84
+ color?: Extract<ColorValue, 'primary' | 'secondary' | 'neutral'>;
80
85
 
81
86
  /**
82
87
  * Size of the menu items
83
88
  */
84
- size?: 'sm' | 'md' | 'lg';
89
+ size?: Extract<SizeValue, 'sm' | 'md' | 'lg'>;
85
90
 
86
91
  /**
87
92
  * Minimal style with no borders, shadows, or container backgrounds
@@ -139,7 +139,9 @@ const PaginationControl: React.FC<
139
139
  showFirstButton={p.showFirstButton && !isDots}
140
140
  showLastButton={p.showLastButton && !isDots}
141
141
  disabled={p.disabled}
142
- color={p.color}
142
+ // MUI spells the unaccented pagination colour `standard`; ours is
143
+ // `neutral`, translated here rather than carried as a second name.
144
+ color={p.color === undefined ? undefined : p.color === 'neutral' ? 'standard' : p.color}
143
145
  renderItem={renderItem}
144
146
  {...rest}
145
147
  />
@@ -1,7 +1,8 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { PaginationProps as MuiPaginationProps } from '@mui/material';
2
3
  import type { ReactNode } from 'react';
3
4
 
4
- export interface PaginationProps extends Omit<MuiPaginationProps, 'variant' | 'size'> {
5
+ export interface PaginationProps extends Omit<MuiPaginationProps, 'variant' | 'size' | 'color'> {
5
6
  /**
6
7
  * The variant of the pagination
7
8
  */
@@ -10,7 +11,7 @@ export interface PaginationProps extends Omit<MuiPaginationProps, 'variant' | 's
10
11
  /**
11
12
  * Size of the pagination buttons
12
13
  */
13
- size?: 'sm' | 'md' | 'lg';
14
+ size?: Extract<SizeValue, 'sm' | 'md' | 'lg'>;
14
15
 
15
16
  /**
16
17
  * Current page number
@@ -85,7 +86,8 @@ export interface PaginationProps extends Omit<MuiPaginationProps, 'variant' | 's
85
86
  /**
86
87
  * Custom color for the active page
87
88
  */
88
- color?: 'primary' | 'secondary' | 'standard';
89
+ /** `neutral` is what MUI spells `standard`; it is translated at the boundary. */
90
+ color?: Extract<ColorValue, 'primary' | 'secondary' | 'neutral'>;
89
91
 
90
92
  /**
91
93
  * Whether to show page info text
@@ -1,3 +1,4 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type { TabsProps as MuiTabsProps } from '@mui/material';
2
3
  import type { ReactNode } from 'react';
3
4
 
@@ -57,7 +58,7 @@ export interface TabsProps extends Omit<MuiTabsProps, 'variant' | 'children' | '
57
58
  /**
58
59
  * Size of the tabs
59
60
  */
60
- size?: 'sm' | 'md' | 'lg';
61
+ size?: Extract<SizeValue, 'sm' | 'md' | 'lg'>;
61
62
 
62
63
  /**
63
64
  * Array of tab items
@@ -77,7 +78,7 @@ export interface TabsProps extends Omit<MuiTabsProps, 'variant' | 'children' | '
77
78
  /**
78
79
  * Color theme for the tabs
79
80
  */
80
- color?: 'primary' | 'secondary';
81
+ color?: Extract<ColorValue, 'primary' | 'secondary'>;
81
82
 
82
83
  /**
83
84
  * Whether tabs should fill the full width
@@ -1,3 +1,4 @@
1
+ import type { ColorValue } from '../../../tokens/scales';
1
2
  import type React from 'react';
2
3
 
3
4
  export type BlockquoteVariant = 'default' | 'bordered' | 'citation';
@@ -6,6 +7,6 @@ export interface BlockquoteProps extends React.HTMLAttributes<HTMLElement> {
6
7
  variant?: BlockquoteVariant;
7
8
  author?: string;
8
9
  source?: string;
9
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral';
10
+ color?: Exclude<ColorValue, 'info'>;
10
11
  children: React.ReactNode;
11
12
  }
@@ -1,3 +1,4 @@
1
+ import type { SizeValue } from '../../../tokens/scales';
1
2
  import type React from 'react';
2
3
 
3
4
  export type CodeVariant = 'inline' | 'block' | 'highlight';
@@ -7,6 +8,6 @@ export interface CodeProps extends React.HTMLAttributes<HTMLElement> {
7
8
  language?: string;
8
9
  copyable?: boolean;
9
10
  lineNumbers?: boolean;
10
- size?: 'xs' | 'sm' | 'md' | 'lg';
11
+ size?: Extract<SizeValue, 'xs' | 'sm' | 'md' | 'lg'>;
11
12
  children: React.ReactNode;
12
13
  }
@@ -1,10 +1,11 @@
1
+ import type { ColorValue } from '../../../tokens/scales';
1
2
  import type React from 'react';
2
3
 
3
4
  export type HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'display';
4
5
 
5
6
  export interface HeadingProps extends React.HTMLAttributes<globalThis.HTMLHeadingElement> {
6
7
  level?: HeadingLevel;
7
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral';
8
+ color?: Exclude<ColorValue, 'info'>;
8
9
  weight?: 'light' | 'normal' | 'medium' | 'semibold' | 'bold';
9
10
  gradient?: boolean;
10
11
  children: React.ReactNode;
@@ -1,10 +1,11 @@
1
+ import type { ColorValue, SizeValue } from '../../../tokens/scales';
1
2
  import type React from 'react';
2
3
 
3
4
  export type ParagraphVariant = 'default' | 'lead' | 'muted' | 'small';
4
5
 
5
6
  export interface ParagraphProps extends React.HTMLAttributes<globalThis.HTMLParagraphElement> {
6
7
  variant?: ParagraphVariant;
7
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral';
8
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
8
+ color?: Exclude<ColorValue, 'info'>;
9
+ size?: SizeValue;
9
10
  children: React.ReactNode;
10
11
  }