Skip to content

Commit 6ce1322

Browse files
feat: integrate EDS semantic color tokens (#74)
Create hybrid token system Use EDS semantic tokens where appropriate and custom tokens for brand colors. Restructure masterToken into colorTokens + layoutTokens composition while maintaining existing API.
1 parent bca03eb commit 6ce1322

9 files changed

Lines changed: 981 additions & 788 deletions

File tree

packages/components/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
},
88
"bugs": "https://github.com/equinor/design-system-mobile/issues",
99
"dependencies": {
10+
"@equinor/eds-tokens": "^2.1.1",
1011
"@floating-ui/react-native": "^0.10.7",
1112
"react-error-boundary": "^6.0.0"
1213
},
Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
// Color tokens sourced from @equinor/eds-tokens + custom tokens
2+
// Matches masterToken.colors structure while sourcing from EDS where possible
3+
4+
import { colors } from "./colors";
5+
import { EDSSemanticJson } from "./edsTokenTypes";
6+
import { ColorToken } from "./types";
7+
8+
/* eslint-disable @typescript-eslint/no-require-imports */
9+
const lightSemanticJson =
10+
require("@equinor/eds-tokens/build/json/color/color-scheme/nested/light-semantic.json") as EDSSemanticJson;
11+
const darkSemanticJson =
12+
require("@equinor/eds-tokens/build/json/color/color-scheme/nested/dark-semantic.json") as EDSSemanticJson;
13+
/* eslint-enable @typescript-eslint/no-require-imports */
14+
15+
// EDS Background tokens (camelCase accessors)
16+
const edsBg = {
17+
neutral: {
18+
canvas: {
19+
light: lightSemanticJson.Bg.Neutral.Canvas,
20+
dark: darkSemanticJson.Bg.Neutral.Canvas,
21+
},
22+
surface: {
23+
light: lightSemanticJson.Bg.Neutral.Surface,
24+
dark: darkSemanticJson.Bg.Neutral.Surface,
25+
},
26+
fillMuted: {
27+
default: {
28+
light: lightSemanticJson.Bg.Neutral["Fill Muted"].Default,
29+
dark: darkSemanticJson.Bg.Neutral["Fill Muted"].Default,
30+
},
31+
hover: {
32+
light: lightSemanticJson.Bg.Neutral["Fill Muted"].Hover,
33+
dark: darkSemanticJson.Bg.Neutral["Fill Muted"].Hover,
34+
},
35+
active: {
36+
light: lightSemanticJson.Bg.Neutral["Fill Muted"].Active,
37+
dark: darkSemanticJson.Bg.Neutral["Fill Muted"].Active,
38+
},
39+
},
40+
fillEmphasis: {
41+
default: {
42+
light: lightSemanticJson.Bg.Neutral["Fill Emphasis"].Default,
43+
dark: darkSemanticJson.Bg.Neutral["Fill Emphasis"].Default,
44+
},
45+
hover: {
46+
light: lightSemanticJson.Bg.Neutral["Fill Emphasis"].Hover,
47+
dark: darkSemanticJson.Bg.Neutral["Fill Emphasis"].Hover,
48+
},
49+
active: {
50+
light: lightSemanticJson.Bg.Neutral["Fill Emphasis"].Active,
51+
dark: darkSemanticJson.Bg.Neutral["Fill Emphasis"].Active,
52+
},
53+
},
54+
},
55+
warning: {
56+
canvas: {
57+
light: lightSemanticJson.Bg.Warning.Canvas,
58+
dark: darkSemanticJson.Bg.Warning.Canvas,
59+
},
60+
surface: {
61+
light: lightSemanticJson.Bg.Warning.Surface,
62+
dark: darkSemanticJson.Bg.Warning.Surface,
63+
},
64+
fillMuted: {
65+
default: {
66+
light: lightSemanticJson.Bg.Warning["Fill Muted"].Default,
67+
dark: darkSemanticJson.Bg.Warning["Fill Muted"].Default,
68+
},
69+
},
70+
fillEmphasis: {
71+
default: {
72+
light: lightSemanticJson.Bg.Warning["Fill Emphasis"].Default,
73+
dark: darkSemanticJson.Bg.Warning["Fill Emphasis"].Default,
74+
},
75+
},
76+
},
77+
success: {
78+
fillEmphasis: {
79+
default: {
80+
light: lightSemanticJson.Bg.Success["Fill Emphasis"].Default,
81+
dark: darkSemanticJson.Bg.Success["Fill Emphasis"].Default,
82+
},
83+
},
84+
},
85+
danger: {
86+
fillEmphasis: {
87+
default: {
88+
light: lightSemanticJson.Bg.Danger["Fill Emphasis"].Default,
89+
dark: darkSemanticJson.Bg.Danger["Fill Emphasis"].Default,
90+
},
91+
},
92+
},
93+
};
94+
95+
// EDS Border tokens (camelCase accessors)
96+
const edsBorder = {
97+
neutral: {
98+
subtle: {
99+
light: lightSemanticJson.Border.Neutral.Subtle,
100+
dark: darkSemanticJson.Border.Neutral.Subtle,
101+
},
102+
medium: {
103+
light: lightSemanticJson.Border.Neutral.Medium,
104+
dark: darkSemanticJson.Border.Neutral.Medium,
105+
},
106+
strong: {
107+
light: lightSemanticJson.Border.Neutral.Strong,
108+
dark: darkSemanticJson.Border.Neutral.Strong,
109+
},
110+
},
111+
warning: {
112+
subtle: {
113+
light: lightSemanticJson.Border.Warning.Subtle,
114+
dark: darkSemanticJson.Border.Warning.Subtle,
115+
},
116+
},
117+
};
118+
119+
// EDS Text tokens (camelCase accessors)
120+
const edsText = {
121+
neutral: {
122+
subtle: {
123+
light: lightSemanticJson.Text.Neutral.Subtle,
124+
dark: darkSemanticJson.Text.Neutral.Subtle,
125+
},
126+
strong: {
127+
light: lightSemanticJson.Text.Neutral.Strong,
128+
dark: darkSemanticJson.Text.Neutral.Strong,
129+
},
130+
subtleOnEmphasis: {
131+
light: lightSemanticJson.Text.Neutral["Subtle on emphasis"],
132+
dark: darkSemanticJson.Text.Neutral["Subtle on emphasis"],
133+
},
134+
strongOnEmphasis: {
135+
light: lightSemanticJson.Text.Neutral["Strong on emphasis"],
136+
dark: darkSemanticJson.Text.Neutral["Strong on emphasis"],
137+
},
138+
},
139+
danger: {
140+
strong: {
141+
light: lightSemanticJson.Text.Danger.Strong,
142+
dark: darkSemanticJson.Text.Danger.Strong,
143+
},
144+
subtle: {
145+
light: lightSemanticJson.Text.Danger.Subtle,
146+
dark: darkSemanticJson.Text.Danger.Subtle,
147+
},
148+
},
149+
warning: {
150+
strong: {
151+
light: lightSemanticJson.Text.Warning.Strong,
152+
dark: darkSemanticJson.Text.Warning.Strong,
153+
},
154+
},
155+
};
156+
157+
// =============================================================================
158+
// Color tokens matching masterToken.colors structure
159+
// Using EDS tokens where possible + custom tokens for gaps
160+
// =============================================================================
161+
162+
export const colorToken: ColorToken = {
163+
// Border colors - using EDS neutral borders
164+
border: {
165+
lighter: edsBorder.neutral.subtle, // EDS subtle border
166+
light: edsBorder.neutral.subtle, // EDS subtle border (same as lighter)
167+
medium: edsBorder.neutral.medium, // EDS medium border
168+
},
169+
170+
// Container colors - mix of EDS + custom
171+
container: {
172+
background: edsBg.neutral.surface, // EDS neutral surface
173+
default: edsBg.neutral.canvas, // EDS neutral canvas
174+
warning: edsBg.warning.surface, // EDS warning surface
175+
elevation: {
176+
// Custom elevation colors (no EDS equivalent)
177+
none: {
178+
light: colors.ui_background_light_default,
179+
dark: colors.ui_background_dark_none_plus_above_scrim,
180+
},
181+
aboveScrim: {
182+
light: colors.ui_background_light_default,
183+
dark: colors.ui_background_dark_none_plus_above_scrim,
184+
},
185+
raised: {
186+
light: colors.ui_background_light_default,
187+
dark: colors.ui_background_dark_raised,
188+
},
189+
overlay: {
190+
light: colors.ui_background_light_default,
191+
dark: colors.ui_background_dark_overlay,
192+
},
193+
sticky: {
194+
light: colors.ui_background_light_default,
195+
dark: colors.ui_background_dark_sticky,
196+
},
197+
temporaryNav: {
198+
light: colors.ui_background_light_default,
199+
dark: colors.ui_background_dark_temporary_nav,
200+
},
201+
},
202+
203+
// TODO same color for dark mode?
204+
scrim: {
205+
light: colors.ui_background_light_scrim,
206+
dark: colors.ui_background_light_scrim,
207+
},
208+
},
209+
210+
// Interactive colors - EDS semantic where appropriate + custom for brand colors
211+
interactive: {
212+
primary: {
213+
light: colors.interactive_primary_light_resting,
214+
dark: colors.interactive_primary_dark_resting,
215+
}, // Custom brand
216+
secondary: {
217+
light: colors.interactive_secondary_light_resting,
218+
dark: colors.interactive_secondary_dark_resting,
219+
}, // Custom brand
220+
success: edsBg.success.fillEmphasis.default, // EDS semantic success
221+
warning: edsBg.warning.fillEmphasis.default, // EDS semantic warning
222+
danger: edsBg.danger.fillEmphasis.default, // EDS semantic danger
223+
224+
disabled: {
225+
light: colors.interactive_disabled_light_fill,
226+
dark: colors.interactive_disabled_dark_fill,
227+
}, // Custom
228+
pressedOverlay: {
229+
light: colors.interactive_pressed_overlay_light,
230+
dark: colors.interactive_pressed_overlay_dark,
231+
}, // Custom
232+
selectedHighlight: {
233+
light: colors.interactive_primary_light_selected_highlight,
234+
dark: colors.interactive_primary_dark_selected_highlight,
235+
}, // Custom brand
236+
},
237+
238+
// Feedback colors - using EDS semantic colors
239+
feedback: {
240+
success: edsBg.success.fillEmphasis.default, // EDS semantic success
241+
warning: edsBg.warning.fillEmphasis.default, // EDS semantic warning
242+
danger: edsBg.danger.fillEmphasis.default, // EDS semantic danger
243+
},
244+
245+
// Environment colors - custom for dev/test/qa indicators + EDS text
246+
environment: {
247+
dev: {
248+
light: colors.infographic_primary_energy_red_100,
249+
dark: colors.infographic_primary_energy_red_34,
250+
}, // Custom indicators
251+
test: {
252+
light: colors.infographic_primary_spruce_wood,
253+
dark: colors.feedback_warning_dark_hover,
254+
}, // Custom indicators
255+
qa: {
256+
light: colors.infographic_primary_moss_green_21,
257+
dark: colors.infographic_primary_moss_green_34,
258+
}, // Custom indicators
259+
text: edsText.neutral.strong, // EDS neutral text
260+
},
261+
262+
// Text colors - EDS semantic where appropriate + custom for specific cases
263+
text: {
264+
primary: edsText.neutral.strong, // EDS primary text
265+
secondary: edsText.neutral.subtle, // EDS secondary text
266+
tertiary: {
267+
light: colors.text_and_static_icons_light_tertiary,
268+
dark: colors.text_and_static_icons_dark_tertiary,
269+
}, // Custom (no EDS tertiary)
270+
primaryInverted: edsText.neutral.strongOnEmphasis, // EDS inverted text
271+
disabled: {
272+
light: colors.interactive_disabled_light_text,
273+
dark: colors.interactive_disabled_dark_text,
274+
}, // Custom
275+
danger: edsText.danger.strong, // EDS semantic danger text
276+
menu: {
277+
resting: edsText.neutral.strong, // EDS neutral text
278+
active: {
279+
light: colors.interactive_primary_light_resting,
280+
dark: colors.interactive_primary_dark_resting,
281+
}, // Custom brand
282+
},
283+
feedbackWarning: edsText.warning.strong, // EDS semantic warning text
284+
},
285+
286+
// Toast colors - custom from colors.ts
287+
toast: {
288+
error: {
289+
background: {
290+
light: colors.toast_error_background_light,
291+
dark: colors.toast_error_background_dark,
292+
},
293+
text: {
294+
light: colors.toast_error_text_light,
295+
dark: colors.toast_error_text_dark,
296+
},
297+
},
298+
success: {
299+
background: {
300+
light: colors.toast_success_background_light,
301+
dark: colors.toast_success_background_dark,
302+
},
303+
text: {
304+
light: colors.toast_success_text_light,
305+
dark: colors.toast_success_text_dark,
306+
},
307+
},
308+
info: {
309+
background: {
310+
light: colors.toast_info_background_light,
311+
dark: colors.toast_info_background_dark,
312+
},
313+
text: {
314+
light: colors.toast_info_text_light,
315+
dark: colors.toast_info_text_dark,
316+
},
317+
},
318+
warning: {
319+
background: {
320+
light: colors.toast_warning_background_light,
321+
dark: colors.toast_warning_background_dark,
322+
},
323+
text: {
324+
light: colors.toast_warning_text_light,
325+
dark: colors.toast_warning_text_dark,
326+
},
327+
},
328+
},
329+
};

packages/components/src/styling/colors.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// These colors are from https://eds.equinor.com/0b0c666ab/p/78c75b-colour/b/708097
22
export const colors = {
3+
interactive_pressed_overlay_light: "#00000033", // rgba(0,0,0,0.2)
4+
interactive_pressed_overlay_dark: "#FFFFFF33", // rgba(255,255,255,0.2)
35
interactive_primary_light_resting: "#007079",
46
interactive_primary_light_hover: "#004F55",
57
interactive_primary_light_hover_alt: "#DEEDEE",

0 commit comments

Comments
 (0)