From 7cf6a59f339a9432ec791da0c6a38f9b4f04dae7 Mon Sep 17 00:00:00 2001 From: Emmanuel Luciano Date: Mon, 22 Apr 2019 10:31:17 -0400 Subject: [PATCH] Adds initial work on theme structure. Adds initial work theme colors, spacing, radius and typography. Adds typography sizes WIP - Feedback Adds rebass Adds initial theme changes Adds theme provider to stories Moves stories to ts Adds button variants and placeholder colors Visualizes palette Adds font weights, space, radius and buttons Cleans up variants file Updates palette display Moves theme to root Cleans up some type definitions --- .gitignore | 4 +- .storybook/config.js | 11 +- .storybook/webpack.config.js | 4 +- package-lock.json | 184 +++++++++++++++++++++++++++ package.json | 7 +- src/button/__tests__/button.test.tsx | 4 +- src/button/button.stories.js | 18 --- src/button/button.stories.tsx | 29 +++++ src/button/index.tsx | 20 +-- src/core/palette.stories.tsx | 61 +++++++++ theme/colors.ts | 70 ++++++++++ theme/constants.ts | 29 +++++ theme/index.ts | 5 + theme/palette.ts | 22 ++++ theme/shadows.ts | 16 +++ theme/theme.ts | 35 +++++ theme/typography.ts | 56 ++++++++ theme/units.ts | 4 + theme/variants.ts | 72 +++++++++++ tsconfig.json | 7 +- 20 files changed, 621 insertions(+), 37 deletions(-) delete mode 100644 src/button/button.stories.js create mode 100644 src/button/button.stories.tsx create mode 100644 src/core/palette.stories.tsx create mode 100644 theme/colors.ts create mode 100644 theme/constants.ts create mode 100644 theme/index.ts create mode 100644 theme/palette.ts create mode 100644 theme/shadows.ts create mode 100644 theme/theme.ts create mode 100644 theme/typography.ts create mode 100644 theme/units.ts create mode 100644 theme/variants.ts diff --git a/.gitignore b/.gitignore index b7dab5e..e48f9b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules -build \ No newline at end of file +storybook-static +build +lib \ No newline at end of file diff --git a/.storybook/config.js b/.storybook/config.js index 217f6a1..8083da9 100644 --- a/.storybook/config.js +++ b/.storybook/config.js @@ -1,13 +1,22 @@ +import React from 'react'; +import { ThemeProvider } from 'styled-components' import { configure } from '@storybook/react'; import { setAddon, addDecorator } from '@storybook/react'; import JSXAddon from 'storybook-addon-jsx'; import { withInfo } from '@storybook/addon-info'; +import { Theme } from "../theme/index"; + setAddon(JSXAddon); addDecorator(withInfo); +addDecorator(story => ( + + {story()} + +)) // automatically import all files ending in *.stories.js -const req = require.context('../src', true, /.stories.js$/); +const req = require.context('../src', true, /\.stories\.tsx$/); function loadStories() { req.keys().forEach(req); } diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js index 78e8a39..ffff379 100644 --- a/.storybook/webpack.config.js +++ b/.storybook/webpack.config.js @@ -5,8 +5,8 @@ const styledComponentsTransformer = createStyledComponentsTransformer(); module.exports = ({ config, mode }) => { config.module.rules.push({ - test: /\.tsx?$/, - include: path.resolve(__dirname, "../src"), + test: /\.(ts|tsx)$/, + include: [path.resolve(__dirname, "../src"), path.resolve(__dirname, "../theme")], use: [ { loader: require.resolve("awesome-typescript-loader"), diff --git a/package-lock.json b/package-lock.json index ce74ca8..7bbd4bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,123 @@ "@babel/highlight": "^7.0.0" } }, + "@babel/core": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.3.tgz", + "integrity": "sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.0", + "@babel/helpers": "^7.4.3", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz", + "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", + "dev": true, + "requires": { + "@babel/types": "^7.4.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.0.tgz", + "integrity": "sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw==", + "dev": true, + "requires": { + "@babel/types": "^7.4.0" + } + }, + "@babel/helpers": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.3.tgz", + "integrity": "sha512-BMh7X0oZqb36CfyhvtbSmcWc3GXocfxv3yNsAEuM0l+fAqSO22rQrUpijr3oE/10jCTrB6/0b9kzmG4VetCj8Q==", + "dev": true, + "requires": { + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0" + } + }, + "@babel/parser": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz", + "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==", + "dev": true + }, + "@babel/template": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.0.tgz", + "integrity": "sha512-SOWwxxClTTh5NdbbYZ0BmaBVzxzTh2tO/TeLTbF6MO6EzVhHTnff8CdBXx3mEtazFBoysmEM6GU/wF+SuSx4Fw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.0", + "@babel/types": "^7.4.0" + } + }, + "@babel/traverse": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.3.tgz", + "integrity": "sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.0", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/types": "^7.4.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + } + }, + "@babel/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", + "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, "@babel/generator": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", @@ -2532,6 +2649,17 @@ "@types/react": "*" } }, + "@types/rebass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/rebass/-/rebass-3.0.3.tgz", + "integrity": "sha512-2/zZV9W7QVjEnJnrwy3TArzdSTVVhNFylWLcricMj5RfmglbM08etPgwelPP/I/UTHUEDjRAEkUYp7YzJt1vhQ==", + "dev": true, + "requires": { + "@types/react": "*", + "@types/styled-components": "*", + "@types/styled-system": "*" + } + }, "@types/storybook__react": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/storybook__react/-/storybook__react-4.0.1.tgz", @@ -2553,6 +2681,15 @@ "csstype": "^2.2.0" } }, + "@types/styled-system": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@types/styled-system/-/styled-system-4.1.0.tgz", + "integrity": "sha512-3TSDL7LbpfGsCv7VZoqnKtHwYJZ/REVT6cfsw5e5vUyB+zymRgrOiJg78XOpXJgd722WrmONi+PYfnyJAMMhdw==", + "dev": true, + "requires": { + "csstype": "^2.2.0" + } + }, "@types/unist": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", @@ -12691,6 +12828,14 @@ "util.promisify": "^1.0.0" } }, + "rebass": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rebass/-/rebass-3.1.0.tgz", + "integrity": "sha512-FtmBb0bDT8q8HaGT4uAiJAQKZOdMsdonx6vp/cjnPc23FdMoo74ClTm0vJAwkWY1KzA0LCvmPbyGvWE0FFMR8w==", + "requires": { + "styled-system": "^4.0.8" + } + }, "recast": { "version": "0.14.7", "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.7.tgz", @@ -14200,6 +14345,45 @@ "supports-color": "^5.5.0" } }, + "styled-system": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/styled-system/-/styled-system-4.1.0.tgz", + "integrity": "sha512-ioIAJ029tRr6eJhiUrE3VZeahN+GBuJHv/jmckkfikY4ej8BaxvIKAaavmjFoqzNsIzr+x5HCpry1ybQYpchtQ==", + "requires": { + "@babel/runtime": "^7.4.2", + "prop-types": "^15.7.2" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.3.tgz", + "integrity": "sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" + }, + "regenerator-runtime": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" + } + } + }, "stylis": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", diff --git a/package.json b/package.json index 21636d1..64c1abc 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "main": "index.js", "license": "MIT", "devDependencies": { + "@babel/core": "^7.4.3", "@storybook/addon-actions": "^5.0.10", "@storybook/addon-info": "^5.0.10", "@storybook/addon-links": "^5.0.10", @@ -11,6 +12,7 @@ "@storybook/react": "^5.0.10", "@types/jest": "^23.3.10", "@types/react-test-renderer": "^16.0.3", + "@types/rebass": "^3.0.3", "@types/storybook__react": "^4.0.1", "@types/styled-components": "^4.1.2", "awesome-typescript-loader": "^5.2.1", @@ -28,12 +30,13 @@ "dependencies": { "react": "^16.6.3", "react-dom": "^16.6.3", + "rebass": "^3.1.0", "styled-components": "^4.1.2" }, "scripts": { "storybook": "start-storybook -p 6006", "build-storybook": "build-storybook", - "check-types": "tsc", + "compile": "tsc", "test": "jest" } -} +} \ No newline at end of file diff --git a/src/button/__tests__/button.test.tsx b/src/button/__tests__/button.test.tsx index 90476a1..a647c26 100644 --- a/src/button/__tests__/button.test.tsx +++ b/src/button/__tests__/button.test.tsx @@ -5,7 +5,9 @@ import { Button } from "../index"; describe("Button test suite", () => { test("Snapshot test", () => { - const tree = renderer.create().toJSON(); + const tree = renderer + .create() + .toJSON(); expect(tree).toMatchSnapshot(); }); diff --git a/src/button/button.stories.js b/src/button/button.stories.js deleted file mode 100644 index a972b77..0000000 --- a/src/button/button.stories.js +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from "react"; -import { storiesOf } from "@storybook/react"; - -import { Button } from "./index"; - -const stories = storiesOf("Button", module); - -stories - .add("with text", () => , { - info: { inline: true } - }) - .add( - "with text disabled", - () => , - { - info: { inline: true } - } - ); diff --git a/src/button/button.stories.tsx b/src/button/button.stories.tsx new file mode 100644 index 0000000..5f575b3 --- /dev/null +++ b/src/button/button.stories.tsx @@ -0,0 +1,29 @@ +import * as React from "react"; +import { storiesOf } from "@storybook/react"; + +import { Button } from "./index"; + +const stories = storiesOf("Button", module); + +stories + .add("Primary", () => , { + info: { inline: true } + }) + .add( + "Secondary", + () => , + { + info: { inline: true } + } + ) + .add( + "Disabled", + () => ( + + ), + { + info: { inline: true } + } + ); diff --git a/src/button/index.tsx b/src/button/index.tsx index 7fb12af..389b905 100644 --- a/src/button/index.tsx +++ b/src/button/index.tsx @@ -1,10 +1,5 @@ import * as React from "react"; -import styled from "styled-components"; - -const StyledButton = styled.button` - background-color: blue; - font-size: 20px; -`; +import { Button as BaseButton } from "rebass"; export interface Props { /** Children to be rendered. */ @@ -15,16 +10,25 @@ export interface Props { * @default false */ isDisabled?: boolean; + /** + * Type of display that the button should be shown. + * + * @default primary + */ + variant: string; } function Button(props: Props) { return ( - {props.children} + + {props.children} + ); } Button.defaultProps = { - isDisabled: false + isDisabled: false, + variant: "primary" }; export { Button }; diff --git a/src/core/palette.stories.tsx b/src/core/palette.stories.tsx new file mode 100644 index 0000000..8b1f429 --- /dev/null +++ b/src/core/palette.stories.tsx @@ -0,0 +1,61 @@ +import * as React from "react"; +import { Box, Flex, Text } from "rebass"; +import { storiesOf } from "@storybook/react"; +import styled from "styled-components"; + +import { palette } from "../../theme/index"; + +interface ItemProps { + bg: string; +} + +const List = styled.ol` + list-style: none; + padding: 0; + margin: 0; +`; + +const Item = styled.li` + display: inline-block; + margin: 10px; + border-radius: ${({ theme }) => `${theme.radii[0]}px`}; + box-shadow: ${({ theme }) => theme.shadows.default}; + overflow: hidden; + + &:hover { + box-shadow: ${({ theme }) => theme.shadows.hover}; + } +`; + +const Color = styled.div` + display: flex; + align-items: center; + justify-content: center; + background-color: ${(props: ItemProps) => props.bg}; + height: 175px; + width: 175px; +`; + +function Palette() { + return ( + + + {Object.keys(palette).map((key, index) => ( + + + + {palette[key]} + {key} + + + ))} + + + ); +} + +const stories = storiesOf("Core", module); + +stories.add("Palette", () => , { + info: { inline: true } +}); diff --git a/theme/colors.ts b/theme/colors.ts new file mode 100644 index 0000000..e5fb53a --- /dev/null +++ b/theme/colors.ts @@ -0,0 +1,70 @@ +import { States, Variants } from "./constants"; +import { palette } from "./palette"; + +interface ColorPalette { + [States.default]: string; + [States.hover]: string; + [States.pressed]: string; +} + +interface BackgroundPalette { + [States.default]: string; + [States.hover]: string; + [States.disabled]: string; +} + +interface TextPalette { + [Variants.primary]: string; + [Variants.secondary]: string; + [States.disabled]: string; + [States.pressed]: string; +} + +interface Colors { + brand: string; + [Variants.primary]: ColorPalette; + [Variants.secondary]: ColorPalette; + success: string; + warning: string; + danger: string; + stroke: string; + background: BackgroundPalette; + text: TextPalette; + common: { + white: string; + }; +} + +const colors: Colors = { + brand: palette.BRAND_COLOR, + primary: { + default: palette.PRIMARY_COLOR, + hover: palette.PRIMARY_COLOR_HOVER, + pressed: palette.PRIMARY_COLOR_PRESSED + }, + secondary: { + default: palette.SECONDARY_COLOR, + hover: palette.SECONDARY_COLOR_HOVER, + pressed: palette.SECONDARY_COLOR_PRESSED + }, + success: palette.SUCCESS_COLOR, + warning: palette.WARNING_COLOR, + danger: palette.DANGER_COLOR, + stroke: palette.STROKE_LINE_COLOR, + background: { + default: palette.BACKGROUND_COLOR, + hover: palette.BACKGROUND_COLOR_HOVER, + disabled: palette.BACKGROUND_COLOR_DISABLED + }, + text: { + primary: palette.PRIMARY_TEXT_COLOR, + secondary: palette.SECODARY_TEXT_COLOR, + disabled: palette.DISABLED_TEXT_COLOR, + pressed: palette.PRESSED_TEXT_COLOR + }, + common: { + white: "#FFFFFF" + } +}; + +export { Colors, colors }; diff --git a/theme/constants.ts b/theme/constants.ts new file mode 100644 index 0000000..a39bdd0 --- /dev/null +++ b/theme/constants.ts @@ -0,0 +1,29 @@ +enum States { + default = "default", + hover = "hover", + pressed = "pressed", + disabled = "disabled" +} + +enum Sizes { + xs = "xs", + sm = "sm", + rg = "rg", + md = "md", + lg = "lg", + xl = "xl" +} + +enum Headers { + subheader2 = "subheader2", + subheader = "subheader", + header = "header" +} + +enum Variants { + primary = "primary", + secondary = "secondary", + inverse = "inverse" +} + +export { States, Sizes, Headers, Variants }; diff --git a/theme/index.ts b/theme/index.ts new file mode 100644 index 0000000..085eba3 --- /dev/null +++ b/theme/index.ts @@ -0,0 +1,5 @@ +import { States, Sizes, Variants, Headers } from "./constants"; +import { palette } from "./palette"; +import { Theme } from "./theme"; + +export { Theme, States, Sizes, Variants, Headers, palette }; diff --git a/theme/palette.ts b/theme/palette.ts new file mode 100644 index 0000000..f0fd3f2 --- /dev/null +++ b/theme/palette.ts @@ -0,0 +1,22 @@ +enum palette { + BRAND_COLOR = "#f73d56", + PRIMARY_COLOR = "#9c4fba", + PRIMARY_COLOR_HOVER = "#753085", + PRIMARY_COLOR_PRESSED = "#51215c", + SECONDARY_COLOR = "#36038c", + SECONDARY_COLOR_HOVER = "#2b0065", + SECONDARY_COLOR_PRESSED = "#1c0046", + BACKGROUND_COLOR = "#f3f5f8", + BACKGROUND_COLOR_HOVER = "#ebebff", + BACKGROUND_COLOR_DISABLED = "#cecece", + SUCCESS_COLOR = "#16d4af", + WARNING_COLOR = "#f0c241", + DANGER_COLOR = "#d0021b", + STROKE_LINE_COLOR = "#dadfe6", + PRIMARY_TEXT_COLOR = "#2a3037", + SECODARY_TEXT_COLOR = "#697280", + PRESSED_TEXT_COLOR = "#b2b2b2", + DISABLED_TEXT_COLOR = "#666666" +} + +export { palette }; diff --git a/theme/shadows.ts b/theme/shadows.ts new file mode 100644 index 0000000..0bfdb07 --- /dev/null +++ b/theme/shadows.ts @@ -0,0 +1,16 @@ +import { States } from "./constants"; + +interface Shadows { + [States.default]: string; + [States.hover]: string; +} + +const SHADOW_DEFAULT = "0px 1px 3px rgba(0, 0, 0, 0.07)"; +const SHADOW_HOVER = "0px 5px 10px rgba(0, 0, 0, 0.1)"; + +const shadows: Shadows = { + default: SHADOW_DEFAULT, + hover: SHADOW_HOVER +}; + +export { Shadows, shadows }; diff --git a/theme/theme.ts b/theme/theme.ts new file mode 100644 index 0000000..32abe53 --- /dev/null +++ b/theme/theme.ts @@ -0,0 +1,35 @@ +import { Colors, colors } from "./colors"; +import { Shadows, shadows } from "./shadows"; +import { space, radii } from "./units"; +import { + TypographyElement, + fontSizes, + lineHeights, + FontWeights, + fontWeights +} from "./typography"; +import { Variant, buttons } from "./variants"; + +interface BaseTheme { + colors: Colors; + shadows: Shadows; + fontSizes: TypographyElement; + fontWeights: FontWeights; + lineHeights: TypographyElement; + buttons: Variant; + space: number[]; + radii: number[]; +} + +const Theme: BaseTheme = { + colors, + shadows, + fontSizes, + fontWeights, + lineHeights, + buttons, + space, + radii +}; + +export { Theme }; diff --git a/theme/typography.ts b/theme/typography.ts new file mode 100644 index 0000000..ee21f2a --- /dev/null +++ b/theme/typography.ts @@ -0,0 +1,56 @@ +import { Sizes, Headers } from "./constants"; + +interface TypographyElement { + [Sizes.xs]: number; + [Sizes.sm]: number; + [Sizes.rg]: number; + [Sizes.md]: number; + [Sizes.lg]: number; + [Sizes.xl]: number; + [Headers.subheader2]?: number; + [Headers.subheader]?: number; + [Headers.header]?: number; +} + +interface FontWeights { + lite: number; + normal: number; + bold: number; +} + +// Line height scale +const LINE_HEIGHTS_SCALE = [19, 23, 26, 32, 39, 49]; + +// Line height scale object +const lineHeights: TypographyElement = { + [Sizes.xs]: LINE_HEIGHTS_SCALE[0], + [Sizes.sm]: LINE_HEIGHTS_SCALE[1], + [Sizes.rg]: LINE_HEIGHTS_SCALE[2], + [Sizes.md]: LINE_HEIGHTS_SCALE[3], + [Sizes.lg]: LINE_HEIGHTS_SCALE[4], + [Sizes.xl]: LINE_HEIGHTS_SCALE[5] +}; + +// Font size scale +const FONT_SIZES_SCALE = [12, 14, 16, 20, 24, 30, 36, 48, 60]; + +// Font size scale object +const fontSizes: TypographyElement = { + [Sizes.xs]: FONT_SIZES_SCALE[0], + [Sizes.sm]: FONT_SIZES_SCALE[1], + [Sizes.rg]: FONT_SIZES_SCALE[2], + [Sizes.md]: FONT_SIZES_SCALE[3], + [Sizes.lg]: FONT_SIZES_SCALE[4], + [Sizes.xl]: FONT_SIZES_SCALE[5], + [Headers.subheader2]: FONT_SIZES_SCALE[6], + [Headers.subheader]: FONT_SIZES_SCALE[7], + [Headers.header]: FONT_SIZES_SCALE[8] +}; + +const fontWeights: FontWeights = { + lite: 300, + normal: 400, + bold: 600 +}; + +export { TypographyElement, fontSizes, lineHeights, FontWeights, fontWeights }; diff --git a/theme/units.ts b/theme/units.ts new file mode 100644 index 0000000..6dc3149 --- /dev/null +++ b/theme/units.ts @@ -0,0 +1,4 @@ +const space = [5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100]; +const radii = [6]; + +export { space, radii }; diff --git a/theme/variants.ts b/theme/variants.ts new file mode 100644 index 0000000..70b978c --- /dev/null +++ b/theme/variants.ts @@ -0,0 +1,72 @@ +import { Variants } from "./constants"; +import { colors } from "./colors"; +import { radii } from "./units"; + +interface BaseButton { + backgroundColor: string; + color?: string; + borderColor?: string; +} + +interface Button extends BaseButton { + borderRadius: number; + borderStyle: string; + borderWidth: number; + cursor?: string; + "&:disabled": BaseButton; + "&:hover"?: BaseButton; + "&:focus"?: BaseButton; + "&:active"?: BaseButton; +} + +interface Variant { + [Variants.primary]: Button; + [Variants.secondary]: Button; +} + +const { primary, secondary, background, text, common } = colors; +const borderStyle: { + borderWidth: number; + borderStyle: string; +} = { + borderWidth: 1, + borderStyle: "solid" +}; +function getButtonStyle({ bg, color }: { bg: string; color: string }) { + return { + backgroundColor: bg, + borderColor: bg, + color: color + }; +} + +const disabled = { + ...getButtonStyle({ bg: background.disabled, color: text.disabled }), + ...borderStyle, + borderRadius: radii[0], + cursor: "not-allowed", + "&:hover": getButtonStyle({ bg: background.disabled, color: text.disabled }) +}; + +const buttons: Variant = { + [Variants.primary]: { + ...getButtonStyle({ bg: primary.default, color: common.white }), + ...borderStyle, + borderRadius: radii[0], + "&:disabled": disabled, + "&:hover": getButtonStyle({ bg: primary.hover, color: common.white }), + "&:focus": getButtonStyle({ bg: primary.hover, color: common.white }), + "&:active": getButtonStyle({ bg: primary.pressed, color: text.pressed }) + }, + [Variants.secondary]: { + ...getButtonStyle({ bg: secondary.default, color: common.white }), + ...borderStyle, + borderRadius: radii[0], + "&:disabled": disabled, + "&:hover": getButtonStyle({ bg: secondary.hover, color: common.white }), + "&:focus": getButtonStyle({ bg: secondary.hover, color: common.white }), + "&:active": getButtonStyle({ bg: secondary.pressed, color: text.pressed }) + } +}; + +export { Variant, buttons }; diff --git a/tsconfig.json b/tsconfig.json index 46c52c2..0a79cc1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,15 +1,14 @@ { "compilerOptions": { - "outDir": "build/lib", + "outDir": "lib", "module": "commonjs", "target": "es5", "lib": ["es5", "es6", "es7", "es2017", "dom"], "sourceMap": true, "allowJs": false, - "alwaysStrict": true, "jsx": "react", "moduleResolution": "node", - "rootDir": "src", + "rootDirs": ["src", "theme"], "baseUrl": "src", "forceConsistentCasingInFileNames": true, "noImplicitReturns": true, @@ -23,6 +22,6 @@ "experimentalDecorators": true, "emitDecoratorMetadata": true }, - "include": ["src/**/*"], + "include": ["src/**/*", "theme"], "exclude": ["node_modules", "build", "scripts"] } \ No newline at end of file