Skip to content

Commit 5bd2a95

Browse files
authored
[WB-1814.6] Refactor Link to use semantic colors (#2464)
Next step is to refactor the `Link` component to use semantic colors. Besides the migration, this PR also includes the following changes: - Reworked the theme structure to make it closer to the semanticColor structure. - Updated stories to use the new semantic colors. ### Implementation plan: 1. #2439 2. #2440 3. #2441 4. #2446 5. #2449 6. Link (current PR) 7. Modal 8. Popover, Tooltip 9. Pill 10. Clickable, Toolbar Issue: WB-1814 ## Test plan: Verify that the Chromatic snapshots are unchanged. URL: `/?path=/story/packages-link-link-all-variants--default` Author: jandrade Reviewers: jandrade, beaesguerra Required Reviewers: Approved By: beaesguerra Checks: ✅ Chromatic - Get results on regular PRs (ubuntu-latest, 20.x), ✅ Test / Test (ubuntu-latest, 20.x, 2/2), ✅ Test / Test (ubuntu-latest, 20.x, 1/2), ✅ Lint / Lint (ubuntu-latest, 20.x), ✅ Check build sizes (ubuntu-latest, 20.x), ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Chromatic - Build and test on regular PRs / chromatic (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ⏭️ Chromatic - Skip on Release PR (changesets), ✅ Prime node_modules cache for primary configuration (ubuntu-latest, 20.x), ⏭️ dependabot, ✅ gerald Pull Request URL: #2464
1 parent ed26d66 commit 5bd2a95

File tree

4 files changed

+194
-96
lines changed

4 files changed

+194
-96
lines changed

.changeset/mighty-goats-look.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@khanacademy/wonder-blocks-banner": patch
3+
"@khanacademy/wonder-blocks-link": patch
4+
---
5+
6+
Internal `Link` refactor to use `semanticColor` tokens intead of `color`. Also moved the link colors to an object to prepare this for an upcoming theme integration"

__docs__/wonder-blocks-link/link-variants.stories.tsx

+40-13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
import {HeadingLarge} from "@khanacademy/wonder-blocks-typography";
1313

1414
import {AllVariants} from "../components/all-variants";
15+
import {PhosphorIcon} from "@khanacademy/wonder-blocks-icon";
16+
import {IconMappings} from "../wonder-blocks-icon/phosphor-icon.argtypes";
1517

1618
const rows = [
1719
{name: "Default", props: {}},
@@ -26,13 +28,36 @@ const columns = [
2628
name: "Primary",
2729
props: {},
2830
},
31+
{
32+
name: "startIcon",
33+
props: {
34+
children: "With startIcon",
35+
startIcon: <PhosphorIcon icon={IconMappings.plusCircleBold} />,
36+
},
37+
},
38+
{
39+
name: "endIcon",
40+
props: {
41+
children: "With endIcon",
42+
endIcon: <PhosphorIcon icon={IconMappings.magnifyingGlassBold} />,
43+
target: "_blank",
44+
},
45+
},
46+
{
47+
name: "External",
48+
props: {
49+
children: "External link",
50+
href: "https://www.khanacademy.org",
51+
target: "_blank",
52+
},
53+
},
2954
{
3055
name: "Visitable",
3156
props: {visitable: true},
3257
},
3358
];
3459

35-
const themes: Array<string> = ["default", "dark"];
60+
const themes: Array<string> = ["default", "dark", "rtl"];
3661

3762
type Story = StoryObj<typeof Link>;
3863

@@ -50,17 +75,16 @@ const meta = {
5075
<AllVariants rows={rows} columns={columns}>
5176
{(props) => (
5277
<>
53-
{theme === "dark" &&
54-
props.kind === "secondary" ? null : (
55-
<Link
56-
{...args}
57-
{...props}
58-
light={theme === "dark"}
59-
href="https://www.khanacademy.org"
60-
>
61-
This is a Link
62-
</Link>
63-
)}
78+
<Link
79+
{...args}
80+
{...props}
81+
light={theme === "dark"}
82+
href="https://www.khanacademy.org"
83+
>
84+
{theme === "rtl"
85+
? "هذا الرابط مكتوب باللغة العربية"
86+
: "This is a Link"}
87+
</Link>
6488
</>
6589
)}
6690
</AllVariants>
@@ -113,7 +137,7 @@ export const PressVisited: Story = {
113137

114138
const styles = StyleSheet.create({
115139
container: {
116-
maxWidth: 700,
140+
maxWidth: 1000,
117141
gap: spacing.medium_16,
118142
},
119143
theme: {
@@ -125,6 +149,9 @@ const styles = StyleSheet.create({
125149
backgroundColor: semanticColor.surface.inverse,
126150
color: semanticColor.text.inverse,
127151
},
152+
rtl: {
153+
direction: "rtl",
154+
},
128155
title: {
129156
textTransform: "capitalize",
130157
},

__docs__/wonder-blocks-link/link.stories.tsx

+75-58
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {Meta, StoryObj} from "@storybook/react";
66
import {View} from "@khanacademy/wonder-blocks-core";
77
import {PhosphorIcon} from "@khanacademy/wonder-blocks-icon";
88
import {Strut} from "@khanacademy/wonder-blocks-layout";
9-
import {color, spacing} from "@khanacademy/wonder-blocks-tokens";
9+
import {semanticColor, spacing} from "@khanacademy/wonder-blocks-tokens";
1010
import {
1111
Body,
1212
HeadingSmall,
@@ -202,7 +202,7 @@ export const StartAndEndIcons: StoryComponentType = {
202202
{/* Light */}
203203
<View
204204
style={{
205-
backgroundColor: color.darkBlue,
205+
backgroundColor: semanticColor.surface.inverse,
206206
padding: spacing.large_24,
207207
}}
208208
>
@@ -262,7 +262,7 @@ export const StartAndEndIcons: StoryComponentType = {
262262
>
263263
This is a multi-line link with start and end icons
264264
</Link>
265-
<Body style={{color: color.white}}>
265+
<Body style={{color: semanticColor.text.inverse}}>
266266
This is an inline{" "}
267267
<Link
268268
href="#link"
@@ -300,7 +300,7 @@ export const StartAndEndIcons: StoryComponentType = {
300300
*/
301301
export const Inline: StoryComponentType = {
302302
render: () => (
303-
<Body>
303+
<Body style={{width: 530}}>
304304
This is an inline{" "}
305305
<Link href="#link" inline={true}>
306306
regular link
@@ -329,6 +329,14 @@ export const Inline: StoryComponentType = {
329329
.
330330
</Body>
331331
),
332+
parameters: {
333+
chromatic: {
334+
// Re-enable snapshots for this story since it shows the links in
335+
// the context of paragraphs.
336+
disableSnapshot: false,
337+
},
338+
pseudo: {visited: true},
339+
},
332340
};
333341

334342
/**
@@ -340,7 +348,7 @@ export const Inline: StoryComponentType = {
340348
*/
341349
export const InlineLight: StoryComponentType = {
342350
render: () => (
343-
<Body style={{color: color.white}}>
351+
<Body style={{color: semanticColor.text.inverse, width: 530}}>
344352
This is an inline{" "}
345353
<Link href="#link" inline={true} light={true}>
346354
regular link
@@ -356,7 +364,7 @@ export const InlineLight: StoryComponentType = {
356364
</Link>
357365
, whereas this is an inline{" "}
358366
<Link href="#link" visitable={true} inline={true} light={true}>
359-
Visitable link (Primary only)
367+
Visitable link
360368
</Link>{" "}
361369
and an{" "}
362370
<Link
@@ -366,15 +374,21 @@ export const InlineLight: StoryComponentType = {
366374
light={true}
367375
target="_blank"
368376
>
369-
external Visitable link (Primary only)
377+
external Visitable link
370378
</Link>
371-
. Secondary light links are not supported.
379+
.
372380
</Body>
373381
),
374382
parameters: {
375383
backgrounds: {
376384
default: "darkBlue",
377385
},
386+
chromatic: {
387+
// Re-enable snapshots for this story since it shows the links in
388+
// the context of paragraphs.
389+
disableSnapshot: false,
390+
},
391+
pseudo: {visited: true},
378392
},
379393
};
380394

@@ -391,56 +405,34 @@ export const WithTypography: StoryComponentType = {
391405
</Link>
392406
</HeadingSmall>
393407
),
408+
parameters: {
409+
chromatic: {
410+
// Re-enable snapshots for this story since it's verifying that
411+
// the styles on typography elements are applied
412+
disableSnapshot: false,
413+
},
414+
},
394415
};
395416

396417
/**
397418
* Link can take a `style` prop. Here, the Link has been given a style in which
398-
* the `color` field has been set to `color.red`.
419+
* the `color` field has been set to `semanticColor.status.critical.foreground`.
399420
*/
400421
export const WithStyle: StoryComponentType = {
401422
render: () => (
402423
<Link href="#link" style={styles.customLink}>
403424
This link has a style.
404425
</Link>
405426
),
427+
parameters: {
428+
chromatic: {
429+
// Re-enable snapshots for this story since it's verifying that
430+
// custom styles are applied (one-off)
431+
disableSnapshot: false,
432+
},
433+
},
406434
};
407435

408-
export const Navigation: StoryComponentType = () => (
409-
<MemoryRouter>
410-
<View>
411-
<View style={styles.row}>
412-
<Link
413-
href="/foo"
414-
style={styles.heading}
415-
onClick={() => {
416-
// eslint-disable-next-line no-console
417-
console.log("I'm still on the same page!");
418-
}}
419-
>
420-
<LabelLarge>Uses Client-side Nav</LabelLarge>
421-
</Link>
422-
<Link
423-
href="/iframe.html?id=link--default&viewMode=story"
424-
style={styles.heading}
425-
skipClientNav
426-
>
427-
<LabelLarge>Avoids Client-side Nav</LabelLarge>
428-
</Link>
429-
</View>
430-
<View style={styles.navigation}>
431-
<Switch>
432-
<Route path="/foo">
433-
<View id="foo">
434-
The first link does client-side navigation here.
435-
</View>
436-
</Route>
437-
<Route path="*">See navigation changes here</Route>
438-
</Switch>
439-
</View>
440-
</View>
441-
</MemoryRouter>
442-
);
443-
444436
/**
445437
* If you want to navigate to an external URL and/or reload the window, make
446438
* sure to use `href` and `skipClientNav={true}`, as shown in this example.
@@ -450,12 +442,42 @@ export const Navigation: StoryComponentType = () => (
450442
* documentation](/story/button-navigation-callbacks--before-nav-callbacks&viewMode=docs)
451443
* for details.
452444
*/
453-
Navigation.parameters = {
454-
docs: {
455-
description: {
456-
story: ``,
457-
},
458-
},
445+
export const Navigation: StoryComponentType = {
446+
render: () => (
447+
<MemoryRouter>
448+
<View>
449+
<View style={styles.row}>
450+
<Link
451+
href="/foo"
452+
style={styles.heading}
453+
onClick={() => {
454+
// eslint-disable-next-line no-console
455+
console.log("I'm still on the same page!");
456+
}}
457+
>
458+
<LabelLarge>Uses Client-side Nav</LabelLarge>
459+
</Link>
460+
<Link
461+
href="/iframe.html?id=link--default&viewMode=story"
462+
style={styles.heading}
463+
skipClientNav
464+
>
465+
<LabelLarge>Avoids Client-side Nav</LabelLarge>
466+
</Link>
467+
</View>
468+
<View style={styles.navigation}>
469+
<Switch>
470+
<Route path="/foo">
471+
<View id="foo">
472+
The first link does client-side navigation here.
473+
</View>
474+
</Route>
475+
<Route path="*">See navigation changes here</Route>
476+
</Switch>
477+
</View>
478+
</View>
479+
</MemoryRouter>
480+
),
459481
};
460482

461483
/**
@@ -517,21 +539,16 @@ export const RightToLeftWithIcons: StoryComponentType = {
517539
};
518540

519541
const styles = StyleSheet.create({
520-
darkBackground: {
521-
backgroundColor: color.darkBlue,
522-
color: color.white,
523-
padding: 10,
524-
},
525542
heading: {
526543
marginRight: spacing.large_24,
527544
},
528545
navigation: {
529-
border: `1px dashed ${color.purple}`,
546+
border: `1px dashed ${semanticColor.border.primary}`,
530547
marginTop: spacing.large_24,
531548
padding: spacing.large_24,
532549
},
533550
customLink: {
534-
color: color.red,
551+
color: semanticColor.status.critical.foreground,
535552
},
536553
row: {
537554
flexDirection: "row",

0 commit comments

Comments
 (0)