@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.
- package/dist/composites/actions/Button/Button.d.ts.map +1 -1
- package/dist/composites/actions/Button/Button.styles.d.ts +3 -1
- package/dist/composites/actions/Button/Button.styles.d.ts.map +1 -1
- package/dist/index.cjs +603 -249
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +599 -251
- package/dist/index.js.map +1 -1
- package/dist/primitives/Frame/Frame.d.ts +2 -3
- package/dist/primitives/Frame/Frame.d.ts.map +1 -1
- package/dist/primitives/Frame/Frame.types.d.ts +4 -15
- package/dist/primitives/Frame/Frame.types.d.ts.map +1 -1
- package/dist/primitives/Icon/Icon.d.ts +1 -1
- package/dist/primitives/Icon/Icon.d.ts.map +1 -1
- package/dist/primitives/Icon/Icon.types.d.ts +7 -12
- package/dist/primitives/Icon/Icon.types.d.ts.map +1 -1
- package/dist/primitives/Text/Text.d.ts.map +1 -1
- package/dist/primitives/Text/Text.types.d.ts +9 -4
- package/dist/primitives/Text/Text.types.d.ts.map +1 -1
- package/dist/primitives/Wrapper/Wrapper.d.ts +1 -1
- package/dist/primitives/Wrapper/Wrapper.types.d.ts +1 -1
- package/dist/registry/icons.d.ts +7 -0
- package/dist/registry/icons.d.ts.map +1 -0
- package/dist/registry/index.d.ts +2 -0
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/types.d.ts +1 -1
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/theme/FrameContext.d.ts +7 -5
- package/dist/theme/FrameContext.d.ts.map +1 -1
- package/dist/theme/NewtoneProvider.d.ts +5 -6
- package/dist/theme/NewtoneProvider.d.ts.map +1 -1
- package/dist/theme/defaults.d.ts.map +1 -1
- package/dist/theme/types.d.ts +38 -24
- package/dist/theme/types.d.ts.map +1 -1
- package/dist/tokens/computeTokens.d.ts +82 -7
- package/dist/tokens/computeTokens.d.ts.map +1 -1
- package/dist/tokens/types.d.ts +58 -16
- package/dist/tokens/types.d.ts.map +1 -1
- package/dist/tokens/useTokens.d.ts +2 -23
- package/dist/tokens/useTokens.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/composites/actions/Button/Button.styles.ts +53 -80
- package/src/composites/actions/Button/Button.tsx +6 -2
- package/src/composites/form-controls/Select/SelectOption.tsx +2 -2
- package/src/composites/form-controls/Toggle/Toggle.styles.ts +1 -1
- package/src/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.styles.ts +1 -1
- package/src/composites/range-inputs/Slider/Slider.styles.ts +2 -2
- package/src/index.ts +13 -4
- package/src/primitives/Frame/Frame.tsx +10 -18
- package/src/primitives/Frame/Frame.types.ts +5 -17
- package/src/primitives/Icon/Icon.tsx +4 -6
- package/src/primitives/Icon/Icon.types.ts +7 -14
- package/src/primitives/Text/Text.tsx +18 -8
- package/src/primitives/Text/Text.types.ts +9 -4
- package/src/primitives/Wrapper/Wrapper.tsx +1 -1
- package/src/primitives/Wrapper/Wrapper.types.ts +1 -1
- package/src/registry/icons.ts +111 -0
- package/src/registry/index.ts +3 -0
- package/src/registry/registry.ts +40 -24
- package/src/registry/types.ts +1 -1
- package/src/theme/FrameContext.tsx +7 -5
- package/src/theme/NewtoneProvider.tsx +5 -10
- package/src/theme/defaults.ts +0 -9
- package/src/theme/types.ts +53 -26
- package/src/tokens/computeTokens.ts +338 -116
- package/src/tokens/types.ts +74 -16
- package/src/tokens/useTokens.ts +16 -33
package/dist/tokens/types.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
27
|
-
readonly
|
|
28
|
-
/**
|
|
29
|
-
readonly
|
|
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
|
-
/**
|
|
35
|
-
readonly
|
|
36
|
-
/**
|
|
37
|
-
readonly
|
|
38
|
-
/**
|
|
39
|
-
readonly
|
|
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":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,cAAc;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tokens/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -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
|
-
*
|
|
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
|
|
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,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
|
-
*
|
|
126
|
-
*
|
|
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
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
*
|
|
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:
|
|
232
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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',
|
|
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:
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
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',
|
|
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
|
-
//
|
|
278
|
+
// Shifted action scale: transparent → 01 (hover) → 02 (pressed)
|
|
309
279
|
return {
|
|
310
280
|
bg: 'transparent',
|
|
311
|
-
|
|
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
|
|
320
|
-
const semanticColor = getSemanticColor();
|
|
290
|
+
// Semantic secondary — uses palette surface tokens for subtle bg
|
|
321
291
|
return {
|
|
322
|
-
bg:
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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',
|
|
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
|
-
//
|
|
305
|
+
// Shifted action scale: transparent → 01 (hover) → 02 (pressed)
|
|
335
306
|
return {
|
|
336
307
|
bg: 'transparent',
|
|
337
|
-
|
|
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',
|
|
313
|
+
borderColor: 'transparent',
|
|
342
314
|
};
|
|
343
315
|
}
|
|
344
316
|
|
|
345
|
-
// Semantic tertiary
|
|
346
|
-
const semanticColor = getSemanticColor();
|
|
317
|
+
// Semantic tertiary — uses palette surface tokens for hover/pressed
|
|
347
318
|
return {
|
|
348
319
|
bg: 'transparent',
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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',
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 {
|
|
21
|
-
|
|
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="
|
|
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
|
-
//
|
|
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
|
|
136
|
-
|
|
137
|
-
|
|
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,
|
|
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
|
-
() => ({
|
|
212
|
-
[
|
|
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.
|
|
236
|
+
outlineColor: srgbToHex(tokens.accent.fill.srgb),
|
|
245
237
|
outlineOffset: 2,
|
|
246
238
|
} as unknown as ViewStyle : undefined; // web-only
|
|
247
239
|
|