├── example ├── .npmignore ├── index.tsx ├── index.html ├── tsconfig.json └── package.json ├── .gitignore ├── src ├── index.tsx ├── tailwind.css ├── Thing.tsx └── Button.tsx ├── postcss.config.js ├── .storybook ├── preview.js └── main.js ├── .github └── workflows │ ├── size.yml │ └── main.yml ├── tailwind.config.js ├── test ├── blah.test.tsx └── Button.test.tsx ├── tsdx.config.js ├── README.md ├── .vscode ├── extensions.json └── settings.json ├── stories ├── Button.stories.tsx └── Thing.stories.tsx ├── LICENSE ├── tsconfig.json ├── package.json └── TSDX_README.md /example/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .cache 3 | dist -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | dist 6 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Thing'; 2 | export * from './Button'; 3 | -------------------------------------------------------------------------------- /src/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | // https://storybook.js.org/docs/react/writing-stories/parameters#global-parameters 2 | export const parameters = { 3 | // https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args 4 | actions: { argTypesRegex: '^on.*' }, 5 | }; 6 | -------------------------------------------------------------------------------- /.github/workflows/size.yml: -------------------------------------------------------------------------------- 1 | name: size 2 | on: [pull_request] 3 | jobs: 4 | size: 5 | runs-on: ubuntu-latest 6 | env: 7 | CI_JOB_NUMBER: 1 8 | steps: 9 | - uses: actions/checkout@v1 10 | - uses: andresz1/size-limit-action@v1 11 | with: 12 | github_token: ${{ secrets.GITHUB_TOKEN }} 13 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../stories/**/*.stories.@(ts|tsx|js|jsx)'], 3 | addons: ['@storybook/addon-links', '@storybook/addon-essentials'], 4 | // https://storybook.js.org/docs/react/configure/typescript#mainjs-configuration 5 | typescript: { 6 | check: true, // type-check stories during Storybook build 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: [ 3 | './src/components/**/*.tsx', 4 | './src/components/**/*.styled.ts', 5 | './src/components/**/*.styled.tsx', 6 | ], 7 | darkMode: false, // or 'media' or 'class' 8 | theme: { 9 | extend: {}, 10 | }, 11 | variants: { 12 | extend: {}, 13 | }, 14 | plugins: [], 15 | } 16 | -------------------------------------------------------------------------------- /example/index.tsx: -------------------------------------------------------------------------------- 1 | import 'react-app-polyfill/ie11'; 2 | import * as React from 'react'; 3 | import * as ReactDOM from 'react-dom'; 4 | import { Thing, Button } from '../.'; 5 | 6 | const App = () => { 7 | return ( 8 |
9 | 10 |
12 | ); 13 | }; 14 | 15 | ReactDOM.render(, document.getElementById('root')); 16 | -------------------------------------------------------------------------------- /test/blah.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | import { Default as Thing } from '../stories/Thing.stories'; 4 | 5 | describe('Thing', () => { 6 | it('renders without crashing', () => { 7 | const div = document.createElement('div'); 8 | ReactDOM.render(, div); 9 | ReactDOM.unmountComponentAtNode(div); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Playground 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tsdx.config.js: -------------------------------------------------------------------------------- 1 | const postcss = require('rollup-plugin-postcss'); 2 | 3 | module.exports = { 4 | rollup(config, options) { 5 | config.plugins.push( 6 | postcss({ 7 | config: { 8 | path: './postcss.config.js', 9 | }, 10 | extensions: ['.css'], 11 | minimize: true, 12 | inject: { 13 | insertAt: 'top', 14 | }, 15 | }) 16 | ); 17 | return config; 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How to Build A React TS Tailwind Design System 2 | This repo is the code for the blog post ["How to Build A React TS Tailwind Design System"](https://dev.to/hamatoyogi/how-to-build-a-react-ts-tailwind-design-system-1ppi). 3 | 4 | You can read along the article and look at the commits which correspond to the sections throughout it. 5 | 6 | For any questions about this repo, feel free to open issues here or [reach out to me](https://twitter.com/HamatoYogi). 7 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": false, 4 | "target": "es5", 5 | "module": "commonjs", 6 | "jsx": "react", 7 | "moduleResolution": "node", 8 | "noImplicitAny": false, 9 | "noUnusedLocals": false, 10 | "noUnusedParameters": false, 11 | "removeComments": true, 12 | "strictNullChecks": true, 13 | "preserveConstEnums": true, 14 | "sourceMap": true, 15 | "lib": ["es2015", "es2016", "dom"], 16 | "types": ["node"] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "bradlc.vscode-tailwindcss", 8 | "jpoissonnier.vscode-styled-components", 9 | "austenc.tailwind-docs" 10 | ], 11 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 12 | "unwantedRecommendations": [] 13 | } 14 | -------------------------------------------------------------------------------- /stories/Button.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { Button, ButtonProps } from '../src'; 4 | 5 | const meta: Meta = { 6 | title: 'Button', 7 | component: Button, 8 | argTypes: { 9 | text: { 10 | control: { 11 | type: 'text', 12 | }, 13 | }, 14 | }, 15 | parameters: { 16 | controls: { expanded: true }, 17 | }, 18 | }; 19 | 20 | export default meta; 21 | 22 | const Template: Story = args =>