@newtonedev/components 0.1.5 → 0.1.7

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 (69) hide show
  1. package/dist/composites/actions/Button/Button.d.ts.map +1 -1
  2. package/dist/composites/actions/Button/Button.styles.d.ts +3 -1
  3. package/dist/composites/actions/Button/Button.styles.d.ts.map +1 -1
  4. package/dist/index.cjs +603 -249
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.ts +6 -5
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +599 -251
  9. package/dist/index.js.map +1 -1
  10. package/dist/primitives/Frame/Frame.d.ts +2 -3
  11. package/dist/primitives/Frame/Frame.d.ts.map +1 -1
  12. package/dist/primitives/Frame/Frame.types.d.ts +4 -15
  13. package/dist/primitives/Frame/Frame.types.d.ts.map +1 -1
  14. package/dist/primitives/Icon/Icon.d.ts +1 -1
  15. package/dist/primitives/Icon/Icon.d.ts.map +1 -1
  16. package/dist/primitives/Icon/Icon.types.d.ts +7 -12
  17. package/dist/primitives/Icon/Icon.types.d.ts.map +1 -1
  18. package/dist/primitives/Text/Text.d.ts.map +1 -1
  19. package/dist/primitives/Text/Text.types.d.ts +9 -4
  20. package/dist/primitives/Text/Text.types.d.ts.map +1 -1
  21. package/dist/primitives/Wrapper/Wrapper.d.ts +1 -1
  22. package/dist/primitives/Wrapper/Wrapper.types.d.ts +1 -1
  23. package/dist/registry/icons.d.ts +7 -0
  24. package/dist/registry/icons.d.ts.map +1 -0
  25. package/dist/registry/index.d.ts +2 -0
  26. package/dist/registry/index.d.ts.map +1 -1
  27. package/dist/registry/registry.d.ts.map +1 -1
  28. package/dist/registry/types.d.ts +1 -1
  29. package/dist/registry/types.d.ts.map +1 -1
  30. package/dist/theme/FrameContext.d.ts +7 -5
  31. package/dist/theme/FrameContext.d.ts.map +1 -1
  32. package/dist/theme/NewtoneProvider.d.ts +5 -6
  33. package/dist/theme/NewtoneProvider.d.ts.map +1 -1
  34. package/dist/theme/defaults.d.ts.map +1 -1
  35. package/dist/theme/types.d.ts +38 -24
  36. package/dist/theme/types.d.ts.map +1 -1
  37. package/dist/tokens/computeTokens.d.ts +82 -7
  38. package/dist/tokens/computeTokens.d.ts.map +1 -1
  39. package/dist/tokens/types.d.ts +58 -16
  40. package/dist/tokens/types.d.ts.map +1 -1
  41. package/dist/tokens/useTokens.d.ts +2 -23
  42. package/dist/tokens/useTokens.d.ts.map +1 -1
  43. package/package.json +1 -1
  44. package/src/composites/actions/Button/Button.styles.ts +53 -80
  45. package/src/composites/actions/Button/Button.tsx +6 -2
  46. package/src/composites/form-controls/Select/SelectOption.tsx +2 -2
  47. package/src/composites/form-controls/Toggle/Toggle.styles.ts +1 -1
  48. package/src/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.styles.ts +1 -1
  49. package/src/composites/range-inputs/Slider/Slider.styles.ts +2 -2
  50. package/src/index.ts +13 -4
  51. package/src/primitives/Frame/Frame.tsx +10 -18
  52. package/src/primitives/Frame/Frame.types.ts +5 -17
  53. package/src/primitives/Icon/Icon.tsx +4 -6
  54. package/src/primitives/Icon/Icon.types.ts +7 -14
  55. package/src/primitives/Text/Text.tsx +18 -8
  56. package/src/primitives/Text/Text.types.ts +9 -4
  57. package/src/primitives/Wrapper/Wrapper.tsx +1 -1
  58. package/src/primitives/Wrapper/Wrapper.types.ts +1 -1
  59. package/src/registry/icons.ts +111 -0
  60. package/src/registry/index.ts +3 -0
  61. package/src/registry/registry.ts +40 -24
  62. package/src/registry/types.ts +1 -1
  63. package/src/theme/FrameContext.tsx +7 -5
  64. package/src/theme/NewtoneProvider.tsx +5 -10
  65. package/src/theme/defaults.ts +0 -9
  66. package/src/theme/types.ts +53 -26
  67. package/src/tokens/computeTokens.ts +338 -116
  68. package/src/tokens/types.ts +74 -16
  69. package/src/tokens/useTokens.ts +16 -33
@@ -1,4 +1,42 @@
1
1
  import type { ColorResult } from 'newtone';
2
+ /**
3
+ * Complete token set for a non-neutral palette (accent, success, warning, error).
4
+ *
5
+ * Fill tokens use the palette's key NV position (user-chosen or WCAG auto-derived).
6
+ * Surface tokens use standard positions from PaletteDefaults, rendered in the palette's hue/saturation.
7
+ */
8
+ export interface PaletteTokens {
9
+ /** Key color at the palette's keyNormalizedValue (used for primary Button fills, badges, indicators) */
10
+ readonly fill: ColorResult;
11
+ /** Key color shifted for hover state */
12
+ readonly fillHover: ColorResult;
13
+ /** Key color shifted for pressed/active state */
14
+ readonly fillActive: ColorResult;
15
+ /** High-contrast color for text/icons on top of fill (auto: dark text on light fills, light on dark) */
16
+ readonly onFill: ColorResult;
17
+ /** Palette-tinted background at current elevation */
18
+ readonly background: ColorResult;
19
+ /** Palette-tinted elevated surface */
20
+ readonly backgroundElevated: ColorResult;
21
+ /** Palette-tinted sunken surface */
22
+ readonly backgroundSunken: ColorResult;
23
+ /** Interactive element background within palette surface */
24
+ readonly backgroundInteractive: ColorResult;
25
+ /** Hover state for interactive elements within palette surface */
26
+ readonly backgroundInteractiveHover: ColorResult;
27
+ /** Pressed/active state for interactive elements within palette surface */
28
+ readonly backgroundInteractiveActive: ColorResult;
29
+ /** High-contrast palette-colored text */
30
+ readonly textPrimary: ColorResult;
31
+ /** Medium-contrast palette-colored text */
32
+ readonly textSecondary: ColorResult;
33
+ /** Low-contrast palette-colored text */
34
+ readonly textTertiary: ColorResult;
35
+ /** Disabled palette-colored text */
36
+ readonly textDisabled: ColorResult;
37
+ /** Palette-colored border */
38
+ readonly border: ColorResult;
39
+ }
2
40
  /**
3
41
  * Resolved design tokens for a specific mode/theme/elevation combination
4
42
  */
@@ -11,32 +49,36 @@ export interface ResolvedTokens {
11
49
  readonly backgroundSunken: ColorResult;
12
50
  /**
13
51
  * Background color for interactive components with neutral backgrounds.
14
- * Uses a fixed -0.035 NV (luminosity) offset from current background to ensure
52
+ * Uses a fixed NV offset from current background to ensure
15
53
  * consistent visual contrast across all elevations (-2 to 2).
16
54
  *
17
- * Use for: Button (neutral primary), and future components with neutral filled backgrounds.
55
+ * Use for: Button (neutral primary enabled), and future components with neutral filled backgrounds.
18
56
  * Don't use for: Semantic variants (accent/success/error/warning), transparent backgrounds,
19
57
  * or primitives (Frame/Wrapper/Text/Icon already handle elevation correctly).
20
58
  */
21
59
  readonly backgroundInteractive: ColorResult;
22
- /** Primary text color (high contrast for body text) */
60
+ /** Hover state for neutral interactive components (enabled + hoverShift) */
61
+ readonly backgroundInteractiveHover: ColorResult;
62
+ /** Pressed/active state for neutral interactive components (enabled + activeShift) */
63
+ readonly backgroundInteractiveActive: ColorResult;
64
+ /** Primary text color (high contrast for body text, 4.5:1 default) */
23
65
  readonly textPrimary: ColorResult;
24
- /** Secondary text color (lower contrast for captions, labels) */
66
+ /** Secondary text color (lower contrast for captions, labels, 3.0:1 default) */
25
67
  readonly textSecondary: ColorResult;
26
- /** Interactive element color (buttons, links) */
27
- readonly interactive: ColorResult;
28
- /** Interactive element hover state */
29
- readonly interactiveHover: ColorResult;
30
- /** Interactive element active/pressed state */
31
- readonly interactiveActive: ColorResult;
68
+ /** Tertiary text color (hints, placeholders, 2.0:1 default) */
69
+ readonly textTertiary: ColorResult;
70
+ /** Disabled text color (disabled elements, 1.5:1 default) */
71
+ readonly textDisabled: ColorResult;
32
72
  /** Border color for subtle separators */
33
73
  readonly border: ColorResult;
34
- /** Success state color (from success palette, index 2) */
35
- readonly success: ColorResult;
36
- /** Warning state color (from warning palette, index 3) */
37
- readonly warning: ColorResult;
38
- /** Error/destructive state color (from error palette, index 4) */
39
- readonly error: ColorResult;
74
+ /** Accent palette tokens (palette index 1) — interactive elements, brand color */
75
+ readonly accent: PaletteTokens;
76
+ /** Success palette tokens (palette index 2) — positive state indicators */
77
+ readonly success: PaletteTokens;
78
+ /** Warning palette tokens (palette index 3) — caution state indicators */
79
+ readonly warning: PaletteTokens;
80
+ /** Error palette tokens (palette index 4) — destructive/error state indicators */
81
+ readonly error: PaletteTokens;
40
82
  /** Spacing tokens for paddings, gaps, and margins.
41
83
  * Token names represent pixel values at Medium (8px) spacing preset.
42
84
  * Actual values scale based on the selected spacing preset. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tokens/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tokens/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAE5B,wGAAwG;IACxG,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC,iDAAiD;IACjD,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;IACjC,wGAAwG;IACxG,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAG7B,qDAAqD;IACrD,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;IACjC,sCAAsC;IACtC,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC;IACzC,oCAAoC;IACpC,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC;IAGvC,4DAA4D;IAC5D,QAAQ,CAAC,qBAAqB,EAAE,WAAW,CAAC;IAC5C,kEAAkE;IAClE,QAAQ,CAAC,0BAA0B,EAAE,WAAW,CAAC;IACjD,2EAA2E;IAC3E,QAAQ,CAAC,2BAA2B,EAAE,WAAW,CAAC;IAGlD,yCAAyC;IACzC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,2CAA2C;IAC3C,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC;IACpC,wCAAwC;IACxC,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;IACnC,oCAAoC;IACpC,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;IAGnC,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAG7B,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC;IACzC,iEAAiE;IACjE,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC;IACvC;;;;;;;;OAQG;IACH,QAAQ,CAAC,qBAAqB,EAAE,WAAW,CAAC;IAC5C,4EAA4E;IAC5E,QAAQ,CAAC,0BAA0B,EAAE,WAAW,CAAC;IACjD,sFAAsF;IACtF,QAAQ,CAAC,2BAA2B,EAAE,WAAW,CAAC;IAClD,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,gFAAgF;IAChF,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC;IACpC,+DAA+D;IAC/D,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;IACnC,6DAA6D;IAC7D,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;IACnC,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAI7B,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAE9B;;mEAE+D;IAC/D,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,mDAAmD;IACnD,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC;KACpB,CAAC;IACF,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE;QACnB,QAAQ,CAAC,KAAK,EAAE;YACd,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;YACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;SAC1B,CAAC;QACF,QAAQ,CAAC,IAAI,EAAE;YACb,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;YACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;YACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;YACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;YACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;YACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;SACtB,CAAC;QACF,QAAQ,CAAC,UAAU,EAAE;YACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;YACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;SAC1B,CAAC;QACF,QAAQ,CAAC,MAAM,EAAE;YACf,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;YACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;YACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;YAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;SACvB,CAAC;KACH,CAAC;IACF,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC;QACnD,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;QACzD,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;KAC/B,CAAC;CACH"}
@@ -15,33 +15,12 @@ export interface UseTokensResult extends ResolvedTokens {
15
15
  * 2. FrameContext values (from nearest parent Frame) are used when elevation is omitted
16
16
  * 3. Falls back to NewtoneProvider theme + elevation 1
17
17
  *
18
- * Theme always reads from FrameContext if present, falling back to NewtoneProvider.
18
+ * When inside a Frame and no explicit elevation override is given, reuses the
19
+ * Frame's pre-computed tokens to avoid redundant computeTokens calls.
19
20
  *
20
21
  * @param elevation - Elevation level (0=sunken, 1=default, 2=elevated).
21
22
  * When omitted, reads from FrameContext or defaults to 1.
22
23
  * @returns Resolved design tokens with all necessary colors + resolved elevation
23
- *
24
- * @example
25
- * ```tsx
26
- * // Inside a <Frame theme="primary" elevation={1}>:
27
- * function MyComponent() {
28
- * const tokens = useTokens(); // Gets primary theme, elevation 2 (mapped from Frame's 1)
29
- * return (
30
- * <View style={{ backgroundColor: srgbToHex(tokens.background.srgb) }} />
31
- * );
32
- * }
33
- * ```
34
- *
35
- * @example
36
- * ```tsx
37
- * // Elevation-aware component:
38
- * function ElevationAwareButton() {
39
- * const tokens = useTokens();
40
- * // Use tokens.elevation to make color decisions
41
- * const bg = tokens.elevation === 2 ? tokens.background : tokens.backgroundSunken;
42
- * return <View style={{ backgroundColor: srgbToHex(bg.srgb) }} />;
43
- * }
44
- * ```
45
24
  */
46
25
  export declare function useTokens(elevation?: ElevationLevel): UseTokensResult;
47
26
  //# sourceMappingURL=useTokens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useTokens.d.ts","sourceRoot":"","sources":["../../src/tokens/useTokens.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,SAAS,EAAE,cAAc,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,cAAc,GAAG,eAAe,CA2BrE"}
1
+ {"version":3,"file":"useTokens.d.ts","sourceRoot":"","sources":["../../src/tokens/useTokens.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,SAAS,EAAE,cAAc,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,cAAc,GAAG,eAAe,CA+BrE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newtonedev/components",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "React + React Native Web component library for Newtone",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,5 +1,6 @@
1
1
  import { srgbToHex } from 'newtone';
2
2
  import type { UseTokensResult } from '../../../tokens/useTokens';
3
+ import type { PaletteTokens } from '../../../tokens/types';
3
4
  import type { ButtonVariant, ButtonSemantic, ButtonSize } from './Button.types';
4
5
  import type { TextSize } from '../../../primitives/Text/Text.types';
5
6
 
@@ -9,6 +10,7 @@ import type { TextSize } from '../../../primitives/Text/Text.types';
9
10
  export interface ButtonConfig {
10
11
  variantColors: {
11
12
  bg: string;
13
+ hoveredBg: string;
12
14
  pressedBg: string;
13
15
  textColor: string;
14
16
  iconColor: string;
@@ -34,17 +36,6 @@ export interface ButtonPadding {
34
36
  paddingBottom: number;
35
37
  }
36
38
 
37
- /**
38
- * Add opacity to a hex color string.
39
- * @param hexColor - Hex color string (e.g., "#ff0000")
40
- * @param opacity - Opacity value from 0 to 1
41
- * @returns Hex color with alpha channel
42
- */
43
- function withOpacity(hexColor: string, opacity: number): string {
44
- const alpha = Math.round(opacity * 255).toString(16).padStart(2, '0');
45
- return `${hexColor}${alpha}`;
46
- }
47
-
48
39
  /**
49
40
  * Compute asymmetric button padding based on icon/text presence.
50
41
  *
@@ -122,16 +113,17 @@ export function computeButtonPadding(
122
113
  }
123
114
 
124
115
  /**
125
- * Get elevation-aware background color for neutral primary button.
126
- * Uses backgroundInteractive token for consistent contrast across all elevations.
127
- *
128
- * @param tokens - Resolved tokens for current elevation
129
- * @returns Background color hex string
116
+ * Resolve the PaletteTokens for a given semantic.
117
+ * Returns undefined for 'neutral' (handled separately).
130
118
  */
131
- function getNeutralPrimaryBg(tokens: UseTokensResult): string {
132
- // Use the new backgroundInteractive token which maintains consistent
133
- // contrast (-0.035 NV offset) across all elevations
134
- return srgbToHex(tokens.backgroundInteractive.srgb);
119
+ function getPaletteTokens(semantic: ButtonSemantic, tokens: UseTokensResult): PaletteTokens | undefined {
120
+ switch (semantic) {
121
+ case 'accent': return tokens.accent;
122
+ case 'success': return tokens.success;
123
+ case 'error': return tokens.error;
124
+ case 'warning': return tokens.warning;
125
+ default: return undefined;
126
+ }
135
127
  }
136
128
 
137
129
  /**
@@ -141,7 +133,8 @@ function getNeutralPrimaryBg(tokens: UseTokensResult): string {
141
133
  * Layout concerns (flexbox, spacing, alignment) are handled by Wrapper primitive.
142
134
  * Typography concerns (font, size, weight) are handled by Text primitive.
143
135
  *
144
- * Now elevation-aware: neutral primary uses backgroundInteractive for consistent contrast.
136
+ * Elevation-aware: neutral primary uses backgroundInteractive for consistent contrast.
137
+ * Semantic variants use proper PaletteTokens — no opacity hacks.
145
138
  *
146
139
  * @param variant - Button type (primary, secondary, tertiary)
147
140
  * @param semantic - Button semantic meaning (neutral, accent, success, error, warning)
@@ -226,10 +219,12 @@ function getVariantColors(
226
219
  // Disabled state overrides for all variants
227
220
  if (disabled) {
228
221
  const baseColors = getVariantColorsForState(variant, semantic, tokens);
222
+ const disabledBg = srgbToHex(tokens.backgroundSunken.srgb);
229
223
  return {
230
224
  ...baseColors,
231
- bg: srgbToHex(tokens.backgroundSunken.srgb),
232
- pressedBg: srgbToHex(tokens.backgroundSunken.srgb),
225
+ bg: disabledBg,
226
+ hoveredBg: disabledBg,
227
+ pressedBg: disabledBg,
233
228
  textColor: srgbToHex(tokens.textSecondary.srgb),
234
229
  iconColor: srgbToHex(tokens.textSecondary.srgb),
235
230
  };
@@ -241,74 +236,50 @@ function getVariantColors(
241
236
  /**
242
237
  * Get variant colors for non-disabled state.
243
238
  * Implements 3 types × 5 semantics = 15 combinations.
239
+ * Uses proper PaletteTokens for all semantic variants — no opacity hacks.
244
240
  */
245
241
  function getVariantColorsForState(
246
242
  variant: ButtonVariant,
247
243
  semantic: ButtonSemantic,
248
244
  tokens: UseTokensResult
249
245
  ) {
250
- // Get semantic color
251
- const getSemanticColor = (): string => {
252
- switch (semantic) {
253
- case 'accent':
254
- return srgbToHex(tokens.interactive.srgb);
255
- case 'success':
256
- return srgbToHex(tokens.success.srgb);
257
- case 'error':
258
- return srgbToHex(tokens.error.srgb);
259
- case 'warning':
260
- return srgbToHex(tokens.warning.srgb);
261
- default:
262
- return srgbToHex(tokens.textPrimary.srgb);
263
- }
264
- };
246
+ const paletteTokens = getPaletteTokens(semantic, tokens);
265
247
 
266
248
  // PRIMARY VARIANT: Filled background
267
249
  if (variant === 'primary') {
268
250
  if (semantic === 'neutral') {
269
- // Neutral primary - uses backgroundInteractive for consistent contrast across elevations
270
- const bg = getNeutralPrimaryBg(tokens);
251
+ // Neutral primary - uses backgroundInteractive tokens for consistent contrast across elevations
271
252
  return {
272
- bg,
273
- pressedBg: withOpacity(bg, 0.8), // Slightly darker on press
253
+ bg: srgbToHex(tokens.backgroundInteractive.srgb),
254
+ hoveredBg: srgbToHex(tokens.backgroundInteractiveHover.srgb),
255
+ pressedBg: srgbToHex(tokens.backgroundInteractiveActive.srgb),
274
256
  textColor: srgbToHex(tokens.textPrimary.srgb),
275
257
  iconColor: srgbToHex(tokens.textPrimary.srgb),
276
258
  borderWidth: 1,
277
- borderColor: 'transparent', // Invisible border for consistent sizing
278
- };
279
- }
280
-
281
- if (semantic === 'accent') {
282
- // Accent primary = old primary (interactive bg, contrast text)
283
- return {
284
- bg: srgbToHex(tokens.interactive.srgb),
285
- pressedBg: srgbToHex(tokens.interactiveActive.srgb),
286
- textColor: srgbToHex(tokens.background.srgb), // Contrast inversion
287
- iconColor: srgbToHex(tokens.background.srgb),
288
- borderWidth: 1,
289
- borderColor: 'transparent', // Invisible border for consistent sizing
259
+ borderColor: 'transparent',
290
260
  };
291
261
  }
292
262
 
293
- // Semantic primary (success, error, warning)
294
- const semanticColor = getSemanticColor();
263
+ // Semantic primary (accent, success, error, warning) — uses palette fill tokens
295
264
  return {
296
- bg: semanticColor,
297
- pressedBg: withOpacity(semanticColor, 0.8), // Darken on press
298
- textColor: srgbToHex(tokens.background.srgb), // Contrast text
299
- iconColor: srgbToHex(tokens.background.srgb),
265
+ bg: srgbToHex(paletteTokens!.fill.srgb),
266
+ hoveredBg: srgbToHex(paletteTokens!.fillHover.srgb),
267
+ pressedBg: srgbToHex(paletteTokens!.fillActive.srgb),
268
+ textColor: srgbToHex(paletteTokens!.onFill.srgb),
269
+ iconColor: srgbToHex(paletteTokens!.onFill.srgb),
300
270
  borderWidth: 1,
301
- borderColor: 'transparent', // Invisible border for consistent sizing
271
+ borderColor: 'transparent',
302
272
  };
303
273
  }
304
274
 
305
275
  // SECONDARY VARIANT: Outlined (border + subtle background for non-neutral)
306
276
  if (variant === 'secondary') {
307
277
  if (semantic === 'neutral') {
308
- // Neutral secondary = old outline (transparent bg)
278
+ // Shifted action scale: transparent 01 (hover) → 02 (pressed)
309
279
  return {
310
280
  bg: 'transparent',
311
- pressedBg: srgbToHex(tokens.backgroundSunken.srgb),
281
+ hoveredBg: srgbToHex(tokens.backgroundInteractive.srgb),
282
+ pressedBg: srgbToHex(tokens.backgroundInteractiveHover.srgb),
312
283
  textColor: srgbToHex(tokens.textPrimary.srgb),
313
284
  iconColor: srgbToHex(tokens.textPrimary.srgb),
314
285
  borderWidth: 1,
@@ -316,47 +287,49 @@ function getVariantColorsForState(
316
287
  };
317
288
  }
318
289
 
319
- // Semantic secondary (accent, success, error, warning) - light bg, NO visible border
320
- const semanticColor = getSemanticColor();
290
+ // Semantic secondary uses palette surface tokens for subtle bg
321
291
  return {
322
- bg: withOpacity(semanticColor, 0.1), // Light background tint
323
- pressedBg: withOpacity(semanticColor, 0.15), // Slightly darker on press
324
- textColor: semanticColor,
325
- iconColor: semanticColor,
292
+ bg: srgbToHex(paletteTokens!.background.srgb),
293
+ hoveredBg: srgbToHex(paletteTokens!.backgroundInteractive.srgb),
294
+ pressedBg: srgbToHex(paletteTokens!.backgroundInteractiveHover.srgb),
295
+ textColor: srgbToHex(paletteTokens!.fill.srgb),
296
+ iconColor: srgbToHex(paletteTokens!.fill.srgb),
326
297
  borderWidth: 1,
327
- borderColor: 'transparent', // Invisible border for consistent sizing
298
+ borderColor: 'transparent',
328
299
  };
329
300
  }
330
301
 
331
302
  // TERTIARY VARIANT: Ghost (text-only, no visible border)
332
303
  if (variant === 'tertiary') {
333
304
  if (semantic === 'neutral') {
334
- // Neutral tertiary = old ghost
305
+ // Shifted action scale: transparent → 01 (hover) → 02 (pressed)
335
306
  return {
336
307
  bg: 'transparent',
337
- pressedBg: srgbToHex(tokens.backgroundSunken.srgb),
308
+ hoveredBg: srgbToHex(tokens.backgroundInteractive.srgb),
309
+ pressedBg: srgbToHex(tokens.backgroundInteractiveHover.srgb),
338
310
  textColor: srgbToHex(tokens.textPrimary.srgb),
339
311
  iconColor: srgbToHex(tokens.textPrimary.srgb),
340
312
  borderWidth: 1,
341
- borderColor: 'transparent', // Invisible border for consistent sizing
313
+ borderColor: 'transparent',
342
314
  };
343
315
  }
344
316
 
345
- // Semantic tertiary (accent, success, error, warning)
346
- const semanticColor = getSemanticColor();
317
+ // Semantic tertiary uses palette surface tokens for hover/pressed
347
318
  return {
348
319
  bg: 'transparent',
349
- pressedBg: withOpacity(semanticColor, 0.1), // Subtle background tint
350
- textColor: semanticColor,
351
- iconColor: semanticColor,
320
+ hoveredBg: srgbToHex(paletteTokens!.background.srgb),
321
+ pressedBg: srgbToHex(paletteTokens!.backgroundInteractive.srgb),
322
+ textColor: srgbToHex(paletteTokens!.fill.srgb),
323
+ iconColor: srgbToHex(paletteTokens!.fill.srgb),
352
324
  borderWidth: 1,
353
- borderColor: 'transparent', // Invisible border for consistent sizing
325
+ borderColor: 'transparent',
354
326
  };
355
327
  }
356
328
 
357
329
  // Fallback (should never reach here with proper types)
358
330
  return {
359
331
  bg: 'transparent',
332
+ hoveredBg: 'transparent',
360
333
  pressedBg: 'transparent',
361
334
  textColor: srgbToHex(tokens.textPrimary.srgb),
362
335
  iconColor: srgbToHex(tokens.textPrimary.srgb),
@@ -70,7 +70,7 @@ export function Button({
70
70
 
71
71
  return (
72
72
  <Pressable disabled={disabled} {...pressableProps}>
73
- {({ pressed }) => (
73
+ {({ pressed, hovered }: { pressed: boolean; hovered?: boolean }) => (
74
74
  // Wrapper handles layout: direction, gap, alignment (padding via style)
75
75
  <Wrapper
76
76
  direction="horizontal"
@@ -80,7 +80,11 @@ export function Button({
80
80
  style={[
81
81
  {
82
82
  ...padding, // Asymmetric horizontal padding for text optical balance
83
- backgroundColor: pressed && !disabled ? variantColors.pressedBg : variantColors.bg,
83
+ backgroundColor: pressed && !disabled
84
+ ? variantColors.pressedBg
85
+ : hovered && !disabled
86
+ ? variantColors.hoveredBg
87
+ : variantColors.bg,
84
88
  borderRadius: sizeTokens.borderRadius,
85
89
  borderWidth: variantColors.borderWidth, // Always 1 for consistent sizing
86
90
  borderColor: variantColors.borderColor || 'transparent',
@@ -80,7 +80,7 @@ export function SelectOptionRow({
80
80
  },
81
81
  isSelected && {
82
82
  fontWeight: tokens.typography.weight.semibold as any,
83
- color: srgbToHex(tokens.interactive.srgb),
83
+ color: srgbToHex(tokens.accent.fill.srgb),
84
84
  },
85
85
  option.disabled && {
86
86
  color: srgbToHex(tokens.textSecondary.srgb),
@@ -95,7 +95,7 @@ export function SelectOptionRow({
95
95
  <Icon
96
96
  name="check"
97
97
  size={fontSize}
98
- color={srgbToHex(tokens.interactive.srgb)}
98
+ color={srgbToHex(tokens.accent.fill.srgb)}
99
99
  />
100
100
  </View>
101
101
  )}
@@ -30,7 +30,7 @@ export function getToggleStyles(
30
30
  height: TRACK_HEIGHT,
31
31
  borderRadius: TRACK_HEIGHT / 2,
32
32
  backgroundColor: value
33
- ? srgbToHex(tokens.interactive.srgb)
33
+ ? srgbToHex(tokens.accent.fill.srgb)
34
34
  : srgbToHex(tokens.border.srgb),
35
35
  justifyContent: 'center',
36
36
  paddingHorizontal: THUMB_OFFSET,
@@ -52,7 +52,7 @@ export function getColorScaleSliderStyles(tokens: ResolvedTokens, disabled: bool
52
52
  fontFamily: tokens.typography.fonts.default,
53
53
  fontSize: tokens.typography.size.xs,
54
54
  fontWeight: tokens.typography.weight.medium as any,
55
- color: srgbToHex(tokens.error.srgb),
55
+ color: srgbToHex(tokens.error.fill.srgb),
56
56
  },
57
57
  });
58
58
  }
@@ -60,14 +60,14 @@ export function getSliderStyles(tokens: ResolvedTokens, disabled: boolean) {
60
60
  left: 0,
61
61
  height: TRACK_HEIGHT,
62
62
  borderRadius: TRACK_HEIGHT / 2,
63
- backgroundColor: srgbToHex(tokens.interactive.srgb),
63
+ backgroundColor: srgbToHex(tokens.accent.fill.srgb),
64
64
  },
65
65
  thumb: {
66
66
  position: 'absolute',
67
67
  width: THUMB_SIZE,
68
68
  height: THUMB_SIZE,
69
69
  borderRadius: THUMB_SIZE / 2,
70
- backgroundColor: srgbToHex(tokens.interactive.srgb),
70
+ backgroundColor: srgbToHex(tokens.accent.fill.srgb),
71
71
  },
72
72
  });
73
73
  }
package/src/index.ts CHANGED
@@ -2,14 +2,13 @@
2
2
  export { NewtoneProvider, useNewtoneTheme } from './theme/NewtoneProvider';
3
3
  export type {
4
4
  ColorMode,
5
- ThemeName,
6
5
  ElevationLevel,
7
6
  FrameElevation,
8
- ThemeMapping,
9
7
  ColorSystemConfig,
10
8
  NewtoneThemeConfig,
11
9
  NewtoneThemeContext,
12
10
  FontConfig,
11
+ TokenOverrides,
13
12
  } from './theme/types';
14
13
  export { useFrameContext } from './theme/FrameContext';
15
14
  export type { FrameContextValue } from './theme/FrameContext';
@@ -17,8 +16,16 @@ export { DEFAULT_THEME_CONFIG } from './theme/defaults';
17
16
 
18
17
  // Tokens
19
18
  export { useTokens } from './tokens/useTokens';
20
- export { computeTokens } from './tokens/computeTokens';
21
- export type { ResolvedTokens } from './tokens/types';
19
+ export {
20
+ computeTokens,
21
+ NEUTRAL_DEFAULTS,
22
+ ACCENT_DEFAULTS,
23
+ SUCCESS_DEFAULTS,
24
+ WARNING_DEFAULTS,
25
+ ERROR_DEFAULTS,
26
+ } from './tokens/computeTokens';
27
+ export type { PaletteDefaults } from './tokens/computeTokens';
28
+ export type { ResolvedTokens, PaletteTokens } from './tokens/types';
22
29
 
23
30
  // Composite Components
24
31
  export { Button } from './composites/actions/Button/Button';
@@ -108,6 +115,7 @@ export type {
108
115
  EditableProp,
109
116
  EditablePropOption,
110
117
  ComponentMeta,
118
+ IconCatalogCategory,
111
119
  } from './registry';
112
120
  export {
113
121
  CATEGORIES,
@@ -116,6 +124,7 @@ export {
116
124
  getCategory,
117
125
  getComponentsByCategory,
118
126
  generateComponentCode,
127
+ ICON_CATALOG,
119
128
  } from './registry';
120
129
 
121
130
  // Fonts
@@ -61,7 +61,7 @@ function toElevationLevel(frameElevation: FrameElevation): ElevationLevel {
61
61
  * // Basic layout
62
62
  * <Frame direction="horizontal" gap="md" padding="lg" align="center">
63
63
  * <Button onPress={() => {}}>Save</Button>
64
- * <Button variant="ghost" onPress={() => {}}>Cancel</Button>
64
+ * <Button variant="tertiary" onPress={() => {}}>Cancel</Button>
65
65
  * </Frame>
66
66
  * ```
67
67
  *
@@ -69,7 +69,6 @@ function toElevationLevel(frameElevation: FrameElevation): ElevationLevel {
69
69
  * ```tsx
70
70
  * // Card-like frame
71
71
  * <Frame
72
- * theme="primary"
73
72
  * elevation={2}
74
73
  * radius="lg"
75
74
  * padding="xl"
@@ -92,8 +91,7 @@ function toElevationLevel(frameElevation: FrameElevation): ElevationLevel {
92
91
  */
93
92
  export function Frame({
94
93
  children,
95
- // Theme & elevation
96
- theme,
94
+ // Elevation
97
95
  elevation,
98
96
  // Layout
99
97
  layout,
@@ -132,15 +130,11 @@ export function Frame({
132
130
  // Style override
133
131
  style,
134
132
  }: FrameProps) {
135
- // Read the global theme configuration, current color mode (light/dark),
136
- // and the default theme name from the nearest NewtoneProvider.
137
- const { config, mode, theme: providerTheme } = useNewtoneTheme();
138
- // Read the theme/elevation from the nearest parent Frame (if nested).
133
+ // Read the global theme configuration and current color mode (light/dark).
134
+ const { config, mode } = useNewtoneTheme();
135
+ // Read the elevation from the nearest parent Frame (if nested).
139
136
  const parentFrameCtx = useFrameContext();
140
137
 
141
- // Decide which theme to use. Priority: this Frame's prop > parent Frame > NewtoneProvider.
142
- const resolvedTheme = theme ?? parentFrameCtx?.theme ?? providerTheme;
143
-
144
138
  // The user-facing elevation (-2 to 2) controls visual depth (shadows, background).
145
139
  const resolvedFrameElevation: FrameElevation = elevation ?? 0;
146
140
 
@@ -156,19 +150,17 @@ export function Frame({
156
150
  // so it needs to compute fresh tokens from the resolved theme/elevation.
157
151
  // Wrapped in useMemo so it only recalculates when the theme/mode/elevation changes.
158
152
  const tokens = useMemo(() => {
159
- const themeMapping = config.themes[resolvedTheme];
160
153
  return computeTokens(
161
154
  config.colorSystem,
162
155
  mode,
163
- themeMapping,
164
156
  resolvedElevation,
165
- config.elevation.offsets,
166
157
  config.spacing,
167
158
  config.radius,
168
159
  config.typography,
169
160
  config.icons,
161
+ config.tokenOverrides,
170
162
  );
171
- }, [config, mode, resolvedTheme, resolvedElevation]);
163
+ }, [config, mode, resolvedElevation]);
172
164
 
173
165
  // Calculate all visual styles (background, layout, border, shadow, etc.).
174
166
  // Only recalculates when one of the style-related props changes.
@@ -208,8 +200,8 @@ export function Frame({
208
200
  // This is the value that child components will inherit via FrameContext.
209
201
  // Any nested Frame, Text, Icon, etc. will read this theme and elevation.
210
202
  const contextValue = useMemo(
211
- () => ({ theme: resolvedTheme, elevation: resolvedElevation }),
212
- [resolvedTheme, resolvedElevation],
203
+ () => ({ elevation: resolvedElevation, tokens }),
204
+ [resolvedElevation, tokens],
213
205
  );
214
206
 
215
207
  // Some styles only work on web browsers (CSS grid, inset shadows).
@@ -241,7 +233,7 @@ export function Frame({
241
233
  const focusRingStyle = isFocusVisible && !disabled ? {
242
234
  outlineWidth: 2,
243
235
  outlineStyle: 'solid',
244
- outlineColor: srgbToHex(tokens.interactive.srgb),
236
+ outlineColor: srgbToHex(tokens.accent.fill.srgb),
245
237
  outlineOffset: 2,
246
238
  } as unknown as ViewStyle : undefined; // web-only
247
239