oneslash-design-system 1.8.5 → 2.0.1

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 (53) hide show
  1. package/README.md +20 -6
  2. package/dist/components/alert.jsx +10 -10
  3. package/dist/components/button.jsx +22 -22
  4. package/dist/components/checkBox.jsx +10 -10
  5. package/dist/components/emptyBox.jsx +2 -2
  6. package/dist/components/icon.jsx +8 -8
  7. package/dist/components/iconButton.jsx +16 -16
  8. package/dist/components/line.jsx +1 -1
  9. package/dist/components/link.jsx +13 -13
  10. package/dist/components/loadingScreen.jsx +1 -1
  11. package/dist/components/menu.jsx +2 -1
  12. package/dist/components/menuItem.jsx +8 -8
  13. package/dist/components/modal.jsx +7 -6
  14. package/dist/components/navigation.jsx +1 -1
  15. package/dist/components/popover.jsx +3 -2
  16. package/dist/components/radioGroup.jsx +6 -6
  17. package/dist/components/select.jsx +10 -10
  18. package/dist/components/sharedStyles.d.ts +5 -5
  19. package/dist/components/sharedStyles.jsx +5 -5
  20. package/dist/components/tab.jsx +4 -4
  21. package/dist/components/tableCell.jsx +1 -1
  22. package/dist/components/tableContainer.jsx +1 -1
  23. package/dist/components/tableHeader.jsx +1 -1
  24. package/dist/components/tableHeaderCell.jsx +1 -1
  25. package/dist/components/tabsContainer.jsx +2 -2
  26. package/dist/components/tag.jsx +36 -36
  27. package/dist/components/textField.jsx +9 -9
  28. package/dist/components/textarea.jsx +8 -8
  29. package/dist/components/timeStamp.jsx +2 -2
  30. package/dist/components/tooltip.jsx +1 -1
  31. package/dist/components/useDarkMode.d.ts +3 -0
  32. package/dist/components/useDarkMode.js +25 -9
  33. package/dist/components/userImage.jsx +6 -3
  34. package/dist/designTokens.d.ts +643 -269
  35. package/dist/designTokens.js +114 -1
  36. package/dist/index.d.ts +1 -0
  37. package/dist/index.js +1 -0
  38. package/dist/stories/EmptyBox.stories.jsx +1 -0
  39. package/dist/tailwind-preset-auto.js +405 -0
  40. package/dist/tailwind-preset.js +399 -0
  41. package/dist/theme-auto.css +259 -0
  42. package/dist/theme.css +254 -0
  43. package/dist/themes/default-auto.css +251 -0
  44. package/dist/themes/default.css +167 -0
  45. package/dist/themes/forest-auto.css +251 -0
  46. package/dist/themes/forest.css +167 -0
  47. package/dist/tokens.css +19 -0
  48. package/dist/typography.css +81 -0
  49. package/package.json +18 -5
  50. package/dist/output.css +0 -2021
  51. package/dist/tailwind.config.d.ts +0 -3
  52. package/dist/tailwind.config.js +0 -222
  53. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,9 +1,9 @@
1
- export declare const focusRing = "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-light-text-primary dark:focus-visible:outline-dark-text-primary";
2
- export declare const focusRingDanger = "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-light-error-main dark:focus-visible:outline-dark-error-main";
3
- export declare const stateTransition = "transition duration-150 ease-out motion-reduce:transition-none";
1
+ export declare const focusRing = "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-fg-primary";
2
+ export declare const focusRingDanger = "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-error-main";
3
+ export declare const stateTransition = "transition duration-[var(--os-duration-fast)] ease-out motion-reduce:transition-none";
4
4
  export declare const pressFeedback = "enabled:active:scale-[0.97]";
5
5
  export declare const pressFeedbackAny = "active:scale-[0.97]";
6
- export declare const overlayTransition = "transition-[opacity,transform] duration-150 ease-[cubic-bezier(0.16,1,0.3,1)] motion-reduce:transition-none";
6
+ export declare const overlayTransition = "transition-[opacity,transform] duration-[var(--os-duration-fast)] ease-emphasized motion-reduce:transition-none";
7
7
  export declare const overlayHidden = "opacity-0 scale-[0.96]";
8
8
  export declare const overlayVisible = "opacity-100 scale-100";
9
- export declare const popTransition = "transition-transform duration-150 ease-[cubic-bezier(0.34,1.56,0.64,1)] motion-reduce:transition-none";
9
+ export declare const popTransition = "transition-transform duration-[var(--os-duration-fast)] ease-spring motion-reduce:transition-none";
@@ -3,18 +3,18 @@
3
3
  // Keyboard focus indicator for every interactive element. Uses the primary text
4
4
  // color (black in light, near-white in dark): the accent yellow is 1.9:1 on the
5
5
  // light background and too faint to see.
6
- export var focusRing = 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-light-text-primary dark:focus-visible:outline-dark-text-primary';
7
- export var focusRingDanger = 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-light-error-main dark:focus-visible:outline-dark-error-main';
6
+ export var focusRing = 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-fg-primary';
7
+ export var focusRingDanger = 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-error-main';
8
8
  // Motion is quick and snappy everywhere, and off for prefers-reduced-motion.
9
9
  // Hover/selected/disabled changes plus press feedback: colors, opacity and transform
10
- export var stateTransition = 'transition duration-150 ease-out motion-reduce:transition-none';
10
+ export var stateTransition = 'transition duration-[var(--os-duration-fast)] ease-out motion-reduce:transition-none';
11
11
  // Pressed controls dip slightly. `enabled:` skips disabled <button>s.
12
12
  export var pressFeedback = 'enabled:active:scale-[0.97]';
13
13
  // For clickable elements that aren't <button>s
14
14
  export var pressFeedbackAny = 'active:scale-[0.97]';
15
15
  // Overlays (Modal, Popover, Select menu) fade and scale in
16
- export var overlayTransition = 'transition-[opacity,transform] duration-150 ease-[cubic-bezier(0.16,1,0.3,1)] motion-reduce:transition-none';
16
+ export var overlayTransition = 'transition-[opacity,transform] duration-[var(--os-duration-fast)] ease-emphasized motion-reduce:transition-none';
17
17
  export var overlayHidden = 'opacity-0 scale-[0.96]';
18
18
  export var overlayVisible = 'opacity-100 scale-100';
19
19
  // Small marks (checkbox tick, radio dot) pop in with a slight overshoot
20
- export var popTransition = 'transition-transform duration-150 ease-[cubic-bezier(0.34,1.56,0.64,1)] motion-reduce:transition-none';
20
+ export var popTransition = 'transition-transform duration-[var(--os-duration-fast)] ease-spring motion-reduce:transition-none';
@@ -22,8 +22,8 @@ export default function Tab(_a) {
22
22
  }[size];
23
23
  // Inside a TabsContainer the container's sliding pill is the selected background
24
24
  var selectedClasses = inContainer
25
- ? 'text-light-text-contrast dark:text-dark-text-contrast'
26
- : 'bg-light-primary-dark dark:bg-dark-primary-dark text-light-text-contrast dark:text-dark-text-contrast';
25
+ ? 'text-primary-contrast'
26
+ : 'bg-primary-dark text-primary-contrast';
27
27
  return (<div data-tab-selected={isSelected} role="tab" aria-selected={isSelected}
28
28
  // Inside a container only the selected tab is in the Tab order; arrow keys move between tabs
29
29
  tabIndex={inContainer && !isSelected ? -1 : 0} onKeyDown={function (e) {
@@ -31,9 +31,9 @@ export default function Tab(_a) {
31
31
  e.preventDefault();
32
32
  handleClick();
33
33
  }
34
- }} className={"\n relative flex items-center space-x-1 rounded-[8px] cursor-pointer justify-start ".concat(stateTransition, " ").concat(pressFeedbackAny, " ").concat(focusRing, "\n ").concat(sizeClasses.tab, "\n ").concat(isSelected
34
+ }} className={"\n relative flex items-center space-x-1 rounded-control cursor-pointer justify-start ".concat(stateTransition, " ").concat(pressFeedbackAny, " ").concat(focusRing, "\n ").concat(sizeClasses.tab, "\n ").concat(isSelected
35
35
  ? selectedClasses
36
- : 'text-light-text-primary dark:text-dark-text-primary hover:bg-light-background-accent200 dark:hover:bg-dark-background-accent200', "\n ")} onClick={handleClick}>
36
+ : 'text-fg-primary hover:bg-background-accent200', "\n ")} onClick={handleClick}>
37
37
  {IconLeft && <IconLeft className={sizeClasses.icon} strokeWidth={2}/>}
38
38
  <div className={"flex flex-col text-center ".concat(sizeClasses.label)}>
39
39
  <span className="whitespace-nowrap">
@@ -5,7 +5,7 @@ export default function TableCell(_a) {
5
5
  var alignClass = align === 'center' ? 'text-center' : align === 'right' ? 'text-right' : 'text-left';
6
6
  var widthStyle = width ? { width: width, minWidth: minWidth || width } : {};
7
7
  var flexClass = width ? '' : 'flex-1';
8
- return (<div role="cell" className={"".concat(flexClass, " p-2 text-body2 text-light-text-primary dark:text-dark-text-primary border-t border-light-misc-divider dark:border-dark-misc-divider ").concat(alignClass)} style={widthStyle}>
8
+ return (<div role="cell" className={"".concat(flexClass, " p-2 text-body2 text-fg-primary border-t border-misc-divider ").concat(alignClass)} style={widthStyle}>
9
9
  {children}
10
10
  </div>);
11
11
  }
@@ -2,7 +2,7 @@
2
2
  import React from 'react';
3
3
  export default function TableContainer(_a) {
4
4
  var children = _a.children;
5
- return (<div role="table" className="w-full overflow-x-auto bg-light-background-default dark:bg-dark-background-default">
5
+ return (<div role="table" className="w-full overflow-x-auto bg-background-default">
6
6
  {children}
7
7
  </div>);
8
8
  }
@@ -2,7 +2,7 @@
2
2
  import React from 'react';
3
3
  export default function TableHeader(_a) {
4
4
  var children = _a.children;
5
- return (<div role="rowgroup" className="bg-light-background-default dark:bg-dark-background-default">
5
+ return (<div role="rowgroup" className="bg-background-default">
6
6
  {children}
7
7
  </div>);
8
8
  }
@@ -5,7 +5,7 @@ export default function TableHeaderCell(_a) {
5
5
  var alignClass = align === 'center' ? 'text-center' : align === 'right' ? 'text-right' : 'text-left';
6
6
  var widthStyle = width ? { width: width, minWidth: minWidth || width } : {};
7
7
  var flexClass = width ? '' : 'flex-1';
8
- return (<div role="columnheader" className={"".concat(flexClass, " p-2 text-body2 text-light-text-secondary dark:text-dark-text-secondary ").concat(alignClass)} style={widthStyle}>
8
+ return (<div role="columnheader" className={"".concat(flexClass, " p-2 text-body2 text-fg-secondary ").concat(alignClass)} style={widthStyle}>
9
9
  {children}
10
10
  </div>);
11
11
  }
@@ -77,11 +77,11 @@ export default function TabsContainer(_a) {
77
77
  e.preventDefault();
78
78
  tabs[next].focus();
79
79
  tabs[next].click();
80
- }} className={"\n relative flex gap-0.5 p-1 rounded-[12px] overflow-x-auto\n ".concat(tabCount > 0 ? 'bg-light-background-accent100 dark:bg-dark-background-accent100' : 'bg-transparent', "\n ")} style={{
80
+ }} className={"\n relative flex gap-0.5 p-1 rounded-container overflow-x-auto\n ".concat(tabCount > 0 ? 'bg-background-accent100' : 'bg-transparent', "\n ")} style={{
81
81
  scrollbarWidth: 'none',
82
82
  msOverflowStyle: 'none',
83
83
  }}>
84
- {indicator && (<span aria-hidden className={"absolute rounded-[8px] pointer-events-none bg-light-primary-dark dark:bg-dark-primary-dark\n ".concat(indicator.animate ? 'transition-[transform,width,height] duration-200 ease-[cubic-bezier(0.16,1,0.3,1)] motion-reduce:transition-none' : '')} style={{
84
+ {indicator && (<span aria-hidden className={"absolute rounded-control pointer-events-none bg-primary-dark\n ".concat(indicator.animate ? 'transition-[transform,width,height] duration-[var(--os-duration-slide)] ease-emphasized motion-reduce:transition-none' : '')} style={{
85
85
  top: 0,
86
86
  left: 0,
87
87
  transform: "translate(".concat(indicator.x, "px, ").concat(indicator.y, "px)"),
@@ -2,47 +2,47 @@
2
2
  import React from 'react';
3
3
  import { icons } from 'lucide-react';
4
4
  import { focusRing, pressFeedbackAny, stateTransition } from './sharedStyles';
5
- // Light: the -dark shade with white text; dark: the -main shade with black text.
6
- // Both keep text at 4.4:1 or better.
5
+ // Filled tags use the status `fill` with `onFill` text; text-only tags use the status `text` token.
6
+ // Each pair is checked at 4.5:1 by `npm run check:contrast`.
7
7
  var colorConfig = {
8
8
  default: {
9
- bg: 'bg-light-secondary-light dark:bg-dark-secondary-light',
10
- text: 'text-light-text-primary dark:text-dark-text-primary',
11
- textOnly: 'text-light-text-secondary dark:text-dark-text-secondary',
12
- border: 'border-light-misc-divider dark:border-dark-misc-divider',
13
- dot: 'bg-light-text-secondary dark:bg-dark-text-secondary',
9
+ bg: 'bg-secondary-light',
10
+ text: 'text-fg-primary',
11
+ textOnly: 'text-fg-secondary',
12
+ border: 'border-misc-divider',
13
+ dot: 'bg-fg-secondary',
14
14
  hasBorderTextOnly: false,
15
15
  },
16
16
  success: {
17
- bg: 'bg-light-success-dark dark:bg-dark-success-main',
18
- text: 'text-light-text-contrast dark:text-dark-text-contrast',
19
- textOnly: 'text-light-success-dark dark:text-dark-success-main',
20
- border: 'border-light-success-dark dark:border-dark-success-main',
21
- dot: 'bg-light-success-main dark:bg-dark-success-main',
17
+ bg: 'bg-success-fill',
18
+ text: 'text-success-onFill',
19
+ textOnly: 'text-success-text',
20
+ border: 'border-success-fill',
21
+ dot: 'bg-success-main',
22
22
  hasBorderTextOnly: true,
23
23
  },
24
24
  warning: {
25
- bg: 'bg-light-warning-dark dark:bg-dark-warning-main',
26
- text: 'text-light-text-contrast dark:text-dark-text-contrast',
27
- textOnly: 'text-light-warning-dark dark:text-dark-warning-main',
28
- border: 'border-light-warning-dark dark:border-dark-warning-main',
29
- dot: 'bg-light-warning-main dark:bg-dark-warning-main',
25
+ bg: 'bg-warning-fill',
26
+ text: 'text-warning-onFill',
27
+ textOnly: 'text-warning-text',
28
+ border: 'border-warning-fill',
29
+ dot: 'bg-warning-main',
30
30
  hasBorderTextOnly: true,
31
31
  },
32
32
  error: {
33
- bg: 'bg-light-error-dark dark:bg-dark-error-main',
34
- text: 'text-light-text-contrast dark:text-dark-text-contrast',
35
- textOnly: 'text-light-error-dark dark:text-dark-error-light',
36
- border: 'border-light-error-dark dark:border-dark-error-main',
37
- dot: 'bg-light-error-main dark:bg-dark-error-main',
33
+ bg: 'bg-error-fill',
34
+ text: 'text-error-onFill',
35
+ textOnly: 'text-error-text',
36
+ border: 'border-error-fill',
37
+ dot: 'bg-error-main',
38
38
  hasBorderTextOnly: true,
39
39
  },
40
40
  info: {
41
- bg: 'bg-light-info-dark dark:bg-dark-info-main',
42
- text: 'text-light-text-contrast dark:text-dark-text-contrast',
43
- textOnly: 'text-light-info-dark dark:text-dark-info-main',
44
- border: 'border-light-info-dark dark:border-dark-info-main',
45
- dot: 'bg-light-info-main dark:bg-dark-info-main',
41
+ bg: 'bg-info-fill',
42
+ text: 'text-info-onFill',
43
+ textOnly: 'text-info-text',
44
+ border: 'border-info-fill',
45
+ dot: 'bg-info-main',
46
46
  hasBorderTextOnly: true,
47
47
  },
48
48
  };
@@ -69,29 +69,29 @@ export default function Tag(_a) {
69
69
  bgClasses = variant === 'contained' ? colorStyles.bg : '';
70
70
  }
71
71
  else if (isSelected && variant === 'contained') {
72
- bgClasses = 'bg-light-accent-main dark:bg-dark-accent-main';
72
+ bgClasses = 'bg-accent-main';
73
73
  }
74
74
  else if (variant === 'contained') {
75
- bgClasses = 'bg-light-background-accent300 dark:bg-dark-background-accent300';
75
+ bgClasses = 'bg-background-accent300';
76
76
  }
77
77
  // Font color
78
78
  var fontClasses = '';
79
79
  if (variant === 'dot') {
80
- fontClasses = 'text-light-text-primary dark:text-dark-text-primary';
80
+ fontClasses = 'text-fg-primary';
81
81
  }
82
82
  else if (colorStyles) {
83
83
  fontClasses = variant === 'textOnly' ? colorStyles.textOnly : colorStyles.text;
84
84
  }
85
85
  else if (isSelected && variant === 'contained') {
86
86
  // Selected contained tags sit on accent-main — use the accent contrast token
87
- fontClasses = 'text-light-accent-contrast dark:text-dark-accent-contrast';
87
+ fontClasses = 'text-accent-contrast';
88
88
  }
89
89
  else if (isSelected) {
90
90
  // No fill behind the text: the accent border marks the selection
91
- fontClasses = 'text-light-text-primary dark:text-dark-text-primary';
91
+ fontClasses = 'text-fg-primary';
92
92
  }
93
93
  else {
94
- fontClasses = 'text-light-text-primary dark:text-dark-text-primary';
94
+ fontClasses = 'text-fg-primary';
95
95
  }
96
96
  // Border styles. Every tag has a 1px border (transparent when hidden) so all variants share a height
97
97
  var borderClasses = 'border border-transparent';
@@ -107,16 +107,16 @@ export default function Tag(_a) {
107
107
  }
108
108
  }
109
109
  else if (isSelected && variant === 'textOnly') {
110
- borderClasses = 'border border-light-accent-main dark:border-dark-accent-main';
110
+ borderClasses = 'border border-accent-main';
111
111
  }
112
112
  else if (variant === 'contained') {
113
- borderClasses = 'border border-light-misc-divider dark:border-dark-misc-divider';
113
+ borderClasses = 'border border-misc-divider';
114
114
  }
115
115
  // Dot color
116
116
  var dotColor = (colorStyles === null || colorStyles === void 0 ? void 0 : colorStyles.dot) || colorConfig.default.dot;
117
117
  // Hover (only when not selected, no color, and onClick is provided)
118
118
  var hoverClasses = !isSelected && !color && variant === 'contained' && onClick
119
- ? 'hover:bg-light-background-accent200 dark:hover:bg-dark-background-accent200'
119
+ ? 'hover:bg-background-accent200'
120
120
  : '';
121
121
  var cursorClass = onClick && !isSelected ? 'cursor-pointer' : '';
122
122
  // inline-flex so a tag wraps its content instead of stretching to its container
@@ -19,20 +19,20 @@ export default function TextField(_a) {
19
19
  small: 'text-body2 p-2 leading-[18px]', // body2 (14px), padding 8px
20
20
  tiny: 'text-caption p-1 leading-[16px]', // caption (12px), padding 4px
21
21
  }[size];
22
- var baseClasses = "w-full border rounded-[8px] outline-none ".concat(stateTransition, "\n placeholder:text-light-text-disabled dark:placeholder:text-dark-text-disabled");
22
+ var baseClasses = "w-full border rounded-control outline-none ".concat(stateTransition, "\n placeholder:text-fg-disabled");
23
23
  // One background and text color per state, so disabled can't be overridden by the enabled ones
24
24
  var colorClasses = disabled
25
- ? 'bg-transparent text-light-text-disabled dark:text-dark-text-disabled cursor-not-allowed'
26
- : 'bg-light-background-default dark:bg-dark-background-default text-light-text-primary dark:text-dark-text-primary';
25
+ ? 'bg-transparent text-fg-disabled cursor-not-allowed'
26
+ : 'bg-background-default text-fg-primary';
27
27
  // Border: error > focus (2px offset outline, the same weight as Button) > hover > default
28
28
  var getBorderColor = function () {
29
29
  if (error) {
30
- return 'border-light-error-main dark:border-dark-error-main focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-light-error-main dark:focus:outline-dark-error-main';
30
+ return 'border-error-main focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-error-main';
31
31
  }
32
32
  if (disabled) {
33
- return 'border-light-text-disabled dark:border-dark-text-disabled';
33
+ return 'border-fg-disabled';
34
34
  }
35
- return "border-light-text-disabled dark:border-dark-text-disabled\n hover:border-light-text-secondary dark:hover:border-dark-text-secondary\n focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-light-text-primary dark:focus:outline-dark-text-primary";
35
+ return "border-fg-disabled\n hover:border-fg-secondary\n focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-fg-primary";
36
36
  };
37
37
  var errorId = "".concat(id, "-error");
38
38
  // Get inputMode for mobile keyboard optimization
@@ -58,13 +58,13 @@ export default function TextField(_a) {
58
58
  'aria-describedby': error ? errorId : undefined,
59
59
  };
60
60
  return (<div className="flex flex-col w-full">
61
- {label && (<label htmlFor={id} className="mb-1 text-body2 text-light-text-secondary dark:text-dark-text-secondary">
62
- {label}{required && <span className="text-light-error-main dark:text-dark-error-main ml-0.5">*</span>}
61
+ {label && (<label htmlFor={id} className="mb-1 text-body2 text-fg-secondary">
62
+ {label}{required && <span className="text-error-main ml-0.5">*</span>}
63
63
  </label>)}
64
64
  <div className="relative">
65
65
  {multiline ? (<textarea id={id} rows={maxRows} className={containerClasses} value={value} onChange={onChange} placeholder={placeholder} onFocus={onFocus} onBlur={onBlur} onKeyDown={handleKeyDown} autoFocus={autoFocus} disabled={disabled} required={required} autoComplete="off" {...errorProps}/>) : (<input id={id} type={type} inputMode={getInputMode()} className={containerClasses} value={value} onChange={onChange} placeholder={placeholder} onFocus={onFocus} onBlur={onBlur} onKeyDown={handleKeyDown} autoFocus={autoFocus} disabled={disabled} required={required} autoComplete="off" {...errorProps}/>)}
66
66
  </div>
67
- {error && (<p id={errorId} className="mt-1 text-light-error-main dark:text-dark-error-main text-body2">
67
+ {error && (<p id={errorId} className="mt-1 text-error-main text-body2">
68
68
  {errorText}
69
69
  </p>)}
70
70
  </div>);
@@ -43,31 +43,31 @@ export default function Textarea(_a) {
43
43
  small: 'text-body2 p-2 leading-[18px]', // body2 (14px), padding 8px
44
44
  tiny: 'text-caption p-1 leading-[16px]', // caption (12px), padding 4px
45
45
  }[size];
46
- var baseClasses = "block w-full border rounded-[8px] outline-none resize-none [&::-webkit-scrollbar]:hidden ".concat(stateTransition, "\n placeholder:text-light-text-disabled dark:placeholder:text-dark-text-disabled");
46
+ var baseClasses = "block w-full border rounded-control outline-none resize-none [&::-webkit-scrollbar]:hidden ".concat(stateTransition, "\n placeholder:text-fg-disabled");
47
47
  // One background and text color per state, so disabled can't be overridden by the enabled ones
48
48
  var colorClasses = disabled
49
- ? 'bg-transparent text-light-text-disabled dark:text-dark-text-disabled cursor-not-allowed'
50
- : 'bg-light-background-default dark:bg-dark-background-default text-light-text-primary dark:text-dark-text-primary';
49
+ ? 'bg-transparent text-fg-disabled cursor-not-allowed'
50
+ : 'bg-background-default text-fg-primary';
51
51
  // Border: error > focus (2px offset outline, the same weight as Button) > hover > default
52
52
  var getBorderColor = function () {
53
53
  if (error) {
54
- return 'border-light-error-main dark:border-dark-error-main focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-light-error-main dark:focus:outline-dark-error-main';
54
+ return 'border-error-main focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-error-main';
55
55
  }
56
56
  if (disabled) {
57
- return 'border-light-text-disabled dark:border-dark-text-disabled';
57
+ return 'border-fg-disabled';
58
58
  }
59
- return "border-light-text-disabled dark:border-dark-text-disabled\n hover:border-light-text-secondary dark:hover:border-dark-text-secondary\n focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-light-text-primary dark:focus:outline-dark-text-primary";
59
+ return "border-fg-disabled\n hover:border-fg-secondary\n focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-fg-primary";
60
60
  };
61
61
  var containerClasses = "\n ".concat(colorClasses, "\n ").concat(baseClasses, "\n ").concat(sizeClasses, "\n ").concat(getBorderColor(), "\n ");
62
62
  var errorId = "".concat(id, "-error");
63
63
  return (<div className="flex flex-col w-full">
64
- {label && (<label htmlFor={id} className="mb-1 text-body2 text-light-text-secondary dark:text-dark-text-secondary">
64
+ {label && (<label htmlFor={id} className="mb-1 text-body2 text-fg-secondary">
65
65
  {label}
66
66
  </label>)}
67
67
  <div className="relative">
68
68
  <textarea ref={textareaRef} id={id} rows={1} className={containerClasses} value={value} onChange={onChange} onInput={adjustHeight} placeholder={placeholder} onFocus={onFocus} onBlur={onBlur} onKeyDown={handleKeyDown} onCompositionStart={onCompositionStart} onCompositionEnd={onCompositionEnd} autoFocus={autoFocus} disabled={disabled} autoComplete="off" aria-invalid={error || undefined} aria-describedby={error ? errorId : undefined}/>
69
69
  </div>
70
- {error && (<p id={errorId} className="mt-1 text-light-error-main dark:text-dark-error-main text-body2">
70
+ {error && (<p id={errorId} className="mt-1 text-error-main text-body2">
71
71
  {errorText}
72
72
  </p>)}
73
73
  </div>);
@@ -96,8 +96,8 @@ export default function TimeStamp(_a) {
96
96
  var sizeClass = textSize === 'medium' ? 'text-body2' : textSize === 'large' ? 'text-body1' : 'text-caption';
97
97
  // Determine text color classes
98
98
  var colorClass = textColor === 'primary'
99
- ? 'text-light-text-primary dark:text-dark-text-primary'
100
- : 'text-light-text-secondary dark:text-dark-text-secondary';
99
+ ? 'text-fg-primary'
100
+ : 'text-fg-secondary';
101
101
  return (
102
102
  // Relative times differ between server and client render, which is expected
103
103
  <time dateTime={isNaN(new Date(createdAt).getTime()) ? undefined : new Date(createdAt).toISOString()} className={"block ".concat(sizeClass, " ").concat(colorClass)} suppressHydrationWarning>
@@ -88,7 +88,7 @@ export default function Tooltip(_a) {
88
88
  onFocus={function () { return show(0); }} onBlur={hide} onClick={hide} className="relative inline-block">
89
89
  {children}
90
90
  {/* Rendered in <body> so no parent's overflow or stacking context can clip or cover it */}
91
- {mounted && createPortal(<div ref={tooltipRef} id={tooltipId} role="tooltip" className={"fixed z-[1000] w-max max-w-[min(320px,calc(100vw-16px))] break-words text-caption rounded-[8px] py-1 px-2 pointer-events-none\n dark:bg-light-background-accent300 bg-dark-background-accent300\n dark:text-light-text-primary text-dark-text-primary\n transition-opacity duration-150 ease-out motion-reduce:transition-none ".concat(visible && coords ? 'opacity-100' : 'opacity-0')} style={{ top: (_b = coords === null || coords === void 0 ? void 0 : coords.top) !== null && _b !== void 0 ? _b : 0, left: (_c = coords === null || coords === void 0 ? void 0 : coords.left) !== null && _c !== void 0 ? _c : 0 }}>
91
+ {mounted && createPortal(<div ref={tooltipRef} id={tooltipId} role="tooltip" className={"fixed z-[var(--os-z-tooltip)] w-max max-w-[min(320px,calc(100vw-16px))] break-words text-caption rounded-control py-1 px-2 pointer-events-none\n bg-misc-tooltipBg\n text-misc-tooltipText\n transition-opacity duration-[var(--os-duration-fast)] ease-out motion-reduce:transition-none ".concat(visible && coords ? 'opacity-100' : 'opacity-0')} style={{ top: (_b = coords === null || coords === void 0 ? void 0 : coords.top) !== null && _b !== void 0 ? _b : 0, left: (_c = coords === null || coords === void 0 ? void 0 : coords.left) !== null && _c !== void 0 ? _c : 0 }}>
92
92
  {title}
93
93
  </div>, document.body)}
94
94
  </div>);
@@ -1 +1,4 @@
1
+ export declare function resolveDarkMode(classList: {
2
+ contains(c: string): boolean;
3
+ }, prefersDark: boolean, mode?: string): boolean;
1
4
  export default function useDarkMode(): boolean;
@@ -1,18 +1,34 @@
1
1
  'use client';
2
2
  import { useState, useEffect } from 'react';
3
+ var QUERY = '(prefers-color-scheme: dark)';
4
+ export function resolveDarkMode(classList, prefersDark, mode) {
5
+ // The loaded theme file declares the mode it renders via --os-mode; it wins over the class/media rule.
6
+ if (mode === 'dark')
7
+ return true;
8
+ if (mode === 'light')
9
+ return false;
10
+ if (classList.contains('dark'))
11
+ return true;
12
+ if (classList.contains('light'))
13
+ return false;
14
+ return prefersDark;
15
+ }
3
16
  export default function useDarkMode() {
4
- var _a = useState(function () {
5
- if (typeof document === 'undefined')
6
- return false;
7
- return document.documentElement.classList.contains('dark');
8
- }), isDark = _a[0], setIsDark = _a[1];
17
+ var _a = useState(false), isDark = _a[0], setIsDark = _a[1];
9
18
  useEffect(function () {
10
19
  var el = document.documentElement;
11
- var observer = new MutationObserver(function () {
12
- setIsDark(el.classList.contains('dark'));
13
- });
20
+ var mq = window.matchMedia ? window.matchMedia(QUERY) : null;
21
+ var update = function () {
22
+ return setIsDark(resolveDarkMode(el.classList, mq ? mq.matches : false, getComputedStyle(el).getPropertyValue('--os-mode').trim()));
23
+ };
24
+ var observer = new MutationObserver(update);
14
25
  observer.observe(el, { attributes: true, attributeFilter: ['class'] });
15
- return function () { return observer.disconnect(); };
26
+ mq === null || mq === void 0 ? void 0 : mq.addEventListener('change', update);
27
+ update();
28
+ return function () {
29
+ observer.disconnect();
30
+ mq === null || mq === void 0 ? void 0 : mq.removeEventListener('change', update);
31
+ };
16
32
  }, []);
17
33
  return isDark;
18
34
  }
@@ -33,11 +33,14 @@ export default function UserImage(_a) {
33
33
  var lightBg = "hsl(".concat(hue, ", ").concat(saturation, "%, 80%)");
34
34
  // Dark mode: darker, vibrant variant
35
35
  var darkBg = "hsl(".concat(hue, ", ").concat(saturation, "%, 30%)");
36
- return (<div style={{
36
+ return (
37
+ // Per-user hue computed in JS, not a theme token, so the dark: variant stays here (one of the two documented
38
+ // `dark:` exemptions, see the overlay rings in Menu/Popover/Modal). The dark: variant follows whatever dark variant the app's preset/@theme defines (class-only or OS-aware).
39
+ <div style={{
37
40
  '--light-bg': lightBg,
38
41
  '--dark-bg': darkBg,
39
- }} className="flex items-center justify-center w-6 h-6 rounded-full overflow-hidden bg-[var(--light-bg)] dark:bg-[var(--dark-bg)] text-light-text-primary dark:text-dark-text-primary">
40
- {userImgUrl ? (<img src={userImgUrl} alt={userHandle} className="w-full h-full object-cover rounded-full"/>) : (<span className="text-body1 text-light-text-primary dark:text-dark-text-primary">
42
+ }} className="flex items-center justify-center w-6 h-6 rounded-full overflow-hidden bg-[var(--light-bg)] dark:bg-[var(--dark-bg)] text-fg-primary">
43
+ {userImgUrl ? (<img src={userImgUrl} alt={userHandle} className="w-full h-full object-cover rounded-full"/>) : (<span className="text-body1 text-fg-primary">
41
44
  {displayInitial}
42
45
  </span>)}
43
46
  </div>);