Skip to content

Commit

Permalink
[wb-semantic-color-refactor] Rework action semantic color tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
Juan Andrade committed Jan 15, 2025
1 parent 4662953 commit a036e68
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 45 deletions.
6 changes: 5 additions & 1 deletion .changeset/hot-panthers-kneel.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@
"@khanacademy/wonder-blocks-tokens": major
---

Rework semanticColor actions to use a new structure. Every `action` now includes `default`, `hover` and `press` states, and each state includes `border`, `background` and `foreground` tokens.
- Reworked semanticColor actions to use a new structure. Every `action` now includes `default`, `hover` and `press` states, and each state includes `border`, `background` and `foreground` tokens.

- Renamed `primary` to `progressive`.

- Added inverse categories to actions: `progressiveInverse` and `destructiveInverse`.
51 changes: 36 additions & 15 deletions __docs__/components/color.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {StyleType, View} from "@khanacademy/wonder-blocks-core";
import {
Caption,
Footnote,
LabelLarge,
LabelSmall,
} from "@khanacademy/wonder-blocks-typography";
import {
Expand All @@ -17,6 +16,8 @@ import {
} from "@khanacademy/wonder-blocks-tokens";
import {getTokenName} from "./tokens-util";

type Variant = "primitive" | "semantic" | "compact";

type Props = {
/**
* A dictionary of colors to display.
Expand All @@ -25,7 +26,7 @@ type Props = {
/**
* The type of color group to display.
*/
variant: "primitive" | "semantic";
variant: Variant;
/**
* The group name to use as a prefix for the color names.
*/
Expand Down Expand Up @@ -59,15 +60,12 @@ export function ColorGroup({
type ColorProps = {
name: string;
value: string;
variant: "primitive" | "semantic";
variant: Variant;
};

function Color({name, value, variant}: ColorProps) {
const TypographyComponent =
variant === "semantic" ? LabelLarge : LabelSmall;

return (
<View style={styles.item}>
<View style={[styles.item, styles[variant + "Item"]]}>
<View
style={[
styles.thumbnail,
Expand All @@ -82,17 +80,23 @@ function Color({name, value, variant}: ColorProps) {
// Expand to fill the parent container
alignSelf: "stretch",
flex: 1,
padding: spacing.medium_16,
}}
/>
</View>
<View>
<TypographyComponent style={{fontWeight: font.weight.bold}}>
<View style={styles.info}>
<LabelSmall
style={{
fontWeight: font.weight.bold,
}}
>
{name}
</TypographyComponent>
{variant === "semantic" ? (
</LabelSmall>
{variant !== "primitive" ? (
<>
<Caption>
Primitive: <em>{getTokenName(color, value)}</em>
Primitive:{" "}
<em>{getTokenName(color, value) || value}</em>
</Caption>
<LabelSmall>
Value:{" "}
Expand All @@ -107,27 +111,44 @@ function Color({name, value, variant}: ColorProps) {
);
}

const itemWidth = 200;
const itemHeight = 120;

const styles = StyleSheet.create({
group: {
flexDirection: "row",
flexWrap: "wrap",
marginBlock: spacing.large_24,
},
item: {
marginBlockEnd: spacing.medium_16,
maxWidth: itemWidth,
overflowWrap: "break-word",
},
compactItem: {
flexDirection: "row",
gap: spacing.xSmall_8,
maxWidth: "unset",
},
pattern: {
backgroundImage: `radial-gradient(${color.blue} 0.5px, ${color.offWhite} 0.5px)`,
backgroundSize: `${spacing.small_12}px ${spacing.small_12}px`,
boxShadow: `0 0 1px 0 ${semanticColor.border.primary}`,
},
thumbnail: {
width: 200,
height: 160,
width: itemWidth,
height: itemHeight,
},
primitiveThumbnail: {
width: 160,
height: spacing.xxxLarge_64,
},
compactThumbnail: {
width: spacing.xxxLarge_64,
height: spacing.xxxLarge_64,
},
info: {
paddingInlineEnd: spacing.medium_16,
},
code: {
alignSelf: "flex-start",
color: semanticColor.text.primary,
Expand Down
123 changes: 105 additions & 18 deletions __docs__/foundations-color.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export const styles = StyleSheet.create({
display: "grid",
gridTemplateColumns: "repeat(auto-fill, 160px)",
},
gridCompact: {
display: "grid",
gridTemplateColumns: "repeat(3, minmax(100px, auto))",
},
banner: {
marginBottom: spacing.xLarge_32,
},
Expand Down Expand Up @@ -78,17 +82,98 @@ how to use these colors depending on the context.
For buttons, links, and controls to communicate the presence and meaning of
interaction.

<View style={styles.grid}>
<ColorGroup colors={semanticColor.action.primary} group="action.primary" />
<ColorGroup
colors={semanticColor.action.destructive}
group="action.destructive"
/>
<ColorGroup
colors={semanticColor.action.disabled}
group="action.disabled"
/>
</View>
#### Progressive

<ColorGroup
colors={semanticColor.action.progressive.default}
group="action.progressive.default"
variant="compact"
style={styles.gridCompact}
/>
<ColorGroup
colors={semanticColor.action.progressive.hover}
group="action.progressive.hover"
variant="compact"
style={styles.gridCompact}
/>
<ColorGroup
colors={semanticColor.action.progressive.press}
group="action.progressive.press"
variant="compact"
style={styles.gridCompact}
/>

#### Progressive inverse

<ColorGroup
colors={semanticColor.action.progressiveInverse.default}
group="action.progressiveInverse.default"
variant="compact"
style={styles.gridCompact}
/>
<ColorGroup
colors={semanticColor.action.progressiveInverse.hover}
group="action.progressiveInverse.hover"
variant="compact"
style={styles.gridCompact}
/>
<ColorGroup
colors={semanticColor.action.progressiveInverse.press}
group="action.progressiveInverse.press"
variant="compact"
style={styles.gridCompact}
/>

#### Destructive

<ColorGroup
colors={semanticColor.action.destructive.default}
group="action.destructive.default"
variant="compact"
style={styles.gridCompact}
/>
<ColorGroup
colors={semanticColor.action.destructive.hover}
group="action.destructive.hover"
variant="compact"
style={styles.gridCompact}
/>
<ColorGroup
colors={semanticColor.action.destructive.press}
group="action.destructive.press"
variant="compact"
style={styles.gridCompact}
/>

#### Destructive inverse

<ColorGroup
colors={semanticColor.action.destructiveInverse.default}
group="action.destructiveInverse.default"
variant="compact"
style={styles.gridCompact}
/>
<ColorGroup
colors={semanticColor.action.destructiveInverse.hover}
group="action.destructiveInverse.hover"
variant="compact"
style={styles.gridCompact}
/>
<ColorGroup
colors={semanticColor.action.destructiveInverse.press}
group="action.destructiveInverse.press"
variant="compact"
style={styles.gridCompact}
/>

#### Disabled

<ColorGroup
colors={semanticColor.action.disabled}
group="action.disabled"
variant="compact"
style={styles.gridCompact}
/>

### Status

Expand Down Expand Up @@ -389,10 +474,12 @@ content is accessible to all users.

For more detail, you can check the following Success Criteria documents:

- <a
href="https://www.w3.org/WAI/WCAG22/Understanding/use-of-color">Use of Color</a>
- <a
href="https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum">Contrast (minimum)</a>
- <a
href="https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast">Non-text
Contrast (Level AA)</a>
- <a href="https://www.w3.org/WAI/WCAG22/Understanding/use-of-color">
Use of Color
</a>
- <a href="https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum">
Contrast (minimum)
</a>
- <a href="https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast">
Non-text Contrast (Level AA)
</a>
86 changes: 75 additions & 11 deletions packages/wonder-blocks-tokens/src/tokens/semantic-color.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,87 @@
import {color} from "./color";

const border = {
primary: color.fadedOffBlack16,
subtle: color.fadedOffBlack8,
strong: color.fadedOffBlack50,
inverse: color.white,
};

export const semanticColor = {
/**
* For buttons, links, and controls to communicate the presence and meaning
* of interaction.
*/
action: {
primary: {
default: color.blue,
active: color.activeBlue,
// For primary actions
progressive: {
default: {
border: "transparent",
background: color.blue,
foreground: color.white,
},
hover: {
border: color.blue,
background: color.blue,
foreground: color.white,
},
press: {
border: color.activeBlue,
background: color.activeBlue,
foreground: color.white,
},
},
// Inverse is meant for use on secondary controls.
progressiveInverse: {
default: {
border: border.strong,
background: color.white,
foreground: color.blue,
},
hover: {
border: color.blue,
background: color.white,
foreground: color.blue,
},
press: {
border: color.activeBlue,
background: color.fadedBlue,
foreground: color.activeBlue,
},
},
destructive: {
default: color.red,
active: color.activeRed,
default: {
border: "transparent",
background: color.red,
foreground: color.white,
},
hover: {
border: color.red,
background: color.white,
foreground: color.red,
},
press: {
border: color.activeRed,
background: color.activeRed,
foreground: color.white,
},
},
destructiveInverse: {
default: {
border: border.strong,
background: color.white,
foreground: color.red,
},
hover: {
border: color.red,
background: color.white,
foreground: color.red,
},
press: {
border: color.activeRed,
background: color.fadedRed,
foreground: color.activeRed,
},
},
disabled: {
default: color.fadedOffBlack32,
Expand Down Expand Up @@ -71,12 +140,7 @@ export const semanticColor = {
* elements would use -Primary, rows and layout elements use -Subtle and
* -Strong for when 3:1 contrast is a priority (ex. form elements)
*/
border: {
primary: color.fadedOffBlack16,
subtle: color.fadedOffBlack8,
strong: color.fadedOffBlack50,
inverse: color.white,
},
border: border,
/**
* Default icon colors that change in context (like actions).
*/
Expand Down

0 comments on commit a036e68

Please sign in to comment.