├── .changeset ├── README.md └── config.json ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github └── workflows │ └── release.yml ├── .gitignore ├── .npmignore ├── .prettierrc ├── .styleguidist ├── StyleguideProvider.tsx └── setup.js ├── LICENSE ├── Readme.md ├── babel.config.js ├── package.json ├── packages ├── components │ ├── @types │ │ └── styled.d.ts │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── interactiveComponentStates.tsx │ │ ├── primitives │ │ ├── Box.md │ │ ├── Box.tsx │ │ ├── Button.md │ │ ├── Button.tsx │ │ ├── Checkbox.md │ │ ├── Checkbox.tsx │ │ ├── Flex.md │ │ ├── Flex.tsx │ │ ├── Grid.md │ │ ├── Grid.tsx │ │ ├── Heading.md │ │ ├── Heading.tsx │ │ ├── HiddenFromReaders.md │ │ ├── HiddenFromReaders.tsx │ │ ├── HiddenVisually.md │ │ ├── HiddenVisually.tsx │ │ ├── Img.md │ │ ├── Img.tsx │ │ ├── Input.md │ │ ├── Input.tsx │ │ ├── Page.md │ │ ├── Page.tsx │ │ ├── Stack.md │ │ ├── Stack.tsx │ │ ├── Text.md │ │ └── Text.tsx │ │ └── theme.ts ├── mixins │ ├── CHANGELOG.md │ ├── Readme.md │ ├── package.json │ └── src │ │ ├── index.ts │ │ └── mixins.ts ├── react-design-tokens │ ├── CHANGELOG.md │ ├── Readme.md │ ├── package.json │ └── src │ │ ├── ColorSwatch.jsx │ │ ├── ColorSwatch.md │ │ ├── Colors.jsx │ │ ├── Colors.md │ │ ├── PaletteSwatch.jsx │ │ ├── PaletteSwatch.md │ │ ├── Spacing.jsx │ │ ├── Spacing.md │ │ ├── SpacingSwatch.jsx │ │ ├── SpacingSwatch.md │ │ ├── Swatch.jsx │ │ ├── Swatch.md │ │ ├── SwatchToken.jsx │ │ ├── SwatchToken.md │ │ ├── SwatchValue.jsx │ │ ├── SwatchValue.md │ │ ├── Swatches.jsx │ │ ├── Swatches.md │ │ ├── TextStyleSwatch.jsx │ │ ├── TextStyleSwatch.md │ │ ├── Typography.jsx │ │ ├── Typography.md │ │ ├── examples │ │ ├── Text.js │ │ ├── cdds.js │ │ └── primer.js │ │ ├── index.js │ │ ├── propTypes.js │ │ └── theme.js ├── react-focus-within │ ├── CHANGELOG.md │ ├── Readme.md │ ├── package.json │ └── src │ │ ├── FocusWithin.js │ │ └── index.js └── with-selector │ ├── CHANGELOG.md │ ├── Readme.md │ ├── package.json │ └── src │ ├── WithSelector.js │ └── index.js ├── styleguide.config.js ├── tsconfig.json └── yarn.lock /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works with multi-package repos, or single-package repos to help you version and publish your code. You can find the full documentation for it [in our repository](https://github.com/changesets/changesets) 4 | 5 | We have a quick list of common questions to get you started engaging with this project in [our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md) 6 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.0.3/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "linked": [], 6 | "access": "public", 7 | "baseBranch": "master" 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | packages/components 4 | packages/**/dist 5 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "babel-eslint", 4 | "plugins": ["react", "react-hooks", "jest", "import"], 5 | "env": { 6 | "browser": true, 7 | "commonjs": true, 8 | "es6": true, 9 | "node": true 10 | }, 11 | "parserOptions": { 12 | "ecmaVersion": 2018, 13 | "sourceType": "module", 14 | "ecmaFeatures": { 15 | "jsx": true 16 | } 17 | }, 18 | "settings": { 19 | "react": { 20 | "version": "detect" 21 | } 22 | }, 23 | "overrides": [ 24 | { 25 | "files": ["test/**/*.test.js"], 26 | "extends": ["plugin:jest/recommended"], 27 | "rules": { 28 | "jest/expect-expect": "off", 29 | "jest/no-disabled-tests": "off" 30 | } 31 | }, 32 | { "files": ["**/__tests__/**"], "env": { "jest": true } }, 33 | { 34 | "files": ["**/*.ts", "**/*.tsx"], 35 | "parser": "@typescript-eslint/parser", 36 | "parserOptions": { 37 | "ecmaVersion": 2018, 38 | "sourceType": "module", 39 | "ecmaFeatures": { 40 | "jsx": true 41 | }, 42 | "warnOnUnsupportedTypeScriptVersion": false 43 | }, 44 | "plugins": ["@typescript-eslint"], 45 | "rules": { 46 | // Already handled by TS 47 | "no-dupe-class-members": "off", 48 | "no-undef": "off", 49 | 50 | // Add TypeScript specific rules (and turn off ESLint equivalents) 51 | "@typescript-eslint/consistent-type-assertions": "warn", 52 | "no-array-constructor": "off", 53 | "@typescript-eslint/no-array-constructor": "warn", 54 | "@typescript-eslint/no-namespace": "error", 55 | "no-use-before-define": "off", 56 | "@typescript-eslint/no-use-before-define": [ 57 | "warn", 58 | { 59 | "functions": false, 60 | "classes": false, 61 | "variables": false, 62 | "typedefs": false 63 | } 64 | ], 65 | "no-unused-vars": "off", 66 | "@typescript-eslint/no-unused-vars": [ 67 | "warn", 68 | { 69 | "args": "none", 70 | "ignoreRestSiblings": true 71 | } 72 | ], 73 | "no-unused-expressions": "off", 74 | "@typescript-eslint/no-unused-expressions": [ 75 | "error", 76 | { 77 | "allowShortCircuit": true, 78 | "allowTernary": true, 79 | "allowTaggedTemplates": true 80 | } 81 | ], 82 | "no-useless-constructor": "off", 83 | "@typescript-eslint/no-useless-constructor": "warn" 84 | } 85 | }, 86 | { 87 | "files": [ 88 | "test/**/*", 89 | "examples/**/*", 90 | "packages/create-next-app/templates/**/*" 91 | ], 92 | "rules": { "react/react-in-jsx-scope": "off" } 93 | }, 94 | { 95 | "files": ["examples/**/*"], 96 | "rules": { 97 | "import/no-anonymous-default-export": [ 98 | "error", 99 | { 100 | // React components: 101 | "allowArrowFunction": false, 102 | "allowAnonymousClass": false, 103 | "allowAnonymousFunction": false, 104 | 105 | // Non-React stuff: 106 | "allowArray": true, 107 | "allowCallExpression": true, 108 | "allowLiteral": true, 109 | "allowObject": true 110 | } 111 | ] 112 | } 113 | }, 114 | { 115 | "files": ["packages/**"], 116 | "rules": { 117 | "no-shadow": ["warn", { "builtinGlobals": false }], 118 | "import/no-extraneous-dependencies": [ 119 | "error", 120 | { "devDependencies": false } 121 | ] 122 | } 123 | }, 124 | { 125 | "files": ["packages/**/*.tsx", "packages/**/*.ts"], 126 | "rules": { 127 | "@typescript-eslint/no-unused-vars": [ 128 | "warn", 129 | { 130 | "args": "all", 131 | "argsIgnorePattern": "^_", 132 | "ignoreRestSiblings": true 133 | } 134 | ] 135 | } 136 | } 137 | ], 138 | "rules": { 139 | "array-callback-return": "warn", 140 | "default-case": ["warn", { "commentPattern": "^no default$" }], 141 | "dot-location": ["warn", "property"], 142 | "eqeqeq": ["warn", "smart"], 143 | "new-parens": "warn", 144 | "no-array-constructor": "warn", 145 | "no-caller": "warn", 146 | "no-cond-assign": ["warn", "except-parens"], 147 | "no-const-assign": "warn", 148 | "no-control-regex": "warn", 149 | "no-delete-var": "warn", 150 | "no-dupe-args": "warn", 151 | "no-dupe-class-members": "warn", 152 | "no-dupe-keys": "warn", 153 | "no-duplicate-case": "warn", 154 | "no-empty-character-class": "warn", 155 | "no-empty-pattern": "warn", 156 | "no-eval": "warn", 157 | "no-ex-assign": "warn", 158 | "no-extend-native": "warn", 159 | "no-extra-bind": "warn", 160 | "no-extra-label": "warn", 161 | "no-fallthrough": "warn", 162 | "no-func-assign": "warn", 163 | "no-implied-eval": "warn", 164 | "no-invalid-regexp": "warn", 165 | "no-iterator": "warn", 166 | "no-label-var": "warn", 167 | "no-labels": ["warn", { "allowLoop": true, "allowSwitch": false }], 168 | "no-lone-blocks": "warn", 169 | "no-loop-func": "warn", 170 | "no-mixed-operators": [ 171 | "warn", 172 | { 173 | "groups": [ 174 | ["&", "|", "^", "~", "<<", ">>", ">>>"], 175 | ["==", "!=", "===", "!==", ">", ">=", "<", "<="], 176 | ["&&", "||"], 177 | ["in", "instanceof"] 178 | ], 179 | "allowSamePrecedence": false 180 | } 181 | ], 182 | "no-multi-str": "warn", 183 | "no-native-reassign": "warn", 184 | "no-negated-in-lhs": "warn", 185 | "no-new-func": "warn", 186 | "no-new-object": "warn", 187 | "no-new-symbol": "warn", 188 | "no-new-wrappers": "warn", 189 | "no-obj-calls": "warn", 190 | "no-octal": "warn", 191 | "no-octal-escape": "warn", 192 | "no-redeclare": ["warn", { "builtinGlobals": false }], 193 | "no-regex-spaces": "warn", 194 | "no-restricted-syntax": ["warn", "WithStatement"], 195 | "no-script-url": "warn", 196 | "no-self-assign": "warn", 197 | "no-self-compare": "warn", 198 | "no-sequences": "warn", 199 | "no-shadow-restricted-names": "warn", 200 | "no-sparse-arrays": "warn", 201 | "no-template-curly-in-string": "error", 202 | "no-this-before-super": "warn", 203 | "no-throw-literal": "warn", 204 | "no-undef": "error", 205 | "no-unexpected-multiline": "warn", 206 | "no-unreachable": "warn", 207 | "no-unused-expressions": [ 208 | "error", 209 | { 210 | "allowShortCircuit": true, 211 | "allowTernary": true, 212 | "allowTaggedTemplates": true 213 | } 214 | ], 215 | "no-unused-labels": "warn", 216 | "no-unused-vars": [ 217 | "warn", 218 | { 219 | "args": "none", 220 | "ignoreRestSiblings": true 221 | } 222 | ], 223 | "no-use-before-define": [ 224 | "warn", 225 | { 226 | "functions": false, 227 | "classes": false, 228 | "variables": false 229 | } 230 | ], 231 | "no-useless-computed-key": "warn", 232 | "no-useless-concat": "warn", 233 | "no-useless-constructor": "warn", 234 | "no-useless-escape": "warn", 235 | "no-useless-rename": [ 236 | "warn", 237 | { 238 | "ignoreDestructuring": false, 239 | "ignoreImport": false, 240 | "ignoreExport": false 241 | } 242 | ], 243 | "no-with": "warn", 244 | "no-whitespace-before-property": "warn", 245 | "react-hooks/exhaustive-deps": "warn", 246 | "require-yield": "warn", 247 | "rest-spread-spacing": ["warn", "never"], 248 | "strict": ["warn", "never"], 249 | "unicode-bom": ["warn", "never"], 250 | "use-isnan": "warn", 251 | "valid-typeof": "warn", 252 | "getter-return": "warn", 253 | "react/forbid-foreign-prop-types": ["warn", { "allowInPropTypes": true }], 254 | "react/jsx-no-comment-textnodes": "warn", 255 | "react/jsx-no-duplicate-props": "warn", 256 | "react/jsx-no-target-blank": "warn", 257 | "react/jsx-no-undef": "error", 258 | "react/jsx-pascal-case": [ 259 | "warn", 260 | { 261 | "allowAllCaps": true, 262 | "ignore": [] 263 | } 264 | ], 265 | "react/jsx-uses-react": "warn", 266 | "react/jsx-uses-vars": "warn", 267 | "react/no-danger-with-children": "warn", 268 | "react/no-deprecated": "warn", 269 | "react/no-direct-mutation-state": "warn", 270 | "react/no-is-mounted": "warn", 271 | "react/no-typos": "error", 272 | "react/react-in-jsx-scope": "error", 273 | "react/require-render-return": "error", 274 | "react/style-prop-object": "warn", 275 | "react-hooks/rules-of-hooks": "error" 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | release: 10 | name: Release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout Repo 14 | uses: actions/checkout@master 15 | with: 16 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 17 | fetch-depth: 0 18 | 19 | - name: Setup Node.js 12.x 20 | uses: actions/setup-node@master 21 | with: 22 | node-version: 12.x 23 | 24 | - name: Install Dependencies 25 | run: yarn 26 | 27 | - name: Create Release Pull Request or Publish to npm 28 | id: changesets 29 | uses: changesets/action@master 30 | with: 31 | # This expects you to have a script called release which does a build for your packages and calls changeset publish 32 | publish: yarn release 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Coverage directory used by tools like istanbul 9 | coverage 10 | 11 | # Build dir 12 | dist/ 13 | 14 | # Dependency directories 15 | node_modules/ 16 | 17 | # TypeScript v1 declaration files 18 | typings/ 19 | 20 | # Optional npm cache directory 21 | .npm 22 | 23 | # Optional eslint cache 24 | .eslintcache 25 | 26 | # Yarn Integrity file 27 | .yarn-integrity 28 | 29 | # Styleguide 30 | /styleguide 31 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .npmignore 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "trailingComma": "none", 4 | "semi": false, 5 | "arrowParens": "always", 6 | "overrides": [ 7 | { 8 | "files": "*.md", 9 | "options": { 10 | "printWidth": 70, 11 | "trailingComma": "none", 12 | "proseWrap": "never" 13 | } 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.styleguidist/StyleguideProvider.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { ThemeProvider } from "styled-components" 3 | import theme from "../packages/components/src/theme" 4 | 5 | const StyleguideProvider: React.FC = ({ children }) => { 6 | return {children} 7 | } 8 | 9 | export default StyleguideProvider 10 | -------------------------------------------------------------------------------- /.styleguidist/setup.js: -------------------------------------------------------------------------------- 1 | import * as components from "../packages/components/src" 2 | 3 | // Expose all components to the global scope for styleguide examples 4 | // so it behaves more like Playroom without the need to import components 5 | Object.entries(components).forEach(([key, value]) => { 6 | global[key] = value 7 | }) 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Andrey Okonetchnikov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Component Driven UI 2 | 3 | ![Release](https://github.com/component-driven/ui/workflows/Release/badge.svg) 4 | 5 | Includes following packages: 6 | 7 | - `components` — React primitive components like Box, Grid, Stack, etc. 8 | - `react-design-tokens` — React components to document design tokens in a styleguide. 9 | - `FocusWithin` component — the missing JS API of the CSS `:focus-within` for React 10 | - `WithSelector` component to allow preview of pseudo-styles like `:hover` and `:focus` in styleguides 11 | - `mixins` — a collection of mixins for pseudo styles (`:focus`, `:disabled`) to work with CSS-in-JS libraries 12 | 13 | ## [Documentation](https://ui.component-driven.dev) 14 | 15 | ## Aknowledgements 16 | 17 | [![Powered by Vercel](https://www.datocms-assets.com/31049/1618983297-powered-by-vercel.svg)](https://vercel.com/?utm_source=component-driven.dev&utm_campaign=oss) 18 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | browsers: ["ie >= 11"] 8 | }, 9 | exclude: ["transform-async-to-generator", "transform-regenerator"], 10 | modules: false, 11 | loose: true 12 | } 13 | ], 14 | "@babel/react", 15 | "@babel/preset-typescript" 16 | ], 17 | plugins: ["@babel/plugin-proposal-class-properties"] 18 | } 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@component-driven/ui", 4 | "workspaces": [ 5 | "packages/*" 6 | ], 7 | "preconstruct": { 8 | "packages": [ 9 | "packages/*" 10 | ] 11 | }, 12 | "scripts": { 13 | "postinstall": "preconstruct dev", 14 | "changeset": "changeset", 15 | "build": "preconstruct build", 16 | "prerelease": "npm run build", 17 | "release": "changeset publish", 18 | "start": "preconstruct watch && styleguidist server", 19 | "styleguide": "styleguidist build", 20 | "test": "preconstruct build", 21 | "lint": "eslint ." 22 | }, 23 | "author": "Andrey Okonetchnikov ", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/component-driven/ui/issues" 27 | }, 28 | "homepage": "https://react-focus-utils.netlify.com", 29 | "dependencies": {}, 30 | "devDependencies": { 31 | "@babel/core": "^7.8.7", 32 | "@babel/plugin-proposal-class-properties": "^7.8.3", 33 | "@babel/preset-env": "^7.8.7", 34 | "@babel/preset-react": "^7.8.3", 35 | "@babel/preset-typescript": "^7.12.7", 36 | "@changesets/cli": "^2.6.5", 37 | "@preconstruct/cli": "^1.1.12", 38 | "@typescript-eslint/eslint-plugin": "^4.8.2", 39 | "@typescript-eslint/parser": "^4.8.2", 40 | "babel-eslint": "^10.1.0", 41 | "babel-loader": "^8.2.2", 42 | "babel-plugin-styled-components": "^1.11.1", 43 | "changeset": "^0.2.6", 44 | "eslint": "^6.8.0", 45 | "eslint-plugin-import": "^2.22.1", 46 | "eslint-plugin-jest": "^24.1.3", 47 | "eslint-plugin-react": "^7.19.0", 48 | "eslint-plugin-react-hooks": "^4.2.0", 49 | "find-up": "^5.0.0", 50 | "husky": "^4.3.0", 51 | "lint-staged": "^10.5.2", 52 | "prettier": "^2.2.0", 53 | "react": "^16.13.0", 54 | "react-docgen-typescript": "^1.20.5", 55 | "react-dom": "^16.13.0", 56 | "react-styleguidist": "^11.0.0", 57 | "typescript": "^4.3.2", 58 | "webpack": "^4.16.5" 59 | }, 60 | "lint-staged": { 61 | "*.{js,ts,tsx}": "eslint --cache --fix", 62 | "*.{js,ts,tsx,json,md}": "prettier --write" 63 | }, 64 | "husky": { 65 | "hooks": { 66 | "pre-commit": "lint-staged" 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/components/@types/styled.d.ts: -------------------------------------------------------------------------------- 1 | import { CSSProp } from "styled-components" 2 | import { CSSObject } from "@styled-system/css" 3 | import { SystemCssProperties } from "../" 4 | import { Theme } from "../src/theme" 5 | 6 | declare module "styled-components" { 7 | /** 8 | * Do not remove next line since even if the ESLint doesn't complain 9 | * and will automatically "fix" the code into a non-working one :shrug: 10 | */ 11 | 12 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 13 | interface DefaultTheme extends Theme {} 14 | } 15 | 16 | declare module "@styled-system/css" { 17 | // TODO: This removes TS errors when used directly but it still leaves the object untyped... 18 | export function css(input?: SystemCssProperties): CSSObject 19 | } 20 | 21 | declare module "react" { 22 | interface Attributes { 23 | css?: CSSProp 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/components/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @component-driven/components 2 | 3 | ## 2.0.0 4 | ### Major Changes 5 | 6 | - a068558: Add components package 7 | 8 | ### Patch Changes 9 | 10 | - Updated dependencies [3829331] 11 | - @component-driven/mixins@3.0.0 12 | -------------------------------------------------------------------------------- /packages/components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@component-driven/components", 3 | "description": "React components for rapid UI creation", 4 | "version": "2.0.0", 5 | "main": "dist/components.cjs.js", 6 | "module": "dist/components.esm.js", 7 | "dependencies": { 8 | "@component-driven/mixins": "^3.0.0", 9 | "@component-driven/react-design-tokens": "^2.1.0", 10 | "@component-driven/with-selector": "^2.1.1", 11 | "@styled-system/css": "^5.1.5", 12 | "focus-visible": "^5.1.0", 13 | "polished": "^3.2.0", 14 | "styled-components": "^5.1.1", 15 | "styled-system": "^5.1.5" 16 | }, 17 | "devDependencies": { 18 | "@types/styled-components": "^5.1.3", 19 | "@types/styled-system": "^5.1.10", 20 | "@types/styled-system__css": "^5.0.13" 21 | }, 22 | "peerDependencies": { 23 | "react": ">=16.0", 24 | "react-dom": ">=16.0" 25 | }, 26 | "author": "Andrey Okonetchnikov ", 27 | "license": "MIT", 28 | "publishConfig": { 29 | "access": "public" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/components/src/index.ts: -------------------------------------------------------------------------------- 1 | import * as CSS from "csstype" 2 | import { Theme } from "./theme" 3 | import { 4 | AllSystemCSSProperties, 5 | ResponsiveStyleValue, 6 | StandardCSSProperties, 7 | SystemStyleObject 8 | } from "@styled-system/css" 9 | 10 | export { default as Box } from "./primitives/Box" 11 | export { default as Button } from "./primitives/Button" 12 | export { default as Checkbox } from "./primitives/Checkbox" 13 | export { default as Flex } from "./primitives/Flex" 14 | export { default as Grid } from "./primitives/Grid" 15 | export { default as Heading } from "./primitives/Heading" 16 | export { default as HiddenFromReaders } from "./primitives/HiddenFromReaders" 17 | export { default as Input } from "./primitives/Input" 18 | export { default as Img } from "./primitives/Img" 19 | export { default as Stack } from "./primitives/Stack" 20 | export { default as Text, textStyles } from "./primitives/Text" 21 | export { default as VisuallyHidden } from "./primitives/HiddenVisually" 22 | export * from "./primitives/Page" 23 | export { default as InteractiveComponentStates } from "./interactiveComponentStates" 24 | 25 | export { default as theme } from "./theme" 26 | 27 | export type SystemCSSObject = T & { 28 | [K in CSS.Pseudos]?: T 29 | } 30 | 31 | export type CssProperties = { 32 | [K in keyof StandardCSSProperties]: StandardCSSProperties[K] 33 | } 34 | 35 | export type SystemCssProperties = { 36 | [K in keyof AllSystemCSSProperties]: 37 | | ResponsiveStyleValue 38 | | ((theme: T) => ResponsiveStyleValue) 39 | | SystemStyleObject 40 | } 41 | -------------------------------------------------------------------------------- /packages/components/src/interactiveComponentStates.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactElement } from "react" 2 | // @ts-ignore 3 | import WithSelector from "@component-driven/with-selector" 4 | import { Grid } from "./" 5 | 6 | type StateProps = { 7 | state: string 8 | } 9 | 10 | type Props = { 11 | children: (arg0: StateProps) => ReactElement 12 | states?: { 13 | [key: string]: string | boolean 14 | } 15 | } 16 | 17 | const defaultStates = { 18 | default: "", 19 | hovered: ":hover", 20 | focused: ".focus-visible", 21 | disabled: true 22 | } 23 | 24 | function InteractiveComponentStates({ children, states = defaultStates }: Props) { 25 | const entries = Object.entries(states) 26 | return ( 27 | 28 | {entries.map(([key, value]) => 29 | typeof value === "boolean" ? ( 30 | React.cloneElement(children({ state: key }), { 31 | key, 32 | [key]: value 33 | }) 34 | ) : ( 35 | 36 | {children({ state: key })} 37 | 38 | ) 39 | )} 40 | 41 | ) 42 | } 43 | 44 | export default InteractiveComponentStates 45 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Box.md: -------------------------------------------------------------------------------- 1 | ```tsx 2 | 3 | Box content 4 | 5 | ``` 6 | 7 | ### Custom styles with `css` prop 8 | 9 | Note that `css` prop isn't theme-aware. If you want to use design tokens from the theme here, you need to use the `useTheme` hook. 10 | 11 | ```tsx 12 | import { useTheme } from "styled-components" 13 | const theme = useTheme() 14 | 15 | ; 20 | 31 | Nav item 32 | 33 | 34 | ``` 35 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Box.tsx: -------------------------------------------------------------------------------- 1 | import styled from "styled-components" 2 | import { 3 | border, 4 | BorderProps, 5 | color, 6 | ColorProps, 7 | compose, 8 | flexbox, 9 | FlexboxProps, 10 | grid, 11 | GridProps, 12 | layout, 13 | LayoutProps, 14 | position, 15 | PositionProps, 16 | shadow, 17 | ShadowProps, 18 | space, 19 | SpaceProps, 20 | ThemeValue 21 | } from "styled-system" 22 | import { Theme } from "../theme" 23 | import React from "react" 24 | 25 | export type BoxProps = React.AllHTMLAttributes & 26 | SpaceProps & 27 | ColorProps & 28 | BorderProps> & // TODO: Add this for all border props 29 | ShadowProps & 30 | LayoutProps & 31 | PositionProps & 32 | FlexboxProps & 33 | GridProps 34 | 35 | /** 36 | * Generic container with responsive props to control whitespace, layout, positioning and colors. 37 | */ 38 | export const Box = styled.div( 39 | { 40 | margin: 0, 41 | boxSizing: "border-box", 42 | minWidth: 0 43 | }, 44 | compose(space, color, border, shadow, layout, position, flexbox, grid) 45 | ) 46 | 47 | export default Box 48 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Button.md: -------------------------------------------------------------------------------- 1 | ### Default button 2 | 3 | ```tsx noeditor 4 | 5 | {({ state }) => } 6 | 7 | ``` 8 | 9 | ### Primary button 10 | 11 | ```tsx noeditor 12 | 13 | {({ state }) => } 14 | 15 | ``` 16 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Button.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import styled from "styled-components" 3 | import css from "@styled-system/css" 4 | import { BorderColorProps, ColorProps, ResponsiveValue, variant } from "styled-system" 5 | // @ts-ignore 6 | import { disabled, focusRing } from "@component-driven/mixins" 7 | import { Theme } from "../theme" 8 | import { SystemCSSObject } from "../index" 9 | 10 | type ButtonStyle = ColorProps & BorderColorProps 11 | 12 | export const buttonStyles: Record<"primary" | "secondary", SystemCSSObject> = { 13 | primary: { 14 | color: "background", 15 | bg: "primary", 16 | borderColor: "primary", 17 | ":hover": { 18 | bg: "background", 19 | color: "primary" 20 | } 21 | }, 22 | secondary: { 23 | color: "primary", 24 | bg: "none", 25 | borderColor: "primary" 26 | } 27 | } 28 | 29 | export type ButtonProps = Omit, "disabled"> & { 30 | /** 31 | * Whether button should be disabled or not 32 | */ 33 | disabled?: boolean 34 | /** 35 | * Button variant 36 | */ 37 | variant?: ResponsiveValue 38 | } 39 | 40 | const Button = styled.button( 41 | css({ 42 | appearance: "none", 43 | display: "inline-block", 44 | py: 3, 45 | px: 4, 46 | background: "none", 47 | border: "thin", 48 | borderColor: "primary", 49 | color: "primary", 50 | cursor: "pointer", 51 | fontSize: "s" 52 | }), 53 | variant({ 54 | prop: "variant", 55 | variants: buttonStyles 56 | }), 57 | focusRing("primary"), 58 | disabled() 59 | ) 60 | 61 | Button.defaultProps = { 62 | variant: "secondary" 63 | } 64 | 65 | export default Button 66 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Checkbox.md: -------------------------------------------------------------------------------- 1 | Checkbox can be in two states. 2 | 3 | ### Unchecked 4 | 5 | ```tsx 6 | {}} /> 7 | ``` 8 | 9 | ### Checked 10 | 11 | ```tsx 12 | {}} /> 13 | ``` 14 | 15 | ### Disabled 16 | 17 | ```tsx 18 | {}} /> 19 | {}} /> 20 | ``` 21 | 22 | ### Controlling Checkbox 23 | 24 | Checkbox is a controlled component so you have to manage the state yourself 25 | 26 | ```tsx 27 | const [checked, setChecked] = React.useState(false) 28 | ; { 31 | setChecked(event.target.checked) 32 | }} 33 | /> 34 | ``` 35 | 36 | Checkbox also works with `Label`. You can either wrap `Checkbox` in `label`: 37 | 38 | ```tsx 39 | const [checked, setChecked] = React.useState(false) 40 | ; 49 | ``` 50 | 51 | or assigning both `htmlFor` and `id` attributes. 52 | 53 | ```tsx 54 | const [checked, setChecked] = React.useState(false) 55 | ;<> 56 | { 59 | setChecked(event.target.checked) 60 | }} 61 | id="my-checkbox" 62 | /> 63 | 66 | 67 | ``` 68 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Checkbox.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | type Props = Omit< 4 | React.InputHTMLAttributes, 5 | "type" | "checked" | "disabled" | "onChange" 6 | > & { 7 | /** Whether checkbox should be disabled */ 8 | disabled?: boolean 9 | 10 | /** Whether checkbox should be checked */ 11 | checked?: boolean 12 | 13 | /** Callback function */ 14 | onChange?: (event: React.ChangeEvent) => void 15 | } 16 | 17 | const Checkbox: React.FC = ({ checked, ...rest }) => { 18 | return 19 | } 20 | 21 | export default Checkbox 22 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Flex.md: -------------------------------------------------------------------------------- 1 | Using Flex we can create a simple columns layout: 2 | 3 | ```tsx 4 | 5 | 6 | Column 1 7 | 8 | 9 | Column 2 10 | 11 | 12 | Column 3 13 | 14 | 15 | ``` 16 | 17 | or rows: 18 | 19 | ```tsx 20 | 21 | 22 | Column 1 23 | 24 | 25 | Column 2 26 | 27 | 28 | Column 3 29 | 30 | 31 | ``` 32 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Flex.tsx: -------------------------------------------------------------------------------- 1 | import styled from "styled-components" 2 | import { Box } from "../" 3 | import { BoxProps } from "./Box" 4 | 5 | const Flex = styled(Box)({ 6 | display: "flex" 7 | }) 8 | 9 | export default Flex 10 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Grid.md: -------------------------------------------------------------------------------- 1 | Using Grid we can create any CSS grid layout: 2 | 3 | ```tsx 4 | 5 | 6 | Column 1 7 | 8 | 9 | Column 2 10 | 11 | 12 | Column 3 13 | 14 | 15 | ``` 16 | 17 | or more complex one: 18 | 19 | ```tsx 20 | 25 | 26 | Text 27 | 28 | 29 | First Name 30 | 31 | 32 | Last Name 33 | 34 | 35 | Column 3 36 | 37 | 38 | ``` 39 | 40 | ### Additional props 41 | 42 | Set `columns` and `rows` prop to create a layout with the amount of columns that take all the space: 43 | 44 | ```tsx 45 | 46 | 47 | Column 1 48 | 49 | 50 | Column 2 51 | 52 | 53 | Column 3 54 | 55 | 56 | Column 1 57 | 58 | 59 | Column 2 60 | 61 | 62 | Column 3 63 | 64 | 65 | ``` 66 | 67 | Set `minColumnWidth` prop to create a variable columns and rows layout based on child minimum width: 68 | 69 | ```tsx 70 | 71 | 72 | Item 1 73 | 74 | 75 | Item 2 76 | 77 | 78 | Item 3 79 | 80 | 81 | Item 4 82 | 83 | 84 | ``` 85 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Grid.tsx: -------------------------------------------------------------------------------- 1 | import styled from "styled-components" 2 | import { Box } from "../" 3 | import { BoxProps } from "./Box" 4 | import { ResponsiveValue, system, TLengthStyledSystem } from "styled-system" 5 | 6 | type StackProps = BoxProps & { 7 | /** Number of columns, will create a responsive CSS Grid layout like 8 | * `grid-template-columns: repeat($numColumns$, 1fr))`. 9 | * (You can use either this prop or `minColumnWidth` but not both.) 10 | */ 11 | columns?: ResponsiveValue 12 | 13 | /** Number of rows, will create a responsive CSS Grid layout like 14 | * `grid-template-rows: repeat($numColumns$, 1fr))`. 15 | */ 16 | rows?: ResponsiveValue 17 | 18 | /** Minimum width of a child. Will create responsive CSS Grid layout like 19 | * `grid-template-columns: repeat(auto-fit, minmax($minColumnWidth$)}, 1fr))`. 20 | * (You can use either this prop or `numColumns` but not both.) 21 | */ 22 | minColumnWidth?: ResponsiveValue 23 | } 24 | 25 | const getMinMaxValue = (value: TLengthStyledSystem, scale: TLengthStyledSystem[] = []) => { 26 | const val = scale[value as number] || value 27 | return typeof val === "number" ? `${val}px` : val 28 | } 29 | 30 | const Grid = styled(Box)( 31 | { 32 | display: "grid" 33 | }, 34 | system({ 35 | columns: { 36 | property: "gridTemplateColumns", 37 | transform: (value) => (value ? `repeat(${value}, 1fr)` : null) 38 | }, 39 | rows: { 40 | property: "gridTemplateRows", 41 | transform: (value) => (value ? `repeat(${value}, 1fr)` : null) 42 | }, 43 | minColumnWidth: { 44 | property: "gridTemplateColumns", 45 | scale: "space", 46 | transform: (value, scale) => 47 | value 48 | ? `repeat(auto-fit, minmax(${getMinMaxValue( 49 | value, 50 | scale as TLengthStyledSystem[] 51 | )}, 1fr))` 52 | : null 53 | } 54 | }) 55 | ) 56 | 57 | export default Grid 58 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Heading.md: -------------------------------------------------------------------------------- 1 | ```tsx 2 | Heading rendered as H1 3 | ``` 4 | 5 | ### Available variants 6 | 7 | ```tsx noeditor 8 | import { 9 | Typography, 10 | Swatch, 11 | Swatches, 12 | SwatchToken 13 | } from "@component-driven/react-design-tokens" 14 | import theme from "../theme" 15 | import { headingStyles } from "../primitives/Heading" 16 | ; 17 | 18 | {(token) => ( 19 | 20 | Heading of size {token} 21 | 22 | )} 23 | 24 | 25 | ``` 26 | -------------------------------------------------------------------------------- /packages/components/src/primitives/Heading.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { StandardLonghandProperties } from "csstype" 3 | import styled from "styled-components" 4 | import { 5 | color, 6 | ColorProps, 7 | compose, 8 | ResponsiveValue, 9 | space, 10 | SpaceProps, 11 | TypographyProps, 12 | variant 13 | } from "styled-system" 14 | import { Theme } from "../theme" 15 | import css from "@styled-system/css" 16 | import { SystemCSSObject } from "../index" 17 | 18 | type HeadingStyle = TypographyProps & ColorProps & StandardLonghandProperties 19 | 20 | export const headingStyles: Record<"xl" | "l" | "m" | "s", SystemCSSObject> = { 21 | xl: { 22 | fontSize: "xxl", 23 | fontWeight: "bold" 24 | }, 25 | l: { 26 | fontSize: "l", 27 | fontWeight: "bold" 28 | }, 29 | m: { 30 | fontSize: "m", 31 | fontWeight: "bold" 32 | }, 33 | s: { 34 | fontSize: "xs", 35 | fontWeight: "normal", 36 | color: "muted", 37 | textTransform: "uppercase" 38 | } 39 | } 40 | 41 | export type HeadingProps = React.HTMLAttributes & 42 | SpaceProps & 43 | ColorProps & { 44 | size?: ResponsiveValue 45 | } 46 | 47 | /** 48 | * A text heading. 49 | */ 50 | const Heading = styled.h1( 51 | css({ 52 | m: 0, 53 | lineHeight: "heading", 54 | fontFamily: "heading", 55 | color: "text", 56 | ...headingStyles.xl 57 | }), 58 | compose( 59 | space, 60 | color, 61 | variant({ 62 | prop: "size", 63 | variants: headingStyles 64 | }) 65 | ) 66 | ) 67 | 68 | export default Heading 69 | -------------------------------------------------------------------------------- /packages/components/src/primitives/HiddenFromReaders.md: -------------------------------------------------------------------------------- 1 | ```tsx 2 | 3 | Text with • a 4 | separator 5 | 6 | ``` 7 | -------------------------------------------------------------------------------- /packages/components/src/primitives/HiddenFromReaders.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | /** 4 | * Render element that’s "hidden" for screen readers 5 | */ 6 | const HiddenFromReaders: React.FC<{}> = (props) => { 7 | return