@kushagradhawan/kookie-ui 0.1.56 → 0.1.58

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 (78) hide show
  1. package/components.css +166 -41
  2. package/dist/cjs/components/_internal/shell-bottom.d.ts.map +1 -1
  3. package/dist/cjs/components/_internal/shell-bottom.js +1 -1
  4. package/dist/cjs/components/_internal/shell-bottom.js.map +3 -3
  5. package/dist/cjs/components/_internal/shell-inspector.d.ts.map +1 -1
  6. package/dist/cjs/components/_internal/shell-inspector.js +1 -1
  7. package/dist/cjs/components/_internal/shell-inspector.js.map +3 -3
  8. package/dist/cjs/components/_internal/shell-sidebar.js +1 -1
  9. package/dist/cjs/components/_internal/shell-sidebar.js.map +3 -3
  10. package/dist/cjs/components/chatbar.d.ts.map +1 -1
  11. package/dist/cjs/components/chatbar.js.map +2 -2
  12. package/dist/cjs/components/icons.d.ts +1 -1
  13. package/dist/cjs/components/icons.d.ts.map +1 -1
  14. package/dist/cjs/components/icons.js.map +2 -2
  15. package/dist/cjs/components/schemas/shell.schema.d.ts +2 -2
  16. package/dist/cjs/components/schemas/shell.schema.d.ts.map +1 -1
  17. package/dist/cjs/components/schemas/shell.schema.js +1 -1
  18. package/dist/cjs/components/schemas/shell.schema.js.map +3 -3
  19. package/dist/cjs/components/shell.d.ts.map +1 -1
  20. package/dist/cjs/components/shell.js +1 -1
  21. package/dist/cjs/components/shell.js.map +3 -3
  22. package/dist/cjs/components/theme.props.d.ts +1 -1
  23. package/dist/cjs/components/theme.props.js +1 -1
  24. package/dist/cjs/components/theme.props.js.map +2 -2
  25. package/dist/cjs/helpers/font-config.d.ts +10 -0
  26. package/dist/cjs/helpers/font-config.d.ts.map +1 -1
  27. package/dist/cjs/helpers/font-config.js +2 -2
  28. package/dist/cjs/helpers/font-config.js.map +2 -2
  29. package/dist/esm/components/_internal/shell-bottom.d.ts.map +1 -1
  30. package/dist/esm/components/_internal/shell-bottom.js +1 -1
  31. package/dist/esm/components/_internal/shell-bottom.js.map +3 -3
  32. package/dist/esm/components/_internal/shell-inspector.d.ts.map +1 -1
  33. package/dist/esm/components/_internal/shell-inspector.js +1 -1
  34. package/dist/esm/components/_internal/shell-inspector.js.map +3 -3
  35. package/dist/esm/components/_internal/shell-sidebar.js +1 -1
  36. package/dist/esm/components/_internal/shell-sidebar.js.map +3 -3
  37. package/dist/esm/components/chatbar.d.ts.map +1 -1
  38. package/dist/esm/components/chatbar.js.map +2 -2
  39. package/dist/esm/components/icons.d.ts +1 -1
  40. package/dist/esm/components/icons.d.ts.map +1 -1
  41. package/dist/esm/components/icons.js.map +2 -2
  42. package/dist/esm/components/schemas/shell.schema.d.ts +2 -2
  43. package/dist/esm/components/schemas/shell.schema.d.ts.map +1 -1
  44. package/dist/esm/components/schemas/shell.schema.js.map +3 -3
  45. package/dist/esm/components/shell.d.ts.map +1 -1
  46. package/dist/esm/components/shell.js +1 -1
  47. package/dist/esm/components/shell.js.map +3 -3
  48. package/dist/esm/components/theme.props.d.ts +1 -1
  49. package/dist/esm/components/theme.props.js +1 -1
  50. package/dist/esm/components/theme.props.js.map +2 -2
  51. package/dist/esm/helpers/font-config.d.ts +10 -0
  52. package/dist/esm/helpers/font-config.d.ts.map +1 -1
  53. package/dist/esm/helpers/font-config.js +2 -2
  54. package/dist/esm/helpers/font-config.js.map +2 -2
  55. package/package.json +1 -1
  56. package/schemas/base-button.json +1 -1
  57. package/schemas/button.json +1 -1
  58. package/schemas/icon-button.json +1 -1
  59. package/schemas/index.json +6 -6
  60. package/schemas/toggle-button.json +1 -1
  61. package/schemas/toggle-icon-button.json +1 -1
  62. package/src/components/_internal/base-sidebar-menu.css +19 -4
  63. package/src/components/_internal/shell-bottom.tsx +14 -13
  64. package/src/components/_internal/shell-inspector.tsx +13 -11
  65. package/src/components/_internal/shell-sidebar.tsx +12 -12
  66. package/src/components/chatbar.tsx +0 -1
  67. package/src/components/icons.tsx +19 -87
  68. package/src/components/schemas/shell.schema.ts +10 -33
  69. package/src/components/separator.css +1 -1
  70. package/src/components/shell.tsx +32 -24
  71. package/src/components/sidebar.css +32 -6
  72. package/src/components/theme.props.tsx +1 -1
  73. package/src/helpers/font-config.ts +35 -8
  74. package/src/styles/fonts.css +11 -15
  75. package/src/styles/tokens/typography.css +17 -7
  76. package/styles.css +182 -47
  77. package/tokens/base.css +12 -3
  78. package/tokens.css +12 -3
@@ -1,6 +1,6 @@
1
1
  .rt-Separator {
2
2
  display: block;
3
- background-color: var(--accent-a6);
3
+ background-color: var(--accent-a5);
4
4
  }
5
5
 
6
6
  /***************************************************************************************************
@@ -309,18 +309,24 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
309
309
  }
310
310
  dispatchPane({ type: 'TOGGLE_PANE', target });
311
311
  },
312
- [paneState.sidebarMode],
312
+ [paneState.sidebarMode, setSidebarMode],
313
313
  );
314
314
 
315
- const expandPane = React.useCallback((target: PaneTarget) => {
316
- if (target === 'sidebar') return setSidebarMode('expanded');
317
- dispatchPane({ type: 'EXPAND_PANE', target });
318
- }, []);
315
+ const expandPane = React.useCallback(
316
+ (target: PaneTarget) => {
317
+ if (target === 'sidebar') return setSidebarMode('expanded');
318
+ dispatchPane({ type: 'EXPAND_PANE', target });
319
+ },
320
+ [setSidebarMode],
321
+ );
319
322
 
320
- const collapsePane = React.useCallback((target: PaneTarget) => {
321
- if (target === 'sidebar') return setSidebarMode('collapsed');
322
- dispatchPane({ type: 'COLLAPSE_PANE', target });
323
- }, []);
323
+ const collapsePane = React.useCallback(
324
+ (target: PaneTarget) => {
325
+ if (target === 'sidebar') return setSidebarMode('collapsed');
326
+ dispatchPane({ type: 'COLLAPSE_PANE', target });
327
+ },
328
+ [setSidebarMode],
329
+ );
324
330
 
325
331
  const baseContextValue = React.useMemo(
326
332
  () => ({
@@ -351,10 +357,15 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
351
357
  }),
352
358
  [
353
359
  paneState.leftMode,
360
+ setLeftMode,
354
361
  paneState.panelMode,
362
+ setPanelMode,
355
363
  paneState.sidebarMode,
364
+ setSidebarMode,
356
365
  paneState.inspectorMode,
366
+ setInspectorMode,
357
367
  paneState.bottomMode,
368
+ setBottomMode,
358
369
  hasLeft,
359
370
  hasSidebar,
360
371
  currentBreakpoint,
@@ -388,7 +399,7 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
388
399
  if (typeof firstRailOpen === 'undefined') return;
389
400
  const shouldOpen = Boolean(firstRailOpen);
390
401
  setLeftMode(shouldOpen ? 'expanded' : 'collapsed');
391
- }, [firstRailOpen]);
402
+ }, [firstRailOpen, setLeftMode]);
392
403
 
393
404
  const heightStyle = React.useMemo(() => {
394
405
  if (height === 'full') return { height: '100vh' };
@@ -588,25 +599,27 @@ const Left = React.forwardRef<HTMLDivElement, LeftProps>(
588
599
 
589
600
  // Initialize from responsive defaultOpen once when uncontrolled and breakpoint ready
590
601
  const didInitFromDefaultOpenRef = React.useRef(false);
602
+ const propsOpen = (props as any).open;
603
+ const propsDefaultOpen = (props as any).defaultOpen;
591
604
  React.useEffect(() => {
592
605
  if (didInitFromDefaultOpenRef.current) return;
593
606
  if (!shell.currentBreakpointReady) return;
594
- if (typeof (props as any).open !== 'undefined') return; // controlled
595
- if (typeof (props as any).defaultOpen === 'undefined') return;
607
+ if (typeof propsOpen !== 'undefined') return; // controlled
608
+ if (typeof propsDefaultOpen === 'undefined') return;
596
609
  didInitFromDefaultOpenRef.current = true;
597
610
  const initial = Boolean(resolvedDefaultOpen);
598
611
  shell.setLeftMode(initial ? 'expanded' : 'collapsed');
599
612
  (props as any).onOpenChange?.(initial, { reason: 'init' });
600
- }, [shell.currentBreakpointReady, (props as any).open, (props as any).defaultOpen, resolvedDefaultOpen]);
613
+ }, [shell, propsOpen, propsDefaultOpen, resolvedDefaultOpen, props]);
601
614
  React.useEffect(() => {
602
615
  // Controlled Left via Rail.open
603
- if (typeof (props as any).open !== 'undefined') {
604
- const shouldOpen = Boolean((props as any).open);
616
+ if (typeof propsOpen !== 'undefined') {
617
+ const shouldOpen = Boolean(propsOpen);
605
618
  shell.setLeftMode(shouldOpen ? 'expanded' : 'collapsed');
606
619
  return;
607
620
  }
608
621
  // defaultOpen is applied in Rail; Left no longer follows responsive defaults
609
- }, [shell, (props as any).open]);
622
+ }, [shell, propsOpen]);
610
623
 
611
624
  // Sync controlled mode
612
625
  // removed mode sync
@@ -622,7 +635,7 @@ const Left = React.forwardRef<HTMLDivElement, LeftProps>(
622
635
  (props as any).onOpenChange?.(shell.leftMode === 'expanded', { reason: 'toggle' });
623
636
  }
624
637
  lastLeftModeRef.current = shell.leftMode;
625
- }, [shell.leftMode, resolvedDefaultOpen]);
638
+ }, [shell, resolvedDefaultOpen, props]);
626
639
 
627
640
  // Emit expand/collapse events
628
641
  React.useEffect(() => {
@@ -739,7 +752,6 @@ const Rail = React.forwardRef<HTMLDivElement, RailProps>(({ className, presentat
739
752
  const wasControlledRef = React.useRef<boolean | null>(null);
740
753
  if (process.env.NODE_ENV !== 'production') {
741
754
  if (typeof props.open !== 'undefined' && typeof props.defaultOpen !== 'undefined') {
742
- // eslint-disable-next-line no-console
743
755
  console.error('Shell.Rail: Do not pass both `open` and `defaultOpen`. Choose one.');
744
756
  }
745
757
  }
@@ -752,7 +764,6 @@ const Rail = React.forwardRef<HTMLDivElement, RailProps>(({ className, presentat
752
764
  return;
753
765
  }
754
766
  if (wasControlledRef.current !== isControlled) {
755
- // eslint-disable-next-line no-console
756
767
  console.warn('Shell.Rail: Switching between controlled and uncontrolled `open` is not supported.');
757
768
  wasControlledRef.current = isControlled;
758
769
  }
@@ -891,11 +902,9 @@ const Panel = React.forwardRef<HTMLDivElement, PanelPublicProps>(
891
902
  // Dev-only runtime guard
892
903
  if (process.env.NODE_ENV !== 'production') {
893
904
  if (typeof open !== 'undefined' && typeof defaultOpen !== 'undefined') {
894
- // eslint-disable-next-line no-console
895
905
  console.error('Shell.Panel: Do not pass both `open` and `defaultOpen`. Choose one.');
896
906
  }
897
907
  if (typeof size !== 'undefined' && typeof defaultSize !== 'undefined') {
898
- // eslint-disable-next-line no-console
899
908
  console.error('Shell.Panel: Do not pass both `size` and `defaultSize`. Choose one.');
900
909
  }
901
910
  }
@@ -924,14 +933,13 @@ const Panel = React.forwardRef<HTMLDivElement, PanelPublicProps>(
924
933
  } else {
925
934
  if (shell.panelMode !== 'collapsed') shell.setPanelMode('collapsed');
926
935
  }
927
- }, [open, shell.leftMode, shell.panelMode]);
936
+ }, [shell, open]);
928
937
 
929
938
  // Dev-only warning if switching controlled/uncontrolled between renders
930
939
  React.useEffect(() => {
931
940
  const isControlled = typeof open !== 'undefined';
932
941
  (Panel as any)._wasControlled = (Panel as any)._wasControlled ?? isControlled;
933
942
  if ((Panel as any)._wasControlled !== isControlled) {
934
- // eslint-disable-next-line no-console
935
943
  console.warn('Shell.Panel: Switching between controlled and uncontrolled `open` is not supported.');
936
944
  (Panel as any)._wasControlled = isControlled;
937
945
  }
@@ -1057,7 +1065,7 @@ const Panel = React.forwardRef<HTMLDivElement, PanelPublicProps>(
1057
1065
  localRef.current.style.setProperty('--panel-size', `${clamped}px`);
1058
1066
  emitSizeChange(clamped, { reason: 'controlled' });
1059
1067
  }
1060
- }, [size, minSize, maxSize, normalizeToPx]);
1068
+ }, [size, minSize, maxSize, normalizeToPx, emitSizeChange]);
1061
1069
 
1062
1070
  // Ensure Left container width is auto whenever Panel is expanded in fixed presentation
1063
1071
  React.useEffect(() => {
@@ -510,11 +510,15 @@
510
510
  .rt-SidebarContainer {
511
511
  &:where(.rt-r-size-1) {
512
512
  --sidebar-base-padding: var(--space-3);
513
- --sidebar-item-height: var(--space-5);
513
+ --sidebar-item-height: var(--space-6);
514
514
  }
515
515
  &:where(.rt-r-size-2) {
516
516
  --sidebar-base-padding: var(--space-4);
517
- --sidebar-item-height: var(--space-6);
517
+ --sidebar-item-height: var(--space-7);
518
+ }
519
+ &:where(.rt-r-size-3) {
520
+ --sidebar-base-padding: var(--space-4);
521
+ --sidebar-item-height: var(--space-8);
518
522
  }
519
523
  }
520
524
 
@@ -525,6 +529,7 @@
525
529
  --sidebar-item-padding-left: var(--base-menu-item-padding-left);
526
530
  --sidebar-item-padding-right: var(--base-menu-item-padding-right);
527
531
  --sidebar-item-padding-y: var(--base-menu-item-padding-y);
532
+ --base-menu-item-height: var(--space-6);
528
533
  --sidebar-item-height: var(--base-menu-item-height);
529
534
  }
530
535
  &:where(.rt-r-size-2) {
@@ -532,6 +537,15 @@
532
537
  --sidebar-item-padding-left: var(--base-menu-item-padding-left);
533
538
  --sidebar-item-padding-right: var(--base-menu-item-padding-right);
534
539
  --sidebar-item-padding-y: var(--base-menu-item-padding-y);
540
+ --base-menu-item-height: var(--space-7);
541
+ --sidebar-item-height: var(--base-menu-item-height);
542
+ }
543
+ &:where(.rt-r-size-3) {
544
+ --sidebar-content-padding: var(--base-menu-content-padding);
545
+ --sidebar-item-padding-left: var(--base-menu-item-padding-left);
546
+ --sidebar-item-padding-right: var(--base-menu-item-padding-right);
547
+ --sidebar-item-padding-y: var(--base-menu-item-padding-y);
548
+ --base-menu-item-height: var(--space-8);
535
549
  --sidebar-item-height: var(--base-menu-item-height);
536
550
  }
537
551
  }
@@ -548,8 +562,8 @@
548
562
 
549
563
  /* stylelint-disable-next-line selector-max-type */
550
564
  & :where(svg) {
551
- width: var(--content-icon-size-1);
552
- height: var(--content-icon-size-1);
565
+ width: var(--content-icon-size-2);
566
+ height: var(--content-icon-size-2);
553
567
  flex-shrink: 0;
554
568
  }
555
569
  }
@@ -574,11 +588,23 @@
574
588
 
575
589
  /* stylelint-disable-next-line selector-max-type */
576
590
  & :where(svg) {
577
- width: var(--content-icon-size-2);
578
- height: var(--content-icon-size-2);
591
+ width: var(--content-icon-size-3);
592
+ height: var(--content-icon-size-3);
579
593
  flex-shrink: 0;
580
594
  }
581
595
  }
596
+ /* stylelint-disable-next-line selector-max-specificity */
597
+ .rt-SidebarContent:where(.rt-r-size-3) {
598
+ /* stylelint-disable-next-line selector-max-specificity */
599
+ & :where(.rt-SidebarMenuButton) {
600
+ /* stylelint-disable-next-line selector-max-type, selector-max-specificity */
601
+ & :where(svg) {
602
+ width: var(--content-icon-size-3);
603
+ height: var(--content-icon-size-3);
604
+ flex-shrink: 0;
605
+ }
606
+ }
607
+ }
582
608
 
583
609
  /* Sub-trigger icon sizing - matches base menu exactly */
584
610
  & :where(.rt-BaseMenuSubTriggerIcon) {
@@ -8,7 +8,7 @@ const appearances = ['inherit', 'light', 'dark'] as const;
8
8
  const panelBackgrounds = ['solid', 'translucent'] as const;
9
9
  const materials = ['solid', 'translucent'] as const;
10
10
  const scalings = ['90%', '95%', '100%', '105%', '110%'] as const;
11
- const fontFamilies = ['sans', 'mono'] as const;
11
+ const fontFamilies = ['sans', 'mono', 'serif'] as const;
12
12
 
13
13
  const themePropDefs = {
14
14
  ...asChildPropDef,
@@ -13,10 +13,14 @@ export interface FontConfig {
13
13
  sans?: string;
14
14
  /** Monospace font stack for fontFamily="mono" */
15
15
  mono?: string;
16
+ /** Serif font stack for fontFamily="serif" */
17
+ serif?: string;
16
18
  /** Base Inter font replacement */
17
19
  inter?: string;
18
20
  /** Base JetBrains Mono font replacement */
19
21
  jetbrainsMono?: string;
22
+ /** Base Playfair Display font replacement */
23
+ playfairDisplay?: string;
20
24
  }
21
25
 
22
26
  /**
@@ -25,8 +29,10 @@ export interface FontConfig {
25
29
  export const FONT_CSS_VARIABLES = {
26
30
  sans: '--font-sans',
27
31
  mono: '--font-mono',
32
+ serif: '--font-serif',
28
33
  inter: '--font-inter',
29
34
  jetbrainsMono: '--font-jetbrains-mono',
35
+ playfairDisplay: '--font-playfair-display',
30
36
  defaultFamily: '--default-font-family',
31
37
  headingFamily: '--heading-font-family',
32
38
  strongFamily: '--strong-font-family',
@@ -39,8 +45,7 @@ export const FONT_CSS_VARIABLES = {
39
45
  export const FONT_STACKS = {
40
46
  // Sans-serif options
41
47
  inter: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
42
- system:
43
- "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
48
+ system: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
44
49
  poppins: "'Poppins', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif",
45
50
  openSans: "'Open Sans', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif",
46
51
 
@@ -49,6 +54,12 @@ export const FONT_STACKS = {
49
54
  firaCode: "'Fira Code', 'JetBrains Mono', 'Consolas', 'Liberation Mono', monospace",
50
55
  sourceCodePro: "'Source Code Pro', 'JetBrains Mono', 'Consolas', monospace",
51
56
  systemMono: "'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', 'Courier New', monospace",
57
+
58
+ // Serif options
59
+ playfair: "'Playfair Display', 'Times New Roman', 'Times', 'Georgia', 'Cambria', serif",
60
+ times: "'Times New Roman', 'Times', 'Georgia', 'Cambria', serif",
61
+ georgia: "'Georgia', 'Times New Roman', 'Times', serif",
62
+ lora: "'Lora', 'Times New Roman', 'Times', serif",
52
63
  } as const;
53
64
 
54
65
  /**
@@ -72,10 +83,7 @@ export const FONT_STACKS = {
72
83
  * });
73
84
  * ```
74
85
  */
75
- export function applyFontConfig(
76
- config: FontConfig,
77
- target: HTMLElement = document.documentElement,
78
- ): void {
86
+ export function applyFontConfig(config: FontConfig, target: HTMLElement = document.documentElement): void {
79
87
  const style = target.style;
80
88
 
81
89
  if (config.sans) {
@@ -86,6 +94,10 @@ export function applyFontConfig(
86
94
  style.setProperty(FONT_CSS_VARIABLES.mono, config.mono);
87
95
  }
88
96
 
97
+ if (config.serif) {
98
+ style.setProperty(FONT_CSS_VARIABLES.serif, config.serif);
99
+ }
100
+
89
101
  if (config.inter) {
90
102
  style.setProperty(FONT_CSS_VARIABLES.inter, config.inter);
91
103
  }
@@ -93,6 +105,10 @@ export function applyFontConfig(
93
105
  if (config.jetbrainsMono) {
94
106
  style.setProperty(FONT_CSS_VARIABLES.jetbrainsMono, config.jetbrainsMono);
95
107
  }
108
+
109
+ if (config.playfairDisplay) {
110
+ style.setProperty(FONT_CSS_VARIABLES.playfairDisplay, config.playfairDisplay);
111
+ }
96
112
  }
97
113
 
98
114
  /**
@@ -125,6 +141,10 @@ export function generateFontCSS(config: FontConfig): string {
125
141
  rules.push(` ${FONT_CSS_VARIABLES.mono}: ${config.mono};`);
126
142
  }
127
143
 
144
+ if (config.serif) {
145
+ rules.push(` ${FONT_CSS_VARIABLES.serif}: ${config.serif};`);
146
+ }
147
+
128
148
  if (config.inter) {
129
149
  rules.push(` ${FONT_CSS_VARIABLES.inter}: ${config.inter};`);
130
150
  }
@@ -133,6 +153,10 @@ export function generateFontCSS(config: FontConfig): string {
133
153
  rules.push(` ${FONT_CSS_VARIABLES.jetbrainsMono}: ${config.jetbrainsMono};`);
134
154
  }
135
155
 
156
+ if (config.playfairDisplay) {
157
+ rules.push(` ${FONT_CSS_VARIABLES.playfairDisplay}: ${config.playfairDisplay};`);
158
+ }
159
+
136
160
  rules.push('}');
137
161
 
138
162
  return rules.join('\n');
@@ -147,8 +171,10 @@ export function resetFonts(target: HTMLElement = document.documentElement): void
147
171
  // Remove custom font variables to fall back to defaults
148
172
  style.removeProperty(FONT_CSS_VARIABLES.sans);
149
173
  style.removeProperty(FONT_CSS_VARIABLES.mono);
174
+ style.removeProperty(FONT_CSS_VARIABLES.serif);
150
175
  style.removeProperty(FONT_CSS_VARIABLES.inter);
151
176
  style.removeProperty(FONT_CSS_VARIABLES.jetbrainsMono);
177
+ style.removeProperty(FONT_CSS_VARIABLES.playfairDisplay);
152
178
  }
153
179
 
154
180
  /**
@@ -160,8 +186,9 @@ export function getCurrentFontConfig(target: HTMLElement = document.documentElem
160
186
  return {
161
187
  sans: computedStyle.getPropertyValue(FONT_CSS_VARIABLES.sans).trim() || undefined,
162
188
  mono: computedStyle.getPropertyValue(FONT_CSS_VARIABLES.mono).trim() || undefined,
189
+ serif: computedStyle.getPropertyValue(FONT_CSS_VARIABLES.serif).trim() || undefined,
163
190
  inter: computedStyle.getPropertyValue(FONT_CSS_VARIABLES.inter).trim() || undefined,
164
- jetbrainsMono:
165
- computedStyle.getPropertyValue(FONT_CSS_VARIABLES.jetbrainsMono).trim() || undefined,
191
+ jetbrainsMono: computedStyle.getPropertyValue(FONT_CSS_VARIABLES.jetbrainsMono).trim() || undefined,
192
+ playfairDisplay: computedStyle.getPropertyValue(FONT_CSS_VARIABLES.playfairDisplay).trim() || undefined,
166
193
  };
167
194
  }
@@ -1,23 +1,19 @@
1
- /* Inter and JetBrains Mono from Google Fonts */
1
+ /* Inter, JetBrains Mono, and Playfair Display from Google Fonts */
2
2
  @import url('https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,100..900;1,100..900&display=swap');
3
3
  @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');
4
+ @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&display=swap');
4
5
 
5
6
  /* Font Variables - Customize these to change fonts throughout your app */
6
7
  :root {
7
- /* Base font definitions - override these in your CSS to customize fonts */
8
- --font-inter:
9
- 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
10
- sans-serif;
11
- --font-jetbrains-mono:
12
- 'JetBrains Mono', 'Fira Code', 'Consolas', 'Liberation Mono', 'Courier New', monospace;
8
+ /* Base font definitions - these are the actual font stacks */
9
+ --font-inter: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
10
+ --font-jetbrains-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', 'Liberation Mono', 'Courier New', monospace;
11
+ --font-playfair-display: 'Playfair Display', 'Times New Roman', 'Times', 'Georgia', 'Cambria', serif;
13
12
 
14
- /* Primary font variables - these map to theme fontFamily values */
15
- --font-general-sans: var(--font-inter); /* Used when fontFamily="sans" */
16
- --font-inter-mono: var(--font-jetbrains-mono); /* Used for code elements */
17
-
18
- /* Tailwind-compatible aliases - override these to change theme fonts */
19
- --font-sans: var(--font-inter); /* Theme fontFamily="sans" uses this */
20
- --font-mono: var(--font-jetbrains-mono); /* Theme fontFamily="mono" uses this */
13
+ /* Theme font family overrides - change these to customize fonts globally */
14
+ --font-sans: var(--font-inter); /* Override this for custom sans-serif */
15
+ --font-mono: var(--font-jetbrains-mono); /* Override this for custom monospace */
16
+ --font-serif: var(--font-playfair-display); /* Override this for custom serif */
21
17
 
22
18
  /* Force proper font weight rendering */
23
19
  font-synthesis: none; /* Prevent browser from synthesizing weights */
@@ -26,7 +22,7 @@
26
22
  /* Radix Themes font weight enforcement */
27
23
  .radix-themes {
28
24
  font-synthesis: none;
29
- font-family: var(--font-inter);
25
+ font-family: var(--default-font-family);
30
26
  }
31
27
 
32
28
  /* System font fallback for critical loading scenarios */
@@ -44,16 +44,15 @@
44
44
  /* default values */
45
45
 
46
46
  --default-font-family:
47
- var(--font-inter, 'Inter'), -apple-system, BlinkMacSystemFont, 'Segoe UI (Custom)', Roboto,
48
- 'Helvetica Neue', 'Open Sans (Custom)', system-ui, sans-serif, 'Apple Color Emoji',
47
+ var(--font-sans, var(--font-inter, 'Inter')), -apple-system, BlinkMacSystemFont, 'Segoe UI (Custom)', Roboto, 'Helvetica Neue', 'Open Sans (Custom)', system-ui, sans-serif, 'Apple Color Emoji',
49
48
  'Segoe UI Emoji';
50
49
 
51
50
  /* Font family overrides based on theme data attribute */
52
51
  --default-font-family-sans:
53
- var(--font-inter, 'Inter'), -apple-system, BlinkMacSystemFont, 'Segoe UI (Custom)', Roboto,
54
- 'Helvetica Neue', 'Open Sans (Custom)', system-ui, sans-serif, 'Apple Color Emoji',
52
+ var(--font-sans, var(--font-inter, 'Inter')), -apple-system, BlinkMacSystemFont, 'Segoe UI (Custom)', Roboto, 'Helvetica Neue', 'Open Sans (Custom)', system-ui, sans-serif, 'Apple Color Emoji',
55
53
  'Segoe UI Emoji';
56
54
  --default-font-family-mono: var(--font-mono);
55
+ --default-font-family-serif: var(--font-serif);
57
56
  --default-font-size: var(--font-size-3); /* Same size used for `<Text size="3">` */
58
57
  --default-font-style: normal;
59
58
  --default-font-weight: var(--font-weight-regular);
@@ -84,9 +83,7 @@
84
83
 
85
84
  /* Code */
86
85
 
87
- --code-font-family:
88
- var(--font-inter-mono, 'JetBrains Mono'), 'Menlo', 'Consolas (Custom)',
89
- 'Bitstream Vera Sans Mono', monospace, 'Apple Color Emoji', 'Segoe UI Emoji';
86
+ --code-font-family: var(--font-mono, var(--font-jetbrains-mono, 'JetBrains Mono')), 'Menlo', 'Consolas (Custom)', 'Bitstream Vera Sans Mono', monospace, 'Apple Color Emoji', 'Segoe UI Emoji';
90
87
  --code-font-size-adjust: 0.95;
91
88
  --code-font-style: normal;
92
89
  --code-font-weight: inherit;
@@ -327,3 +324,16 @@
327
324
  --heading-font-family: var(--default-font-family-mono);
328
325
  --strong-font-family: var(--default-font-family-mono);
329
326
  }
327
+
328
+ [data-font-family='serif'] {
329
+ /* Map serif directly to --font-serif to avoid resolution issues */
330
+ --default-font-family: var(--font-serif);
331
+ --heading-font-family: var(--font-serif);
332
+ --strong-font-family: var(--font-serif);
333
+ }
334
+
335
+ /* Ensure serif font takes precedence over .radix-themes */
336
+ /* stylelint-disable-next-line selector-max-specificity */
337
+ .radix-themes[data-font-family='serif'] {
338
+ font-family: var(--font-serif) !important;
339
+ }