diff --git a/README.md b/README.md index 69f8d06..79fb647 100644 --- a/README.md +++ b/README.md @@ -36,32 +36,59 @@ export default function MyRootApp() { The error boundary is optional but highly recommended. -## Styles customization +# Styles customization -SX Design leverages full power of [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) as a main way of style customization. You can optionally adjust the values if you want from your application. Here are some component specific default values (not dependent on dark mode): +SX Design leverages full power of [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) as a main way of style customization. You can optionally adjust the values if you want from your application. Here are some component specific default values and colors (not dependent on dark mode): ```text --sx-kbd-border: 1px solid #b4b4b4 ---sx-money-text-color: var(--sx-text-color) ¹ ---sx-skipLink-background-color: 28, 30, 33 ² ---sx-skipLink-text-color: 255, 255, 255 +--sx-money-text-color: var(--sx-foreground) ¹ + +--sx-error-lighter: 247, 212, 214 ² +--sx-error-light: 255, 26, 26 +--sx-error: 238, 0, 0 +--sx-error-dark: 197, 0, 0 + +--sx-success-lighter: 211, 229, 255 +--sx-success-light: 50, 145, 255 +--sx-success: 0, 112, 243 +--sx-success-dark: 7, 97, 209 + +--sx-warning-lighter: 255, 239, 207 +--sx-warning-light: 247, 185, 85 +--sx-warning: 245, 166, 35 +--sx-warning-dark: 171, 87, 10 ``` Generic default values for light mode: ```text ---sx-background-color: 255, 255, 255 ² ---sx-text-color: 28, 30, 33 +--sx-background: 255, 255, 255 ² +--sx-accent-1: 227, 227, 227 +--sx-accent-2: 198, 199, 200 +--sx-accent-3: 170, 171, 172 +--sx-accent-4: 142, 143, 144 +--sx-accent-5: 113, 114, 116 +--sx-accent-6: 85, 86, 89 +--sx-accent-7: 56, 58, 61 +--sx-foreground: 28, 30, 33 --sx-text-link-color: 3, 102, 214 ``` And finally generic default values for dark mode: ```text ---sx-background-color: 51, 51, 51 ² ---sx-text-color: 255, 255, 255 +--sx-background: 51, 51, 51 ² +--sx-accent-1: 77, 77, 77 +--sx-accent-2: 102, 102, 102 +--sx-accent-3: 128, 128, 128 +--sx-accent-4: 153, 153, 153 +--sx-accent-5: 179, 179, 179 +--sx-accent-6: 204, 204, 204 +--sx-accent-7: 230, 230, 230 +--sx-foreground: 255, 255, 255 --sx-text-link-color: 88, 166, 255 ``` @@ -78,7 +105,7 @@ export default function MyComponent() { } ``` -## Available components +# Available components **🚧 WORK in PROGRESS 🚧** @@ -89,28 +116,72 @@ Legend: 🧐 not evaluated/ready yet ``` -| Component | Localized? | Dark mode? | Has stories? | Tested? | -| ------------------- | :--------: | :--------: | :----------: | :-----: | -| `` | ✅ | ✅ | ✅ | 🧐 | -| `` | ✅ | ✅ | 🧐 | ✅ | -| `` | ✅ | ✅ | ✅ | ✅ | -| `` | ✅ | ✅ | ✅ | ✅ | -| `` | ✅ | ✅ | ✅ | 🧐 | -| `` | ✅ | ✅ | ✅ | 🧐 | -| `` | ✅ | ✅ | 🧐 | ✅ | -| `` | ✅ | ✅ | ✅ | 🧐 | -| `
` | ✅ | ✅ | ✅ | 🧐 | -| `` | ✅ | ✅ | ✅ | 🧐 | -| `` | ✅ | 🧐 | 🧐 | 🧐 | +| Component | Localized?¹ | Dark mode?² | Has stories?³ | Tested?⁴ | +| ------------------- | :---------: | :---------: | :-----------: | :------: | +| `` | ✅ | ✅ | ✅ | 🧐 | +| `` | ✅ | ✅ | 🧐 | ✅ | +| `` | ✅ | ✅ | ✅ | ✅ | +| `` | ✅ | ✅ | ✅ | ✅ | +| `` | ✅ | ✅ | ✅ | 🧐 | +| `` | ✅ | ✅ | ✅ | 🧐 | +| `` | ✅ | ✅ | 🧐 | ✅ | +| `` | ✅ | ✅ | ✅ | 🧐 | +| `
` | ✅ | ✅ | ✅ | 🧐 | +| `` | ✅ | ✅ | ✅ | 🧐 | +| `` | ✅ | 🧐 | 🧐 | 🧐 | _Did you find a mistake in this table? Please, [report is as an issue](https://github.com/adeira/universe/issues/new)._ -## Development +¹ Localized means that it's either translated by us or the component inputs are (Flow) typed in a way that encourages passing translated strings instead of plain strings. -To start storybook run: +² Component should look fine in both light and dark mode. + +³ There are stories in the [Storybook](https://sx-design.vercel.app/) and these stories are somehow useful and explanatory. + +⁴ There are tests available to make sure that the component works as expected and we won't break it by accident. + +# Development + +## Storybook + +The easiest way how to develop these components is to run a Storybook: ```bash yarn workspace @adeira/sx-design storybook ``` Please, make sure that any changes still follow the core values of this project and the matrix of available components was updated accordingly. + +## Working with SX Design colors + +It's recommended to use [`pastel`](https://github.com/sharkdp/pastel) when working with the SX Design colors: + +```bash +brew install pastel +``` + +SX Design commonly uses colors written as triplets of values from 0 to 255. Here is how you can convert these triplets back and forth: + +```bash +pastel color "28, 30, 33" +pastel format hex "28, 30, 33" +``` + +To generate colors gradient run: + +```bash +pastel gradient -n 9 '255, 255, 255' '28, 30, 33' +pastel gradient -s rgb -n 9 '255, 255, 255' '28, 30, 33' | pastel format rgb +``` + +Another interesting command for checking colors with simulated colorblindness: + +```bash +pastel colorblind deuter "247,212,214" "255,26,26" "238,0,0" "197,0,0" +``` + +For more info run: + +```bash +pastel --help +``` diff --git a/src/ErrorBoundary/ErrorBoundary.js b/src/ErrorBoundary/ErrorBoundary.js index d6d0082..e5228a1 100644 --- a/src/ErrorBoundary/ErrorBoundary.js +++ b/src/ErrorBoundary/ErrorBoundary.js @@ -80,8 +80,8 @@ export default class ErrorBoundary extends React.Component { const styles = sx.create({ error: { - color: 'rgb(var(--sx-text-color))', - background: 'rgb(var(--sx-background-color))', + color: 'rgb(var(--sx-foreground))', + background: 'rgb(var(--sx-background))', fontFamily: '-apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif', height: '100vh', @@ -100,7 +100,7 @@ const styles = sx.create({ }, h1: { display: 'inline-block', - borderRight: '1px solid rgba(var(--sx-text-color), 0.3)', + borderRight: '1px solid rgba(var(--sx-foreground), 0.3)', margin: 0, marginRight: 20, padding: '10px 23px 10px 0', diff --git a/src/Heading/Heading.js b/src/Heading/Heading.js index a769aff..d59287f 100644 --- a/src/Heading/Heading.js +++ b/src/Heading/Heading.js @@ -32,6 +32,6 @@ export default function Heading(props: Props): React.Node { const styles = sx.create({ heading: { - color: 'rgba(var(--sx-text-color))', + color: 'rgba(var(--sx-foreground))', }, }); diff --git a/src/Heading/__tests__/Heading.test.js b/src/Heading/__tests__/Heading.test.js index db7d5a8..c898536 100644 --- a/src/Heading/__tests__/Heading.test.js +++ b/src/Heading/__tests__/Heading.test.js @@ -9,7 +9,7 @@ import Section from '../../Section/Section'; it('renders top level by default', () => { const { container } = render(level one); - expect(container.innerHTML).toMatchInlineSnapshot(`"

level one

"`); + expect(container.innerHTML).toMatchInlineSnapshot(`"

level one

"`); }); it('renders H1 tags in parallel', () => { @@ -20,7 +20,7 @@ it('renders H1 tags in parallel', () => { , ); expect(container.innerHTML).toMatchInlineSnapshot( - `"

level one

level one

"`, + `"

level one

level one

"`, ); }); diff --git a/src/Heading/__tests__/__snapshots__/Heading.test.js.snap b/src/Heading/__tests__/__snapshots__/Heading.test.js.snap index 3469c16..153a9c2 100644 --- a/src/Heading/__tests__/__snapshots__/Heading.test.js.snap +++ b/src/Heading/__tests__/__snapshots__/Heading.test.js.snap @@ -1,30 +1,30 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders maximum 6 levels 1`] = ` -"

level one

-
-

level two

-
-

level three

-
-

level four

-
-
level five
-
-
level six
-
-
level six again
-
level six again
+"

level one

+
+

level two

+
+

level three

+
+

level four

+
+
level five
+
+
level six
+
+
level six again
+
level six again
-
level six
+
level six
-
level five
+
level five
-

level four

+

level four

-

level three

+

level three

-

level two

+

level two

" `; diff --git a/src/Kbd/Kbd.js b/src/Kbd/Kbd.js index 6eecdcb..5292e90 100644 --- a/src/Kbd/Kbd.js +++ b/src/Kbd/Kbd.js @@ -29,7 +29,7 @@ const styles = sx.create({ kbd: { borderRadius: '3px', border: 'var(--sx-kbd-border, 1px solid #b4b4b4)', - color: 'rgba(var(--sx-text-color))', + color: 'rgba(var(--sx-foreground))', display: 'inline-block', fontSize: '0.85em', fontWeight: '700', diff --git a/src/Money/Money.js b/src/Money/Money.js index de8a4f6..2b26f76 100644 --- a/src/Money/Money.js +++ b/src/Money/Money.js @@ -25,7 +25,7 @@ export default function Money(props: MoneyProps): React.Node { const styles = sx.create({ text: { - color: 'rgba(var(--sx-money-text-color, var(--sx-text-color)))', + color: 'rgba(var(--sx-money-text-color, var(--sx-foreground)))', transition: 'inherit', }, }); diff --git a/src/ProductCard/ProductCard.js b/src/ProductCard/ProductCard.js index f63a500..931ea56 100644 --- a/src/ProductCard/ProductCard.js +++ b/src/ProductCard/ProductCard.js @@ -133,14 +133,14 @@ const styles = sx.create({ padding: '1rem', }, highlight: { - 'color': 'rgba(var(--sx-text-color))', - 'backgroundColor': 'rgba(var(--sx-background-color))', - '--sx-money-text-color': 'var(--sx-text-color)', + 'color': 'rgba(var(--sx-foreground))', + 'backgroundColor': 'rgba(var(--sx-background))', + '--sx-money-text-color': 'var(--sx-foreground)', }, highlightHover: { - 'color': 'rgba(var(--sx-background-color))', - 'backgroundColor': 'rgba(var(--sx-text-color))', - '--sx-money-text-color': 'var(--sx-background-color)', + 'color': 'rgba(var(--sx-background))', + 'backgroundColor': 'rgba(var(--sx-foreground))', + '--sx-money-text-color': 'var(--sx-background)', }, heading: { margin: 0, diff --git a/src/Section/Section.js b/src/Section/Section.js index aa94148..183b6d1 100644 --- a/src/Section/Section.js +++ b/src/Section/Section.js @@ -28,6 +28,6 @@ export default function Section(props: Props): React.Node { const styles = sx.create({ section: { - color: 'rgba(var(--sx-text-color))', + color: 'rgba(var(--sx-foreground))', }, }); diff --git a/src/SkipLink/SkipLink.js b/src/SkipLink/SkipLink.js index ac0d4ef..c745e42 100644 --- a/src/SkipLink/SkipLink.js +++ b/src/SkipLink/SkipLink.js @@ -21,8 +21,9 @@ const styles = sx.create({ 'position': 'absolute', 'top': -40, 'left': 0, - 'background': 'rgba(var(--sx-skipLink-background-color))', - 'color': 'rgba(var(--sx-skipLink-text-color))', + // the colors are flipped on purpose so it's visible in light/dark mode + 'background': 'rgba(var(--sx-foreground))', + 'color': 'rgba(var(--sx-background))', 'padding': 8, 'zIndex': 100, ':focus': { diff --git a/src/SxDesignProviderCSSVariables.js b/src/SxDesignProviderCSSVariables.js index 379809f..66d9ce6 100644 --- a/src/SxDesignProviderCSSVariables.js +++ b/src/SxDesignProviderCSSVariables.js @@ -3,13 +3,13 @@ * apply alpha channel when needed (https://stackoverflow.com/a/41265350). Usage: * * ```js - * { color: 'rgba(var(--sx-text-color))' } + * { color: 'rgba(var(--sx-foreground))' } * ``` * * With optional alpha channel: * * ```js - * { color: 'rgba(var(--sx-text-color), 0.5)' } + * { color: 'rgba(var(--sx-foreground), 0.5)' } * ``` * * @flow @@ -17,18 +17,49 @@ export default { // Check and update README.md as well! + // https://coolors.co/generate common: { - '--sx-skipLink-background-color': '28, 30, 33', - '--sx-skipLink-text-color': '255, 255, 255', + '--sx-error-lighter': '247, 212, 214', + '--sx-error-light': '255, 26, 26', + '--sx-error': '238, 0, 0', + '--sx-error-dark': '197, 0, 0', + + '--sx-success-lighter': '211, 229, 255', + '--sx-success-light': '50, 145, 255', + '--sx-success': '0, 112, 243', + '--sx-success-dark': '7, 97, 209', + + '--sx-warning-lighter': '255, 239, 207', + '--sx-warning-light': '247, 185, 85', + '--sx-warning': '245, 166, 35', + '--sx-warning-dark': '171, 87, 10', }, lightTheme: { - '--sx-background-color': '255, 255, 255', - '--sx-text-color': '28, 30, 33', - '--sx-text-link-color': '3, 102, 214', + '--sx-background': '255, 255, 255', // lighter + '--sx-accent-1': '227, 227, 227', + '--sx-accent-2': '198, 199, 200', + '--sx-accent-3': '170, 171, 172', + '--sx-accent-4': '142, 143, 144', + '--sx-accent-5': '113, 114, 116', + '--sx-accent-6': '85, 86, 89', + '--sx-accent-7': '56, 58, 61', + '--sx-foreground': '28, 30, 33', // darker + + // + '--sx-text-link-color': '3, 102, 214', // TODO: naming (?) }, darkTheme: { - '--sx-background-color': '51, 51, 51', - '--sx-text-color': '255, 255, 255', - '--sx-text-link-color': '88, 166, 255', + '--sx-background': '51, 51, 51', + '--sx-accent-1': '77, 77, 77', + '--sx-accent-2': '102, 102, 102', + '--sx-accent-3': '128, 128, 128', + '--sx-accent-4': '153, 153, 153', + '--sx-accent-5': '179, 179, 179', + '--sx-accent-6': '204, 204, 204', + '--sx-accent-7': '230, 230, 230', + '--sx-foreground': '255, 255, 255', + + // + '--sx-text-link-color': '88, 166, 255', // TODO: naming (?) }, }; diff --git a/src/stories/ColorShowcase.js b/src/stories/ColorShowcase.js new file mode 100644 index 0000000..0c1085e --- /dev/null +++ b/src/stories/ColorShowcase.js @@ -0,0 +1,23 @@ +// @flow strict + +import * as React from 'react'; + +type Props = { + +color: string, +}; + +export default function ColorShowcase(props: Props): React.Node { + return ( +
+ {props.color} +
+ ); +} diff --git a/src/stories/Colors.stories.mdx b/src/stories/Colors.stories.mdx new file mode 100644 index 0000000..1d2bb71 --- /dev/null +++ b/src/stories/Colors.stories.mdx @@ -0,0 +1,64 @@ +import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks'; +import SxDesignProvider from '../SxDesignProvider'; +import ColorShowcase from './ColorShowcase'; + + + +# Colors showcase + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + colors for light theme + + + + + + + + + + + + + + + colors for dark theme (it's not a simple reverse of light mode) + + + + + + + + + + + diff --git a/src/stories/Introduction.stories.mdx b/src/stories/Introduction.stories.mdx index 8b069c4..2484e58 100644 --- a/src/stories/Introduction.stories.mdx +++ b/src/stories/Introduction.stories.mdx @@ -8,7 +8,7 @@ import Plugin from './assets/plugin.svg'; import Repo from './assets/repo.svg'; import StackAlt from './assets/stackalt.svg'; - +