Skip to content
This repository has been archived by the owner on Nov 26, 2024. It is now read-only.

chore: adding initial json generated from figma variables #673

Merged
merged 5 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions docs/BrandColors.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import tokens from '../src/figma/tokens.json';
import { brandColor } from '../src/js';
import getCSSVariablesFromStylesheet from './utils/getCSSVariablesFromStylesheet';
import { brandColor as brandColorJS } from '../src/js';
import { getCSSVariablesFromStylesheet, useJsonColor } from './utils';
import { ColorSwatchGroup, ColorSwatch } from './components';
import README from './BrandColors.mdx';

Expand All @@ -21,7 +20,10 @@ export default meta;
type Story = StoryObj<typeof ColorSwatchGroup>;

export const Figma: Story = {
render: () => <ColorSwatchGroup swatchData={tokens.global.brandColors} />,
render: () => {
const { brandColor } = useJsonColor();
return <ColorSwatchGroup swatchData={brandColor} />;
},
};

export const CSS: Story = {
Expand Down Expand Up @@ -54,7 +56,7 @@ export const JS: Story = {
}}
>
{/* Mapping through each brand color and rendering a ColorSwatch component for it */}
{Object.entries(brandColor).map(([name, color]) => (
{Object.entries(brandColorJS).map(([name, color]) => (
<ColorSwatch key={name} color={color} name={`brandColor.${name}`} />
))}
</div>
Expand Down
2 changes: 1 addition & 1 deletion docs/ThemeColors.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Canvas } from '@storybook/addon-docs/blocks';
import { Canvas } from '@storybook/blocks';
import * as ThemeColorStories from './ThemeColors.stories';

# Theme Colors (second tier)
Expand Down
77 changes: 40 additions & 37 deletions docs/ThemeColors.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React from 'react';
import tokens from '../src/figma/tokens.json';
import { lightTheme, darkTheme } from '../src';
import getCSSVariablesFromStylesheet from './utils/getCSSVariablesFromStylesheet';

import { ColorSwatchGroup, ColorSwatch } from './components';

import { lightTheme as lightThemeJS, darkTheme as darkThemeJS } from '../src';
import brandColor from '../src/figma/brandColors.json';
import { ColorSwatch, ColorSwatchGroup } from './components';
import README from './ThemeColors.mdx';
import { getCSSVariablesFromStylesheet, useJsonColor } from './utils';

export default {
title: 'Colors/Theme Colors',
Expand All @@ -18,39 +17,43 @@ export default {
};

export const FigmaLightTheme = {
render: () => <ColorSwatchGroup {...FigmaLightTheme.args} />,
args: {
swatchData: tokens.light.colors,
borderColor: tokens.light.colors.border.muted.value,
textBackgroundColor: tokens.light.colors.background.default.value,
textColor: tokens.light.colors.text.default.value,
render: () => {
const { lightTheme } = useJsonColor();
if (!lightTheme) {
return null; // or some fallback component
}
console.log('lightTheme', lightTheme);
return <ColorSwatchGroup swatchData={lightTheme} />;
},
};

export const FigmaDarkTheme = {
render: () => (
<div
style={{
backgroundColor: tokens.dark.colors.background.default.value,
margin: '-1rem',
padding: '1rem',
}}
>
<ColorSwatchGroup {...FigmaDarkTheme.args} />
</div>
),
args: {
swatchData: tokens.dark.colors,
borderColor: tokens.dark.colors.border.muted.value,
textBackgroundColor: tokens.dark.colors.background.default.value,
textColor: tokens.dark.colors.text.default.value,
render: () => {
const { darkTheme } = useJsonColor();
console.log('darkTheme', darkTheme);
if (!darkTheme) {
return null; // or some fallback component
}
return (
<div
style={{
margin: '-1rem',
padding: '1rem',
}}
>
<ColorSwatchGroup
swatchData={darkTheme}
borderColor={darkTheme.border.muted.value}
textBackgroundColor={darkTheme.background.default.value}
textColor={darkTheme.text.default.value}
/>
</div>
);
},
parameters: {
backgrounds: {
default: 'dark',
values: [
{ name: 'dark', value: tokens.dark.colors.background.default.value },
],
values: [{ name: 'dark', value: brandColor.grey[800].value }],
},
},
};
Expand Down Expand Up @@ -136,7 +139,7 @@ export const JSLightTheme = {
gridTemplateColumns: 'repeat(auto-fill, 300px)',
}}
>
{Object.entries(lightTheme.colors).flatMap(([category, colorObj]) =>
{Object.entries(lightThemeJS.colors).flatMap(([category, colorObj]) =>
Object.entries(colorObj).map(([name, color]) => (
<ColorSwatch
key={`${category}-${name}`}
Expand All @@ -153,7 +156,7 @@ export const JSDarkTheme = {
render: () => (
<div
style={{
backgroundColor: darkTheme.colors.background.default,
backgroundColor: darkThemeJS.colors.background.default,
margin: '-1rem',
padding: '1rem',
}}
Expand All @@ -165,15 +168,15 @@ export const JSDarkTheme = {
gridTemplateColumns: 'repeat(auto-fill, 300px)',
}}
>
{Object.entries(darkTheme.colors).flatMap(([category, colorObj]) =>
{Object.entries(darkThemeJS.colors).flatMap(([category, colorObj]) =>
Object.entries(colorObj).map(([name, color]) => (
<ColorSwatch
key={`${category}-${name}`}
color={color}
name={`color.${category}.${name}`}
borderColor={darkTheme.colors.border.muted}
textBackgroundColor={darkTheme.colors.background.default}
textColor={darkTheme.colors.text.default}
borderColor={darkThemeJS.colors.border.muted}
textBackgroundColor={darkThemeJS.colors.background.default}
textColor={darkThemeJS.colors.text.default}
/>
)),
)}
Expand All @@ -183,7 +186,7 @@ export const JSDarkTheme = {
parameters: {
backgrounds: {
default: 'dark',
values: [{ name: 'dark', value: darkTheme.colors.background.default }],
values: [{ name: 'dark', value: darkThemeJS.colors.background.default }],
},
},
};
4 changes: 2 additions & 2 deletions docs/components/ColorSwatch/ColorSwatch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const ColorSwatch: FunctionComponent<ColorSwatchProps> = ({
style={{
height: 120,
backgroundColor: color,
border: `1px solid ${borderColor}`,
border: `2px solid ${borderColor}`,
display: 'flex',
flexDirection: 'column-reverse',
borderRadius: '8px',
Expand All @@ -48,7 +48,7 @@ export const ColorSwatch: FunctionComponent<ColorSwatchProps> = ({
style={{
backgroundColor: textBackgroundColor,
padding: 8,
borderRadius: '0 0 8px 8px',
borderRadius: '0 0 6px 6px',
color: textColor,
}}
>
Expand Down
23 changes: 2 additions & 21 deletions docs/components/ColorSwatchGroup/ColorSwatchGroup.tsx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh this is going to be a fun merge conflict for me... 🙃

Original file line number Diff line number Diff line change
@@ -1,31 +1,12 @@
import React, { FunctionComponent } from 'react';

import { Theme } from '../../utils/useJsonColor';
import { ColorSwatch } from '..';

interface ColorToken {
/**
* The value of the color can be hex or a reference to another color using
* the Figma Token reference syntax {colors.blue.blue500} or using maths
* notation rgba($colors.blue.blue500, .5)
*/
value: string;
/**
* The description of the color and what is should be used for
*/
description?: string;
/**
* The type of token
*/
type: 'color';
}

interface ColorSwatchGroupProps {
/**
* The color object
*/
swatchData: {
[key: string]: ColorToken;
};
swatchData: Theme;
/**
* The color of text background that contains the name of the color defaults to background.default
*/
Expand Down
6 changes: 2 additions & 4 deletions docs/utils/getCSSVariablesFromStylesheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type Color = {
* @param varPrefix - The prefix of the CSS variables to retrieve.
* @returns An object containing the retrieved CSS variables.
*/
function getCSSVariablesFromStylesheet(varPrefix: string): Color {
export const getCSSVariablesFromStylesheet = (varPrefix: string): Color => {
const cssVariables: Color = {};

Array.from(document.styleSheets)
Expand Down Expand Up @@ -41,6 +41,4 @@ function getCSSVariablesFromStylesheet(varPrefix: string): Color {
});

return cssVariables;
}

export default getCSSVariablesFromStylesheet;
};
2 changes: 2 additions & 0 deletions docs/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { getCSSVariablesFromStylesheet } from './getCSSVariablesFromStylesheet';
export { useJsonColor } from './useJsonColor';
100 changes: 100 additions & 0 deletions docs/utils/useJsonColor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { useEffect, useState } from 'react';

import figmaBrandColors from '../../src/figma/brandColors.json';
import figmaDarkTheme from '../../src/figma/darkTheme.json';
import figmaLightTheme from '../../src/figma/lightTheme.json';

export type ColorDetails = {
value: string; // Hex value or alias to another color
type: string; // Type usually color
parent: string; // Parent category or group of the color
description: string; // Description or notes about the color
};

export type ColorPalette = {
[shade: string]: ColorDetails;
};

export type Theme = {
[colorName: string]: ColorPalette;
};

type CompiledColors = {
[themeName: string]: Theme;
};

/**
* Custom hook for compiling color themes from Figma JSON definitions.
* Merges brand, light, and dark theme color settings into a single object.
*
* @returns Object containing compiled color themes.
*/
export const useJsonColor = (): CompiledColors => {
const [colors, setColors] = useState<CompiledColors>({});

useEffect(() => {
/**
* Parses a referenced color value and resolves it based on the current theme.
* If the value is a reference (enclosed in curly braces), it navigates through the theme object.
*
* @param value - The color value or reference to resolve.
* @param theme - The theme object to resolve references against.
* @returns The resolved color value.
*/
const parseColorValue = (value: string, theme: Theme): string => {
if (value.startsWith('{') && value.endsWith('}')) {
const path = value.slice(1, -1).split('.');
let current: any = theme;
for (const segment of path) {
current = current[segment];
if (!current) {
return value; // Return original value if resolution fails.
}
}
return current.value; // Return the resolved color value.
}
return value; // Return the direct value if not a reference.
};

/**
* Compiles color themes from provided JSON theme definitions.
* Each color value is checked and potentially resolved using parseColorValue.
*
* @param themes - Object containing various theme definitions.
* @returns Object containing compiled and resolved themes.
*/
const compileColors = (themes: {
[key: string]: Theme;
}): CompiledColors => {
const compiledColors: CompiledColors = {};
Object.entries(themes).forEach(([themeName, theme]) => {
compiledColors[themeName] = {};
Object.entries(theme).forEach(([colorName, colorValues]) => {
compiledColors[themeName][colorName] = {};
Object.entries(colorValues).forEach(([shade, details]) => {
const { value, description } = details;
const resolvedValue = parseColorValue(value, figmaBrandColors);
compiledColors[themeName][colorName][shade] = {
...details,
value: resolvedValue,
description:
description +
(value === resolvedValue ? '' : ` Alias: ${value}`),
};
});
});
});
return compiledColors;
};

// Compile all color themes into a single object and update the state
const allColors = compileColors({
brandColor: { ...figmaBrandColors },
lightTheme: figmaLightTheme,
darkTheme: figmaDarkTheme,
});
setColors(allColors);
}, []);

return colors;
};
4 changes: 3 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"noErrorTruncation": true,
"noUncheckedIndexedAccess": true,
"strict": true,
"target": "es2020"
"target": "es2020",
"resolveJsonModule": true,
"jsx": "react"
},
"exclude": ["./dist", "**/node_modules"]
}
Loading