├── src ├── util │ ├── index.tsx │ ├── cypress-utils.ts │ ├── test-utils.tsx │ ├── storybook-utils.tsx │ └── helpers.tsx ├── index.ts └── theme │ ├── components │ ├── container │ │ ├── container.ts │ │ └── container.stories.tsx │ ├── code │ │ ├── code.ts │ │ └── code.stories.tsx │ ├── form-label │ │ ├── form-label.ts │ │ └── form-label.stories.tsx │ ├── link │ │ ├── link.ts │ │ └── link.stories.tsx │ ├── list │ │ ├── list.ts │ │ └── list.stories.tsx │ ├── divider │ │ ├── divider.ts │ │ └── divider.stories.tsx │ ├── kbd │ │ ├── kbd.ts │ │ └── kbd.stories.tsx │ ├── skip-link │ │ ├── skip-link.ts │ │ └── skip-link.stories.tsx │ ├── spinner │ │ ├── spinner.ts │ │ └── spinner.stories.tsx │ ├── breadcrumb │ │ ├── breadcrumb.ts │ │ └── breadcrumb.stories.tsx │ ├── tooltip │ │ ├── tooltip.ts │ │ └── tooltip.stories.tsx │ ├── heading │ │ ├── heading.ts │ │ └── heading.stories.tsx │ ├── textarea │ │ ├── textarea.ts │ │ └── textarea.stories.tsx │ ├── editable │ │ ├── editable.ts │ │ └── editable.stories.tsx │ ├── form-error │ │ ├── form-error.ts │ │ └── form-error.stories.tsx │ ├── form │ │ ├── form.ts │ │ └── form.stories.tsx │ ├── stat │ │ ├── stat.ts │ │ └── stat.stories.tsx │ ├── pin-input │ │ ├── pin-input.ts │ │ └── pin-input.stories.tsx │ ├── skeleton │ │ ├── skeleton.ts │ │ └── skeleton.stories.tsx │ ├── accordion │ │ ├── accordion.ts │ │ └── accordion.stories.tsx │ ├── close-button │ │ ├── close-button.ts │ │ └── close-button.stories.tsx │ ├── radio │ │ ├── radio.ts │ │ └── radio.stories.tsx │ ├── select │ │ ├── select.stories.tsx │ │ └── select.ts │ ├── avatar │ │ ├── avatar.stories.tsx │ │ └── avatar.ts │ ├── number-input │ │ ├── number-input.stories.tsx │ │ └── number-input.ts │ ├── popover │ │ ├── popover.ts │ │ └── popover.stories.tsx │ ├── index.ts │ ├── menu │ │ ├── menu.ts │ │ └── menu.stories.tsx │ ├── tag │ │ └── tag.ts │ ├── badge │ │ └── badge.ts │ ├── drawer │ │ ├── drawer.ts │ │ └── drawer.stories.tsx │ ├── modal │ │ ├── modal.stories.tsx │ │ └── modal.ts │ ├── switch │ │ ├── switch.ts │ │ └── switch.stories.tsx │ ├── progress │ │ └── progress.ts │ ├── checkbox │ │ └── checkbox.ts │ ├── alert │ │ └── alert.ts │ ├── table │ │ └── table.stories.tsx │ └── button │ │ └── button.ts │ ├── foundations │ ├── colors.stories.tsx │ ├── colors.ts │ └── colors.test.tsx │ ├── index.ts │ └── styles.ts ├── .gitignore ├── cypress.json ├── doc └── images │ ├── plus.png │ ├── chakra-ui-logo.png │ └── radix-ui-logo.png ├── cypress ├── fixtures │ ├── profile.json │ └── example.json ├── tsconfig.json ├── support │ ├── index.js │ └── commands.js ├── integration │ └── components │ │ ├── container.spec.ts │ │ ├── stat.spec.ts │ │ ├── list.spec.ts │ │ ├── breadcrumb.spec.ts │ │ ├── editable.spec.ts │ │ ├── heading.spec.ts │ │ ├── kbd.spec.ts │ │ ├── form-label.spec.ts │ │ ├── pin-input.spec.ts │ │ ├── select.spec.ts │ │ ├── skip-link.spec.ts │ │ ├── spinner.spec.ts │ │ ├── skeleton.spec.ts │ │ ├── divider.spec.ts │ │ ├── link.spec.ts │ │ ├── number-input.spec.ts │ │ ├── modal.spec.ts │ │ ├── tooltip.spec.ts │ │ ├── form-error.spec.ts │ │ ├── form.spec.ts │ │ ├── popover.spec.ts │ │ ├── drawer.spec.ts │ │ ├── accordion.spec.ts │ │ ├── textarea.spec.ts │ │ ├── radio.spec.ts │ │ ├── tag.spec.ts │ │ ├── close-button.spec.ts │ │ ├── menu.spec.ts │ │ ├── avatar.spec.ts │ │ ├── table.spec.ts │ │ └── code.spec.ts └── plugins │ └── index.js ├── babel.config.js ├── release.config.js ├── .storybook ├── preview.js ├── decorators │ └── chakraDecorator.tsx └── main.js ├── .npmignore ├── .github ├── dependabot.yml └── workflows │ ├── push-to-main.yml │ └── pull-on-main.yml ├── LICENSE └── package.json /src/util/index.tsx: -------------------------------------------------------------------------------- 1 | export * from "./helpers"; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | coverage/ 4 | out/ -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./theme"; 2 | export * from "./util"; 3 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "video": false, 3 | "screenshotOnRunFailure": false 4 | } 5 | -------------------------------------------------------------------------------- /doc/images/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dub-stack/chakra-radix-colors/HEAD/doc/images/plus.png -------------------------------------------------------------------------------- /cypress/fixtures/profile.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 8739, 3 | "name": "Jane", 4 | "email": "jane@example.com" 5 | } -------------------------------------------------------------------------------- /doc/images/chakra-ui-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dub-stack/chakra-radix-colors/HEAD/doc/images/chakra-ui-logo.png -------------------------------------------------------------------------------- /doc/images/radix-ui-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dub-stack/chakra-radix-colors/HEAD/doc/images/radix-ui-logo.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ["@babel/preset-env", { targets: { node: "current" } }], 4 | "@babel/preset-react", 5 | "@babel/preset-typescript", 6 | ], 7 | }; 8 | -------------------------------------------------------------------------------- /cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } 6 | -------------------------------------------------------------------------------- /release.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | branches: ["main"], 3 | plugins: [ 4 | "@semantic-release/commit-analyzer", 5 | "@semantic-release/release-notes-generator", 6 | "@semantic-release/npm", 7 | "@semantic-release/github", 8 | ], 9 | }; 10 | -------------------------------------------------------------------------------- /src/theme/components/container/container.ts: -------------------------------------------------------------------------------- 1 | import type { SystemStyleObject } from "@chakra-ui/theme-tools"; 2 | 3 | const baseStyle: SystemStyleObject = { 4 | w: "100%", 5 | mx: "auto", 6 | maxW: "60ch", 7 | px: "1rem", 8 | }; 9 | 10 | export default { 11 | baseStyle, 12 | }; 13 | -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | import { chakraDecorator } from "./decorators/chakraDecorator"; 2 | 3 | export const parameters = { 4 | actions: { argTypesRegex: "^on[A-Z].*" }, 5 | controls: { 6 | matchers: { 7 | color: /(background|color)$/i, 8 | date: /Date$/, 9 | }, 10 | }, 11 | }; 12 | 13 | // export const decorators = [chakraDecorator]; 14 | -------------------------------------------------------------------------------- /.storybook/decorators/chakraDecorator.tsx: -------------------------------------------------------------------------------- 1 | import { ChakraProvider, ColorModeScript } from "@chakra-ui/react"; 2 | import theme from "../../src/theme"; 3 | 4 | export const chakraDecorator = (Story) => ( 5 | <> 6 | 7 | 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /cypress/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["es5", "dom"], 5 | "types": ["cypress", "cypress-real-events"], 6 | "baseUrl": "..", 7 | "paths": { /* Specify a set of entries that re-map imports to additional lookup locations. */ 8 | "*": ["src/*"] 9 | } 10 | }, 11 | "include": ["**/*.ts"] 12 | } -------------------------------------------------------------------------------- /src/theme/components/code/code.ts: -------------------------------------------------------------------------------- 1 | import type { SystemStyleObject } from "@chakra-ui/theme-tools"; 2 | import Badge from "../badge/badge"; 3 | 4 | const { variants, defaultProps } = Badge; 5 | 6 | const baseStyle: SystemStyleObject = { 7 | fontFamily: "mono", 8 | fontSize: "sm", 9 | px: "0.2em", 10 | borderRadius: "sm", 11 | }; 12 | 13 | export default { 14 | baseStyle, 15 | variants, 16 | defaultProps, 17 | }; 18 | -------------------------------------------------------------------------------- /src/theme/components/form-label/form-label.ts: -------------------------------------------------------------------------------- 1 | import type { SystemStyleObject } from "@chakra-ui/theme-tools"; 2 | 3 | const baseStyle: SystemStyleObject = { 4 | fontSize: "md", 5 | marginEnd: 3, 6 | mb: 2, 7 | fontWeight: "medium", 8 | transitionProperty: "common", 9 | transitionDuration: "normal", 10 | opacity: 1, 11 | _disabled: { 12 | opacity: 0.4, 13 | }, 14 | }; 15 | 16 | export default { 17 | baseStyle, 18 | }; 19 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | !package.json 2 | !LICENSE 3 | 4 | # ignore all test and story files 5 | dist/**/*.test.{ts,tsx,js,jsx} 6 | dist/**/*.stories.{ts,tsx,js,jsx} 7 | dist/util/test-utils.tsx 8 | .storybook/ 9 | coverage/ 10 | cypress/ 11 | cypress.json 12 | .github/ 13 | 14 | # ignore all config files 15 | *.config.{ts,tsx,js,jsx} 16 | tsconfig.json 17 | 18 | # ignore all source files 19 | src/ 20 | 21 | # ignore npm package files 22 | out/ 23 | 24 | # ignore documentation 25 | doc/ -------------------------------------------------------------------------------- /src/theme/components/link/link.ts: -------------------------------------------------------------------------------- 1 | import type { SystemStyleObject } from "@chakra-ui/theme-tools"; 2 | 3 | const baseStyle: SystemStyleObject = { 4 | transitionProperty: "common", 5 | transitionDuration: "fast", 6 | transitionTimingFunction: "ease-out", 7 | cursor: "pointer", 8 | textDecoration: "none", 9 | outline: "none", 10 | color: "inherit", 11 | _hover: { 12 | textDecoration: "underline", 13 | }, 14 | _focus: { 15 | boxShadow: "outline", 16 | }, 17 | }; 18 | 19 | export default { 20 | baseStyle, 21 | }; 22 | -------------------------------------------------------------------------------- /src/theme/components/list/list.ts: -------------------------------------------------------------------------------- 1 | import { listAnatomy as parts } from "@chakra-ui/anatomy"; 2 | import type { 3 | PartsStyleObject, 4 | SystemStyleObject, 5 | } from "@chakra-ui/theme-tools"; 6 | 7 | const baseStyleIcon: SystemStyleObject = { 8 | marginEnd: "0.5rem", 9 | display: "inline", 10 | verticalAlign: "text-bottom", 11 | }; 12 | 13 | const baseStyle: PartsStyleObject = { 14 | container: {}, 15 | item: {}, 16 | icon: baseStyleIcon, 17 | }; 18 | 19 | export default { 20 | parts: parts.keys, 21 | baseStyle, 22 | }; 23 | -------------------------------------------------------------------------------- /src/theme/components/divider/divider.ts: -------------------------------------------------------------------------------- 1 | import type { SystemStyleObject } from "@chakra-ui/theme-tools"; 2 | 3 | const baseStyle: SystemStyleObject = { 4 | opacity: 0.6, 5 | borderColor: "inherit", 6 | }; 7 | 8 | const variantSolid: SystemStyleObject = { 9 | borderStyle: "solid", 10 | }; 11 | 12 | const variantDashed: SystemStyleObject = { 13 | borderStyle: "dashed", 14 | }; 15 | 16 | const variants = { 17 | solid: variantSolid, 18 | dashed: variantDashed, 19 | }; 20 | 21 | const defaultProps = { 22 | variant: "solid", 23 | }; 24 | 25 | export default { 26 | baseStyle, 27 | variants, 28 | defaultProps, 29 | }; 30 | -------------------------------------------------------------------------------- /src/theme/foundations/colors.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { ComponentStory, ComponentMeta } from "@storybook/react"; 3 | import { Box } from "@chakra-ui/react"; 4 | import { Decorators } from "util/storybook-utils"; 5 | 6 | export default { 7 | title: "Colors", 8 | component: Box, 9 | } as ComponentMeta; 10 | 11 | const New = ; 12 | const Default = ; 13 | 14 | const Template: ComponentStory = (args) => { 15 | return ; 16 | }; 17 | 18 | export const Primary = Template.bind({}); 19 | -------------------------------------------------------------------------------- /src/theme/index.ts: -------------------------------------------------------------------------------- 1 | import { extendTheme, Theme } from "@chakra-ui/react"; 2 | 3 | // Global style overrides 4 | import styles from "./styles"; 5 | 6 | // Foundational style overrides 7 | import colors, { RadixColorsType } from "./foundations/colors"; 8 | 9 | // Component style overrides 10 | import * as components from "./components"; 11 | 12 | // create the theme 13 | const theme = extendTheme({ 14 | colors: { ...colors }, 15 | components: { ...components }, 16 | styles: { ...styles }, 17 | }) as unknown as Omit & { colors: RadixColorsType }; 18 | theme.colors = colors; // remove the default @chakra-ui colors 19 | 20 | // export the theme 21 | export { theme }; 22 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | 6 | # update dependencies on sunday at 9:00AM CST 7 | schedule: 8 | interval: "weekly" 9 | day: "sunday" 10 | time: "09:00" 11 | timezone: "America/Chicago" 12 | 13 | # keep all dependencies up-to-date 14 | allow: 15 | - dependency-type: "all" 16 | 17 | # see how this plays with mergify, don't need to update the 18 | # package and trigger release with only a dev-deps update 19 | commit-message: 20 | prefix: "chore" 21 | prefix-development: "chore" 22 | include: "scope" 23 | 24 | labels: 25 | - "dependency" 26 | -------------------------------------------------------------------------------- /.github/workflows/push-to-main.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: [main] 5 | 6 | jobs: 7 | # PUBLISH_TO_NPM: ✅ 8 | # publish-to-npm job exists to publish a new patch or minor version to NPM. 9 | release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: 14 17 | - run: npm install 18 | - run: npm run build 19 | - name: Semantic Release 20 | uses: cycjimmy/semantic-release-action@v2 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 24 | -------------------------------------------------------------------------------- /src/theme/components/kbd/kbd.ts: -------------------------------------------------------------------------------- 1 | import type { SystemStyleFunction } from "@chakra-ui/theme-tools"; 2 | import { mode } from "@chakra-ui/theme-tools"; 3 | import { getColorInfo } from "../../../util/helpers"; 4 | 5 | const baseStyle: SystemStyleFunction = (props) => { 6 | const { theme } = props; 7 | const { light: _gray, dark: _grayDark } = getColorInfo("_gray", theme); 8 | 9 | return { 10 | bg: mode(`${_gray}.3`, `${_grayDark}.3`)(props), 11 | borderRadius: "md", 12 | borderWidth: "1px", 13 | borderBottomWidth: "3px", 14 | fontSize: "0.8em", 15 | fontWeight: "bold", 16 | lineHeight: "normal", 17 | px: "0.4em", 18 | whiteSpace: "nowrap", 19 | }; 20 | }; 21 | 22 | export default { 23 | baseStyle, 24 | }; 25 | -------------------------------------------------------------------------------- /src/theme/components/skip-link/skip-link.ts: -------------------------------------------------------------------------------- 1 | import type { SystemStyleFunction } from "@chakra-ui/theme-tools"; 2 | import { mode } from "@chakra-ui/theme-tools"; 3 | import { getColorInfo } from "../../../util/helpers"; 4 | 5 | const baseStyle: SystemStyleFunction = (props) => { 6 | const { theme } = props; 7 | const { light: _gray, dark: _grayDark } = getColorInfo("_gray", theme); 8 | 9 | return { 10 | borderRadius: "md", 11 | fontWeight: "semibold", 12 | _focus: { 13 | boxShadow: "outline", 14 | padding: "1rem", 15 | position: "fixed", 16 | top: "1.5rem", 17 | insetStart: "1.5rem", 18 | bg: mode(`${_gray}.1`, `${_grayDark}.1`)(props), 19 | }, 20 | }; 21 | }; 22 | 23 | export default { 24 | baseStyle, 25 | }; 26 | -------------------------------------------------------------------------------- /src/theme/components/spinner/spinner.ts: -------------------------------------------------------------------------------- 1 | import { cssVar, SystemStyleObject } from "@chakra-ui/theme-tools"; 2 | 3 | const $size = cssVar("spinner-size"); 4 | 5 | const baseStyle: SystemStyleObject = { 6 | width: [$size.reference], 7 | height: [$size.reference], 8 | }; 9 | 10 | const sizes: Record = { 11 | xs: { 12 | [$size.variable]: "0.75rem", 13 | }, 14 | sm: { 15 | [$size.variable]: "1rem", 16 | }, 17 | md: { 18 | [$size.variable]: "1.5rem", 19 | }, 20 | lg: { 21 | [$size.variable]: "2rem", 22 | }, 23 | xl: { 24 | [$size.variable]: "3rem", 25 | }, 26 | }; 27 | 28 | const defaultProps = { 29 | size: "md", 30 | }; 31 | 32 | export default { 33 | baseStyle, 34 | sizes, 35 | defaultProps, 36 | }; 37 | -------------------------------------------------------------------------------- /src/theme/components/breadcrumb/breadcrumb.ts: -------------------------------------------------------------------------------- 1 | import { breadcrumbAnatomy as parts } from "@chakra-ui/anatomy"; 2 | import type { 3 | PartsStyleObject, 4 | SystemStyleObject, 5 | } from "@chakra-ui/theme-tools"; 6 | 7 | const baseStyleLink: SystemStyleObject = { 8 | transitionProperty: "common", 9 | transitionDuration: "fast", 10 | transitionTimingFunction: "ease-out", 11 | cursor: "pointer", 12 | textDecoration: "none", 13 | outline: "none", 14 | color: "inherit", 15 | _hover: { 16 | textDecoration: "underline", 17 | }, 18 | _focus: { 19 | boxShadow: "outline", 20 | }, 21 | }; 22 | 23 | const baseStyle: PartsStyleObject = { 24 | link: baseStyleLink, 25 | }; 26 | 27 | export default { 28 | parts: parts.keys, 29 | baseStyle, 30 | }; 31 | -------------------------------------------------------------------------------- /cypress/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import "./commands"; 18 | import "cypress-real-events/support"; 19 | 20 | // Alternatively you can use CommonJS syntax: 21 | // require('./commands') 22 | -------------------------------------------------------------------------------- /cypress/integration/components/container.spec.ts: -------------------------------------------------------------------------------- 1 | describe("Default", () => { 2 | beforeEach(() => { 3 | cy.visit( 4 | "http://localhost:6006/iframe.html?id=components-container--default&args=&viewMode=story" 5 | ); 6 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 7 | }); 8 | 9 | it("displays in light mode correctly", () => { 10 | // no theme changes, but make sure this mounts correctly 11 | cy.get("[data-testid=NewDefault] .chakra-container"); 12 | }); 13 | 14 | it("displays in dark mode correctly", () => { 15 | cy.get("#switch-color-mode").click(); 16 | 17 | // no theme changes, but make sure this mounts correctly 18 | cy.get("[data-testid=NewDefault] .chakra-container"); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /src/theme/styles.ts: -------------------------------------------------------------------------------- 1 | import { mode, StyleFunctionProps, Styles } from "@chakra-ui/theme-tools"; 2 | 3 | export function globalStyles(props: StyleFunctionProps) { 4 | return { 5 | body: { 6 | fontFamily: "body", 7 | color: mode("_gray.12", "_grayDark.12")(props), 8 | bg: mode("_gray.1", "_grayDark.1")(props), 9 | transitionProperty: "background-color", 10 | transisionDuration: "normal", 11 | lineHeight: "base", 12 | }, 13 | "*::placeholder": { 14 | color: mode("_gray.8", "_grayDark.8")(props), 15 | }, 16 | "*, *::before, &::after": { 17 | borderColor: mode("_gray.6", "_grayDark.6")(props), 18 | wordWrap: "break-word", 19 | }, 20 | }; 21 | } 22 | 23 | const styles: Styles = { 24 | global: globalStyles, 25 | }; 26 | 27 | export default styles; 28 | -------------------------------------------------------------------------------- /cypress/plugins/index.js: -------------------------------------------------------------------------------- 1 | /// 2 | // *********************************************************** 3 | // This example plugins/index.js can be used to load plugins 4 | // 5 | // You can change the location of this file or turn off loading 6 | // the plugins file with the 'pluginsFile' configuration option. 7 | // 8 | // You can read more here: 9 | // https://on.cypress.io/plugins-guide 10 | // *********************************************************** 11 | 12 | // This function is called when a project is opened or re-opened (e.g. due to 13 | // the project's config changing) 14 | require("tsconfig-paths").register(); 15 | 16 | /** 17 | * @type {Cypress.PluginConfig} 18 | */ 19 | // eslint-disable-next-line no-unused-vars 20 | module.exports = (on, config) => { 21 | // `on` is used to hook into various events Cypress emits 22 | // `config` is the resolved Cypress config 23 | }; 24 | -------------------------------------------------------------------------------- /cypress/integration/components/stat.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-stat--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | const _2em = "24px"; 13 | cy.get("[data-testid=NewDefault] .chakra-stat__number").should( 14 | "have.css", 15 | "font-size", 16 | _2em 17 | ); 18 | }); 19 | 20 | it("displays in dark mode correctly", () => { 21 | const _2em = "24px"; 22 | cy.get("[data-testid=NewDefault] .chakra-stat__number").should( 23 | "have.css", 24 | "font-size", 25 | _2em 26 | ); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /cypress/integration/components/list.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-list--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] .chakra-icon").should( 13 | "have.css", 14 | "color", 15 | getRgbFromThemeColor("_gray.12") 16 | ); 17 | }); 18 | 19 | it("displays in dark mode correctly", () => { 20 | cy.get("#switch-color-mode").click(); 21 | cy.get("[data-testid=NewDefault] .chakra-icon").should( 22 | "have.css", 23 | "color", 24 | getRgbFromThemeColor("_grayDark.12") 25 | ); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /src/theme/components/tooltip/tooltip.ts: -------------------------------------------------------------------------------- 1 | import { mode, cssVar, SystemStyleFunction } from "@chakra-ui/theme-tools"; 2 | import { getColorInfo } from "../../../util/helpers"; 3 | 4 | const $bg = cssVar("tooltip-bg"); 5 | const $arrowBg = cssVar("popper-arrow-bg"); 6 | 7 | const baseStyle: SystemStyleFunction = (props) => { 8 | const { theme } = props; 9 | const { light: _gray, dark: _grayDark } = getColorInfo("_gray", theme); 10 | 11 | const bg = mode(`${_grayDark}.2`, `${_gray}.2`)(props); 12 | return { 13 | [$bg.variable]: `colors.${bg}`, 14 | px: "8px", 15 | py: "2px", 16 | bg: [$bg.reference], 17 | [$arrowBg.variable]: [$bg.reference], 18 | color: mode(`${_gray}.1`, `${_grayDark}.1`)(props), 19 | borderRadius: "sm", 20 | fontWeight: "medium", 21 | fontSize: "sm", 22 | boxShadow: "md", 23 | maxW: "320px", 24 | zIndex: "tooltip", 25 | }; 26 | }; 27 | 28 | export default { 29 | baseStyle, 30 | }; 31 | -------------------------------------------------------------------------------- /cypress/integration/components/breadcrumb.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-breadcrumb--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] .chakra-breadcrumb__list-item") 13 | .eq(0) 14 | .should("have.css", "color", getRgbFromThemeColor("_gray.12")); 15 | }); 16 | it("displays in dark mode correctly", () => { 17 | cy.get("#switch-color-mode").click(); 18 | cy.get("[data-testid=NewDefault] .chakra-breadcrumb__list-item") 19 | .eq(0) 20 | .should("have.css", "color", getRgbFromThemeColor("_grayDark.12")); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /cypress/integration/components/editable.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-editable--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] .chakra-editable").should( 13 | "have.css", 14 | "color", 15 | getRgbFromThemeColor("_gray.12") 16 | ); 17 | }); 18 | 19 | it("displays in dark mode correctly", () => { 20 | cy.get("#switch-color-mode").click(); 21 | cy.get("[data-testid=NewDefault] .chakra-editable").should( 22 | "have.css", 23 | "color", 24 | getRgbFromThemeColor("_grayDark.12") 25 | ); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /cypress/integration/components/heading.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-heading--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] .chakra-heading").should( 13 | "have.css", 14 | "color", 15 | getRgbFromThemeColor("_gray.12") 16 | ); 17 | }); 18 | 19 | it("displays in dark mode correctly", () => { 20 | cy.get("#switch-color-mode").click(); 21 | cy.get("[data-testid=NewDefault] .chakra-heading").should( 22 | "have.css", 23 | "color", 24 | getRgbFromThemeColor("_grayDark.12") 25 | ); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /cypress/integration/components/kbd.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-kbd--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] .chakra-kbd").should( 13 | "have.css", 14 | "background-color", 15 | getRgbFromThemeColor("_gray.3") 16 | ); 17 | }); 18 | 19 | it("displays in dark mode correctly", () => { 20 | cy.get("#switch-color-mode").click(); 21 | cy.get("[data-testid=NewDefault] .chakra-kbd").should( 22 | "have.css", 23 | "background-color", 24 | getRgbFromThemeColor("_grayDark.3") 25 | ); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /cypress/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add('login', (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This will overwrite an existing command -- 25 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /cypress/integration/components/form-label.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-formlabel--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] .chakra-form__label").should( 13 | "have.css", 14 | "color", 15 | getRgbFromThemeColor("_gray.12") 16 | ); 17 | }); 18 | 19 | it("displays in dark mode correctly", () => { 20 | cy.get("#switch-color-mode").click(); 21 | cy.get("[data-testid=NewDefault] .chakra-form__label").should( 22 | "have.css", 23 | "color", 24 | getRgbFromThemeColor("_grayDark.12") 25 | ); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /src/util/cypress-utils.ts: -------------------------------------------------------------------------------- 1 | import { getColor } from "@chakra-ui/theme-tools"; 2 | import { theme } from "../theme"; 3 | import { hsl, hex } from "color-convert"; 4 | 5 | /** 6 | * Turns an HSL string into an array of the h, s, l values. 7 | * 8 | * @example normalizeHslString("hsl(360, 97.9%, 94.8%)") -> [360, 97.9, 94.8] 9 | * 10 | * @param hsl An hsl string 11 | * @returns 12 | */ 13 | function normalizeHslString(hsl: string) { 14 | let [h, s, l] = hsl 15 | .replace(/[^\d,.]/g, "") 16 | .split(",") 17 | .map((item) => parseFloat(item)); 18 | 19 | return [h, s, l]; 20 | } 21 | 22 | export function getRgbFromThemeColor(color: string) { 23 | const c = getColor(theme, color); 24 | let [h, s, l] = normalizeHslString(c); 25 | let [r, g, b] = hsl.rgb([h, s, l]); 26 | return `rgb(${r}, ${g}, ${b})`; 27 | } 28 | 29 | export function getRgbFromHex(color: string) { 30 | let [r, g, b] = hex.rgb(color); 31 | return `rgb(${r}, ${g}, ${b})`; 32 | } 33 | -------------------------------------------------------------------------------- /cypress/integration/components/pin-input.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-pininput--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] .chakra-pin-input").should( 13 | "have.css", 14 | "border-color", 15 | getRgbFromThemeColor("_gray.6") 16 | ); 17 | }); 18 | 19 | it("displays in dark mode correctly", () => { 20 | cy.get("#switch-color-mode").click(); 21 | cy.get("[data-testid=NewDefault] .chakra-pin-input").should( 22 | "have.css", 23 | "border-color", 24 | getRgbFromThemeColor("_grayDark.6") 25 | ); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /cypress/integration/components/select.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-select--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] .chakra-select").should( 13 | "have.css", 14 | "background-color", 15 | getRgbFromThemeColor("_gray.3") 16 | ); 17 | }); 18 | 19 | it("displays in dark mode correctly", () => { 20 | cy.get("#switch-color-mode").click(); 21 | cy.get("[data-testid=NewDefault] .chakra-select").should( 22 | "have.css", 23 | "background-color", 24 | getRgbFromThemeColor("_grayDark.3") 25 | ); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /cypress/integration/components/skip-link.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-skipnavlink--default&args=&viewMode=story#chakra-skip-nav" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] a") 13 | .focus() 14 | .should("have.css", "background-color", getRgbFromThemeColor("_gray.1")); 15 | }); 16 | 17 | it("displays in dark mode correctly", () => { 18 | cy.get("#switch-color-mode").click(); 19 | cy.get("[data-testid=NewDefault] a") 20 | .focus() 21 | .should( 22 | "have.css", 23 | "background-color", 24 | getRgbFromThemeColor("_grayDark.1") 25 | ); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /src/theme/components/heading/heading.ts: -------------------------------------------------------------------------------- 1 | import { SystemStyleObject } from "@chakra-ui/theme-tools"; 2 | 3 | const baseStyle: SystemStyleObject = { 4 | fontFamily: "heading", 5 | fontWeight: "bold", 6 | }; 7 | 8 | const sizes: Record = { 9 | "4xl": { 10 | fontSize: ["6xl", null, "7xl"], 11 | lineHeight: 1, 12 | }, 13 | "3xl": { 14 | fontSize: ["5xl", null, "6xl"], 15 | lineHeight: 1, 16 | }, 17 | "2xl": { 18 | fontSize: ["4xl", null, "5xl"], 19 | lineHeight: [1.2, null, 1], 20 | }, 21 | xl: { 22 | fontSize: ["3xl", null, "4xl"], 23 | lineHeight: [1.33, null, 1.2], 24 | }, 25 | lg: { 26 | fontSize: ["2xl", null, "3xl"], 27 | lineHeight: [1.33, null, 1.2], 28 | }, 29 | md: { fontSize: "xl", lineHeight: 1.2 }, 30 | sm: { fontSize: "md", lineHeight: 1.2 }, 31 | xs: { fontSize: "sm", lineHeight: 1.2 }, 32 | }; 33 | 34 | const defaultProps = { 35 | size: "xl", 36 | }; 37 | 38 | export default { 39 | baseStyle, 40 | sizes, 41 | defaultProps, 42 | }; 43 | -------------------------------------------------------------------------------- /cypress/integration/components/spinner.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-spinner--default&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | const c = getRgbFromThemeColor("_gray.12"); 13 | cy.get("[data-testid=NewDefault] .chakra-spinner").should( 14 | "have.css", 15 | "border-color", 16 | `${c} ${c} rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)` 17 | ); 18 | }); 19 | 20 | it("displays in dark mode correctly", () => { 21 | cy.get("#switch-color-mode").click(); 22 | 23 | const c = getRgbFromThemeColor("_grayDark.12"); 24 | cy.get("[data-testid=NewDefault] .chakra-spinner").should( 25 | "have.css", 26 | "border-color", 27 | `${c} ${c} rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)` 28 | ); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /cypress/integration/components/skeleton.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-skeleton--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | const animation = 13 | "0.8s linear 0s infinite alternate none running animation-12xlxsq"; 14 | cy.get("[data-testid=NewDefault] .chakra-skeleton") 15 | .eq(0) 16 | .should("have.css", "animation", animation); 17 | }); 18 | 19 | it("displays in dark mode correctly", () => { 20 | cy.get("#switch-color-mode").click(); 21 | 22 | const animation = 23 | "0.8s linear 0s infinite alternate none running animation-t2xdlo"; 24 | cy.get("[data-testid=NewDefault] .chakra-skeleton") 25 | .eq(0) 26 | .should("have.css", "animation", animation); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /src/theme/components/textarea/textarea.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | SystemStyleInterpolation, 3 | SystemStyleObject, 4 | } from "@chakra-ui/theme-tools"; 5 | import Input from "../input/input"; 6 | 7 | const baseStyle: SystemStyleObject = { 8 | ...Input.baseStyle.field, 9 | paddingY: "8px", 10 | minHeight: "80px", 11 | lineHeight: "short", 12 | verticalAlign: "top", 13 | }; 14 | 15 | const variants: Record = { 16 | outline: (props) => Input.variants.outline(props).field ?? {}, 17 | flushed: (props) => Input.variants.flushed(props).field ?? {}, 18 | filled: (props) => Input.variants.filled(props).field ?? {}, 19 | unstyled: Input.variants.unstyled.field ?? {}, 20 | }; 21 | 22 | const sizes: Record = { 23 | xs: Input.sizes.xs.field ?? {}, 24 | sm: Input.sizes.sm.field ?? {}, 25 | md: Input.sizes.md.field ?? {}, 26 | lg: Input.sizes.lg.field ?? {}, 27 | }; 28 | 29 | const defaultProps = { 30 | size: "md", 31 | variant: "outline", 32 | }; 33 | 34 | export default { 35 | baseStyle, 36 | sizes, 37 | variants, 38 | defaultProps, 39 | }; 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 dub-stack 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 | -------------------------------------------------------------------------------- /cypress/integration/components/divider.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-divider--default&args=&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] hr") 13 | .eq(0) 14 | .should("have.css", "color", getRgbFromThemeColor("_gray.12")); 15 | cy.get("[data-testid=NewDefault] hr") 16 | .eq(1) 17 | .should("have.css", "color", getRgbFromThemeColor("_gray.12")); 18 | }); 19 | 20 | it("displays in dark mode correctly", () => { 21 | cy.get("#switch-color-mode").click(); 22 | cy.get("[data-testid=NewDefault] hr") 23 | .eq(0) 24 | .should("have.css", "color", getRgbFromThemeColor("_grayDark.12")); 25 | cy.get("[data-testid=NewDefault] hr") 26 | .eq(1) 27 | .should("have.css", "color", getRgbFromThemeColor("_grayDark.12")); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /src/theme/components/editable/editable.ts: -------------------------------------------------------------------------------- 1 | import { editableAnatomy as parts } from "@chakra-ui/anatomy"; 2 | import type { 3 | PartsStyleObject, 4 | SystemStyleObject, 5 | } from "@chakra-ui/theme-tools"; 6 | 7 | const baseStylePreview: SystemStyleObject = { 8 | borderRadius: "md", 9 | py: "3px", 10 | transitionProperty: "common", 11 | transitionDuration: "normal", 12 | }; 13 | 14 | const baseStyleInput: SystemStyleObject = { 15 | borderRadius: "md", 16 | py: "3px", 17 | transitionProperty: "common", 18 | transitionDuration: "normal", 19 | width: "full", 20 | _focus: { boxShadow: "outline" }, 21 | _placeholder: { opacity: 0.6 }, 22 | }; 23 | 24 | const baseStyleTextarea: SystemStyleObject = { 25 | borderRadius: "md", 26 | py: "3px", 27 | transitionProperty: "common", 28 | transitionDuration: "normal", 29 | width: "full", 30 | _focus: { boxShadow: "outline" }, 31 | _placeholder: { opacity: 0.6 }, 32 | }; 33 | 34 | const baseStyle: PartsStyleObject = { 35 | preview: baseStylePreview, 36 | input: baseStyleInput, 37 | textarea: baseStyleTextarea, 38 | }; 39 | 40 | export default { 41 | parts: parts.keys, 42 | baseStyle, 43 | }; 44 | -------------------------------------------------------------------------------- /src/theme/components/form-error/form-error.ts: -------------------------------------------------------------------------------- 1 | import { formErrorAnatomy as parts } from "@chakra-ui/anatomy"; 2 | import type { 3 | PartsStyleFunction, 4 | SystemStyleFunction, 5 | } from "@chakra-ui/theme-tools"; 6 | import { mode } from "@chakra-ui/theme-tools"; 7 | import { getColorInfo } from "../../../util/helpers"; 8 | 9 | const baseStyleText: SystemStyleFunction = (props) => { 10 | const { theme } = props; 11 | const { light: redLight, dark: redDark } = getColorInfo("red", theme); 12 | 13 | return { 14 | color: mode(`${redLight}.9`, `${redDark}.9`)(props), 15 | mt: 2, 16 | fontSize: "sm", 17 | lineHeight: "normal", 18 | }; 19 | }; 20 | 21 | const baseStyleIcon: SystemStyleFunction = (props) => { 22 | const { theme } = props; 23 | const { light: redLight, dark: redDark } = getColorInfo("red", theme); 24 | 25 | return { 26 | marginEnd: "0.5em", 27 | color: mode(`${redLight}.9`, `${redDark}.9`)(props), 28 | }; 29 | }; 30 | 31 | const baseStyle: PartsStyleFunction = (props) => ({ 32 | text: baseStyleText(props), 33 | icon: baseStyleIcon(props), 34 | }); 35 | 36 | export default { 37 | parts: parts.keys, 38 | baseStyle, 39 | }; 40 | -------------------------------------------------------------------------------- /src/theme/components/form/form.ts: -------------------------------------------------------------------------------- 1 | import { formAnatomy as parts } from "@chakra-ui/anatomy"; 2 | import type { 3 | PartsStyleFunction, 4 | SystemStyleFunction, 5 | } from "@chakra-ui/theme-tools"; 6 | import { mode } from "@chakra-ui/theme-tools"; 7 | import { getColorInfo } from "../../../util/helpers"; 8 | 9 | const baseStyleRequiredIndicator: SystemStyleFunction = (props) => { 10 | const { theme } = props; 11 | const { light: redLight, dark: redDark } = getColorInfo("red", theme); 12 | return { 13 | marginStart: 1, 14 | color: mode(`${redLight}.9`, `${redDark}.9`)(props), 15 | }; 16 | }; 17 | 18 | const baseStyleHelperText: SystemStyleFunction = (props) => { 19 | const { theme } = props; 20 | const { light, dark } = getColorInfo("_gray", theme); 21 | 22 | return { 23 | mt: 2, 24 | color: mode(`${light}.9`, `${dark}.9`)(props), 25 | lineHeight: "normal", 26 | fontSize: "sm", 27 | }; 28 | }; 29 | 30 | const baseStyle: PartsStyleFunction = (props) => ({ 31 | container: { width: "100%", position: "relative" }, 32 | requiredIndicator: baseStyleRequiredIndicator(props), 33 | helperText: baseStyleHelperText(props), 34 | }); 35 | 36 | export default { 37 | parts: parts.keys, 38 | baseStyle, 39 | }; 40 | -------------------------------------------------------------------------------- /src/theme/components/stat/stat.ts: -------------------------------------------------------------------------------- 1 | import { statAnatomy as parts } from "@chakra-ui/anatomy"; 2 | import type { 3 | PartsStyleObject, 4 | SystemStyleObject, 5 | } from "@chakra-ui/theme-tools"; 6 | 7 | const baseStyleLabel: SystemStyleObject = { 8 | fontWeight: "medium", 9 | }; 10 | 11 | const baseStyleHelpText: SystemStyleObject = { 12 | opacity: 0.8, 13 | marginBottom: 2, 14 | }; 15 | 16 | const baseStyleNumber: SystemStyleObject = { 17 | verticalAlign: "baseline", 18 | fontWeight: "semibold", 19 | }; 20 | 21 | const baseStyleIcon: SystemStyleObject = { 22 | marginEnd: 1, 23 | w: "14px", 24 | h: "14px", 25 | verticalAlign: "middle", 26 | }; 27 | 28 | const baseStyle: PartsStyleObject = { 29 | container: {}, 30 | label: baseStyleLabel, 31 | helpText: baseStyleHelpText, 32 | number: baseStyleNumber, 33 | icon: baseStyleIcon, 34 | }; 35 | 36 | const sizes: Record> = { 37 | md: { 38 | label: { fontSize: "sm" }, 39 | helpText: { fontSize: "sm" }, 40 | number: { fontSize: "2xl" }, 41 | }, 42 | }; 43 | 44 | const defaultProps = { 45 | size: "md", 46 | }; 47 | 48 | export default { 49 | parts: parts.keys, 50 | baseStyle, 51 | sizes, 52 | defaultProps, 53 | }; 54 | -------------------------------------------------------------------------------- /cypress/integration/components/link.spec.ts: -------------------------------------------------------------------------------- 1 | import { getRgbFromThemeColor } from "util/cypress-utils"; 2 | 3 | describe("Default", () => { 4 | beforeEach(() => { 5 | cy.visit( 6 | "http://localhost:6006/iframe.html?id=components-link--default&viewMode=story" 7 | ); 8 | cy.get("#reset-color-mode").realHover().click(); // Important! Need to .realHover() to remove the hover state from prior tests. 9 | }); 10 | 11 | it("displays in light mode correctly", () => { 12 | cy.get("[data-testid=NewDefault] .chakra-link") 13 | .realHover() 14 | .wait(200) 15 | .should( 16 | "have.css", 17 | "text-decoration", 18 | `underline solid ${getRgbFromThemeColor("_gray.12")}` 19 | ) 20 | .should("have.css", "color", getRgbFromThemeColor("_gray.12")); 21 | }); 22 | 23 | it("displays in dark mode correctly", () => { 24 | cy.get("#switch-color-mode").click(); 25 | cy.get("[data-testid=NewDefault] .chakra-link") 26 | .realHover() 27 | .wait(200) 28 | .should( 29 | "have.css", 30 | "text-decoration", 31 | `underline solid ${getRgbFromThemeColor("_grayDark.12")}` 32 | ) 33 | .should("have.css", "color", getRgbFromThemeColor("_grayDark.12")); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /src/theme/components/pin-input/pin-input.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | SystemStyleInterpolation, 3 | SystemStyleObject, 4 | } from "@chakra-ui/theme-tools"; 5 | import Input from "../input/input"; 6 | 7 | const baseStyle: SystemStyleObject = { 8 | ...Input.baseStyle.field, 9 | textAlign: "center", 10 | }; 11 | 12 | const sizes: Record = { 13 | lg: { 14 | fontSize: "lg", 15 | w: 12, 16 | h: 12, 17 | borderRadius: "md", 18 | }, 19 | md: { 20 | fontSize: "md", 21 | w: 10, 22 | h: 10, 23 | borderRadius: "md", 24 | }, 25 | sm: { 26 | fontSize: "sm", 27 | w: 8, 28 | h: 8, 29 | borderRadius: "sm", 30 | }, 31 | xs: { 32 | fontSize: "xs", 33 | w: 6, 34 | h: 6, 35 | borderRadius: "sm", 36 | }, 37 | }; 38 | 39 | const variants: Record = { 40 | outline: (props) => Input.variants.outline(props).field ?? {}, 41 | flushed: (props) => Input.variants.flushed(props).field ?? {}, 42 | filled: (props) => Input.variants.filled(props).field ?? {}, 43 | unstyled: Input.variants.unstyled.field ?? {}, 44 | }; 45 | 46 | const defaultProps = Input.defaultProps; 47 | 48 | export default { 49 | baseStyle, 50 | sizes, 51 | variants, 52 | defaultProps, 53 | }; 54 | -------------------------------------------------------------------------------- /src/util/test-utils.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, ReactElement } from "react"; 2 | import { render } from "@testing-library/react"; 3 | import { ChakraProvider } from "@chakra-ui/provider"; 4 | import { theme } from "../theme"; 5 | import { RenderOptions } from "@storybook/addons"; 6 | import { matchers } from "@emotion/jest"; 7 | import { Button, useColorMode } from "@chakra-ui/react"; 8 | 9 | const ColorModeButtons = () => { 10 | const { toggleColorMode, setColorMode } = useColorMode(); 11 | return ( 12 | <> 13 |