diff --git a/README.md b/README.md index e6e6fbf..003aa70 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ An optimized and creative theming solution that generates CSS variables based on > Please note that [react](https://www.npmjs.com/package/react) >= 17 and [react-dom](https://www.npmjs.com/package/react-dom) >= 17 are peer dependencies. Run the following script to install and save in your `package.json` dependencies: + ```bash # with npm npm install react-design-tokens @@ -22,36 +23,85 @@ pnpm add react-design-tokens
-## API - -The exposed APIs: - -- `createTheming(defaultTheme, config?) => { useTheme, getVariablesAsStyles, ThemeProvider }`\ -The main exposed API which will return:\ -`useTheme`: A React Hook to hook into the provided theme object.\ -`ThemeProvider`: A React Context Provider to provide the theme object down the tree and also populate the generated CSS variables for it's children. -`getVariablesAsStyles`: A helper function that gets a theme object and returns its CSS variables as inline `style` DOM property. (Useful when you want to opt-in `initializeVariablesOnHTMLRoot` and you also want your variables to be attached to `:root` during SSR) - - `defaultTheme`\ - The default theme which will be used as `ThemeContext`'s default value. - - `config` [optional]\ - The theming configuration object. - - `config.cssVariableGenerator` [optional]\ - The function which is being used to generate CSS variables based on the provided theme object. - - `config.initializeVariablesOnHTMLRoot` [optional | default: `false`]\ - If set to `true`, initial `` will attach CSS variables to the HTML element (Also known as `:root`). - -- `defaultCssVariableGenerator(tokenFamilyKey, tokenPath, tokenValue)`\ -The default CSS variable generate function. The generated variables obey the following rules:\ -1- Values that are not of type `string` or `number` will be omitted.\ -2- `number` values will be converted into `{tokenValue}px`.\ -3- Overall variable string: `{path-to-token}: {tokenValue}` - - `tokenFamilyKey`\ - The key of a root token family. - - `tokenPath`\ - The dot-separated path to the token from which the root key has been omitted. - - `tokenValue`\ - The value of the token. +## API Documentation + +The library exposes two APIs, `create` and `defaultCSSVariableGenerator`: + +### 1. `create(variants, config?): { useTokens, VariantSelector, generateCSSVariablesAsInlineStyle }` + +This is the main API exposed by the library. It will take your variants map and an optional config options to create your theming client. + +The `config` options are: + +| Property Name | Type | Default | Description | +|---------------|------|---------|-------------| +| cssVariableGenerator | `context => ({ variableName: string; variableValue: string; } \| null)` | `defaultCSSVariableGenerator` | The function which is being used to generate CSS variables based on the provided variants map. | + +The theming client consists of: + +#### ``: + +A wrapper component which will activate a variant for the tree it's wrapping. The properties are: + +| Property Name | Type | Default | Description | +|---------------|------|---------|-------------| +| children? | `React.ReactNode` | - | The content of the component. | +| disableCSSVariableGeneration? | `boolean` | `false` | If `true`, CSS variable generation will be disabled.
Useful when you are manually controlling or populating CSS variables using `generateCSSVariablesAsInlineStyle`. | +| variant | `string` | - | The variant to be activated. It has to be a valid variant key that exists in the provided variants map. | + +#### `useTokens()`: + +A React hook to use in a component that is descendant of `` wrapper. It returns the tokens of the selected variant. + +#### `generateCSSVariablesAsInlineStyle(variant)`: + +A helper function to generate CSS variables in valid CSS syntax (`--variable=value`). It is helpful when you want to manually control the population of the CSS variables (e.g. Put initial tokens on html tag with ``) + +### 2. `defaultCSSVariableGenerator(context): { variableName: string; variableValue: string } | null` + +The default CSS variable generate function. The generated variables obey the following rules: +- Values that are not of type `string` or `number` will be omitted (returns `null`). +- Values of type `number` will be converted into `{tokenValue}px`. +- The generated variable format: `{ variableName: 'PATH-TO-TOKEN', variableValue: 'tokenValue' }` + +The `context` consists of: +#### `context.tokenFamilyKey`: + +The key of a root token family. + +For example, The `colors` key is a `tokenFamilyKey` in the following variants map: + +```ts +{ + dark: { + colors: { + primary: {}, + secondary: {}, + // ... + } + }, + light: { + colors: { + primary: {}, + secondary: {}, + // ... + } + }, +} +``` + +#### `context.tokenKey`: + +The key (name) of the token. + +#### `context.tokenValue`: + +The value of the token. + +#### `context.tokenPath`: + +The dot-separated path to the token from which the root key has been omitted.
@@ -59,139 +109,185 @@ The default CSS variable generate function. The generated variables obey the fol To getting started, all you need to do is: -1. Create your own theme: +1. Create your own variants map: + ```ts // theming.ts -export const theme = { - colors: { - primary: { - base: "1", - hover: "2", - active: "3", - disabled: "4" - }, - secondary: { - base: "5", - hover: "6", - active: "7", - disabled: "8" +const variants = { + dark: { + colors: { + primary: { + base: "d1", + hover: "d2", + active: "d3", + disabled: "d4", + }, + secondary: { + base: "d5", + hover: "d6", + active: "d7", + disabled: "d8", + }, + neutral: { + text: { + base: "d9", + secondary: "d10", + tertiary: "d11", + }, + background: { + base: "d12", + container: "d13", + elevated: "d14", + }, + }, }, - neutral: { - text: { - base: "9", - secondary: "10", - tertiary: "11" + }, + light: { + colors: { + primary: { + base: "l1", + hover: "l2", + active: "l3", + disabled: "l4", }, - background: { - base: "12", - container: "13", - elevated: "14" - } - } + secondary: { + base: "l5", + hover: "l6", + active: "l7", + disabled: "l8", + }, + neutral: { + text: { + base: "l9", + secondary: "l10", + tertiary: "l11", + }, + background: { + base: "l12", + container: "l13", + elevated: "l14", + }, + }, + }, }, - dark: 1 }; - -export type Theme = typeof theme; ``` -2. Create a theming client for your theme: \ -(We recommend to create a theming for each theme object) +2. Create a theming client: + ```ts // theming.ts -import { createTheming } from "react-design-tokens"; - -export const theme = { - colors: { - primary: { - base: "1", - hover: "2", - active: "3", - disabled: "4" - }, - secondary: { - base: "5", - hover: "6", - active: "7", - disabled: "8" + +import { create } from "react-design-tokens"; + +const variants = { + dark: { + colors: { + primary: { + base: "d1", + hover: "d2", + active: "d3", + disabled: "d4", + }, + secondary: { + base: "d5", + hover: "d6", + active: "d7", + disabled: "d8", + }, + neutral: { + text: { + base: "d9", + secondary: "d10", + tertiary: "d11", + }, + background: { + base: "d12", + container: "d13", + elevated: "d14", + }, + }, }, - neutral: { - text: { - base: "9", - secondary: "10", - tertiary: "11" + }, + light: { + colors: { + primary: { + base: "l1", + hover: "l2", + active: "l3", + disabled: "l4", }, - background: { - base: "12", - container: "13", - elevated: "14" - } - } + secondary: { + base: "l5", + hover: "l6", + active: "l7", + disabled: "l8", + }, + neutral: { + text: { + base: "l9", + secondary: "l10", + tertiary: "l11", + }, + background: { + base: "l12", + container: "l13", + elevated: "l14", + }, + }, + }, }, - dark: 1 }; -export type Theme = typeof theme; - -export const { ThemeProvider, useTheme } = createTheming(theme); +export const { useTokens, VariantSelector, generateCSSVariablesAsInlineStyle } = create(variants); ``` -3. Provide the theme: +3. Use the theme variants: + ```tsx // App.tsx -import { ThemeProvider, theme } from "./theming"; +import { VariantSelector } from "./theming"; const App = () => { return ( - - {/* Components */} - + + + {/* Components with dark variant tokens */} + + + + {/* Components with light variant tokens */} + + + ); } export default App; ``` -4. You can now access the `theme` object down the tree using `useTheme` hook. Also you have access to the generated CSS variables in your CSS. +4. You can now access the tokens down the tree using `useTokens` hook. Also you have access to the generated CSS variables in your CSS. -The CSS variables generated for this theme with default configuration are as follows: -``` ---colors-primary-base: 1; ---colors-primary-hover: 2; ---colors-primary-active: 3; ---colors-primary-disabled: 4; ---colors-secondary-base: 5; ---colors-secondary-hover: 6; ---colors-secondary-active: 7; ---colors-secondary-disabled: 8; ---colors-neutral-text-base: 9; ---colors-neutral-text-secondary: 10; ---colors-neutral-text-tertiary: 11; ---colors-neutral-background-base: 12; ---colors-neutral-background-container: 13; ---colors-neutral-background-elevated: 14; ---dark: 1px; -``` +The CSS variables generated for this variants map with default configuration set and the `dark` variant being selected is: -
- -## Notes - -- You can only access the CSS variables in a sub-tree which is being wrapped with `ThemeProvider`. (In other words, each sub-tree has it's own CSS variables) - -- Inner theme objects will be merged with outer theme objects. So to override an outer theme, just provide the tokens you want to change in the child-tree: -```tsx - - - - ``` - -
+--colors-primary-base: d1; +--colors-primary-hover: d2; +--colors-primary-active: d3; +--colors-primary-disabled: d4; +--colors-secondary-base: d5; +--colors-secondary-hover: d6; +--colors-secondary-active: d7; +--colors-secondary-disabled: d8; +--colors-neutral-text-base: d9; +--colors-neutral-text-secondary: d10; +--colors-neutral-text-tertiary: d11; +--colors-neutral-background-base: d12; +--colors-neutral-background-container: d13; +--colors-neutral-background-elevated: d14; +``` ## Contributing