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