diff --git a/package-lock.json b/package-lock.json index a75eab7822..fe50b655c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5375,6 +5375,23 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@storybook/addon-themes": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-themes/-/addon-themes-9.0.2.tgz", + "integrity": "sha512-f9MYge4YWGxz3DTf61i9z47iWdOu4klzsCxQEVlEjf5kAQYxsIRMoZS8RqAegVpt7d4bPR++cY481FUtDnMbFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^9.0.2" + } + }, "node_modules/@storybook/addon-webpack5-compiler-babel": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-babel/-/addon-webpack5-compiler-babel-3.0.6.tgz", @@ -28749,6 +28766,7 @@ "@bundle-stats/utils": "^4.21.1", "ariakit": "2.0.0-next.44", "d3": "7.9.0", + "js-cookie": "2", "modern-css-reset": "1.4.0", "react-use": "17.6.0", "snarkdown": "2.0.0", @@ -28758,6 +28776,7 @@ "@babel/preset-env": "7.28.0", "@babel/preset-react": "7.27.1", "@babel/preset-typescript": "7.27.1", + "@storybook/addon-themes": "9.0.2", "@storybook/addon-webpack5-compiler-babel": "3.0.6", "@storybook/react": "9.0.18", "@storybook/react-webpack5": "9.0.18", @@ -28792,6 +28811,15 @@ "react-router-dom": "^5.0.0" } }, + "packages/ui/node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "packages/utils": { "name": "@bundle-stats/utils", "version": "4.21.1", diff --git a/packages/ui/build/storybook/main.js b/packages/ui/build/storybook/main.js index 6cf6143fb3..1598ef6691 100644 --- a/packages/ui/build/storybook/main.js +++ b/packages/ui/build/storybook/main.js @@ -7,8 +7,10 @@ function getAbsolutePath(value) { module.exports = { framework: getAbsolutePath('@storybook/react-webpack5'), stories: ['../../src/**/*.stories.@(jsx|tsx|mdx)'], - addons: [getAbsolutePath('@storybook/addon-webpack5-compiler-babel')], - + addons: [ + getAbsolutePath('@storybook/addon-webpack5-compiler-babel'), + getAbsolutePath('@storybook/addon-themes'), + ], docs: { autodocs: true, }, diff --git a/packages/ui/build/storybook/preview.tsx b/packages/ui/build/storybook/preview.tsx index d630d99f5f..e107a40d8b 100644 --- a/packages/ui/build/storybook/preview.tsx +++ b/packages/ui/build/storybook/preview.tsx @@ -1,5 +1,6 @@ import React from 'react'; import type { Preview } from '@storybook/react'; +import { withThemeByClassName } from '@storybook/addon-themes'; import '../../src/css/variables.css'; import '../../src/css/default.css'; @@ -7,6 +8,13 @@ import { SvgIcons } from '../../src/assets/icons.svg.jsx'; const preview: Preview = { decorators: [ + withThemeByClassName({ + themes: { + light: 'light-theme', + dark: 'dark-theme', + }, + defaultTheme: 'light', + }), (Story) => (
diff --git a/packages/ui/package.json b/packages/ui/package.json index 05973bee7d..4b2fc9d388 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -39,6 +39,7 @@ "@babel/preset-env": "7.28.0", "@babel/preset-react": "7.27.1", "@babel/preset-typescript": "7.27.1", + "@storybook/addon-themes": "9.0.2", "@storybook/addon-webpack5-compiler-babel": "3.0.6", "@storybook/react": "9.0.18", "@storybook/react-webpack5": "9.0.18", @@ -76,6 +77,7 @@ "@bundle-stats/utils": "^4.21.1", "ariakit": "2.0.0-next.44", "d3": "7.9.0", + "js-cookie": "2.2.1", "modern-css-reset": "1.4.0", "react-use": "17.6.0", "snarkdown": "2.0.0", diff --git a/packages/ui/src/app/app.jsx b/packages/ui/src/app/app.jsx index 081b798658..e057c0388c 100644 --- a/packages/ui/src/app/app.jsx +++ b/packages/ui/src/app/app.jsx @@ -5,6 +5,7 @@ import { HashRouter, NavLink, Route, Switch, useLocation } from 'react-router-do import { COMPONENT } from '@bundle-stats/utils'; import { URLS } from '../constants'; +import { ThemeProvider } from '../context/theme'; import { BundleAssets } from '../components/bundle-assets'; import { BundleAssetsTotals } from '../components/bundle-assets-totals'; import { BundleModules } from '../components/bundle-modules'; @@ -205,10 +206,12 @@ AppComponent.propTypes = { }; export const App = (props) => ( -
-
-
-
-
-
+
+
+
+
+
+
+
+
); diff --git a/packages/ui/src/app/app.module.css b/packages/ui/src/app/app.module.css index 049bd4c9fb..d3304ea3fb 100644 --- a/packages/ui/src/app/app.module.css +++ b/packages/ui/src/app/app.module.css @@ -7,7 +7,7 @@ } .empty { - padding-top: var(--space-large); + padding-top: var(--space-8x); min-height: 80vh; text-align: center; } @@ -18,13 +18,13 @@ } .summaryContainer { - padding-top: var(--space-small); - padding-bottom: var(--space-xxsmall); + padding-top: var(--space-4x); + padding-bottom: var(--space-2x); } .tabsContainer { border-bottom: 1px solid var(--color-outline); - background: var(--color-light); + background: var(--color-background); } .tabs { @@ -40,8 +40,8 @@ } .tabsContent { - padding-top: var(--space-medium); - padding-bottom: var(--space-medium); + padding-top: var(--space-6x); + padding-bottom: var(--space-6x); min-height: 480px; } diff --git a/packages/ui/src/app/header/header.module.css b/packages/ui/src/app/header/header.module.css index d2b153b3e7..64cc43ae04 100644 --- a/packages/ui/src/app/header/header.module.css +++ b/packages/ui/src/app/header/header.module.css @@ -6,23 +6,7 @@ flex: 0 0 auto; } -.toolsGitHub { - display: block; - border-radius: 50%; - opacity: 0.8; - color: var(--color-text-ultra-dark); - transition: var(--transition-out); -} - -.toolsGitHub:hover, -.toolsGitHub:focus, -.toolsGitHub:active { - opacity: 1; - transition: var(--transition-in); -} - -.toolsGitHubIcon { - display: block; +.toolsButton { } @media (min-width: 1140px) { @@ -33,6 +17,6 @@ height: var(--header-height); display: flex; align-items: center; - padding: 0 var(--space-small); + padding: 0 var(--space-4x); } } diff --git a/packages/ui/src/app/header/header.tsx b/packages/ui/src/app/header/header.tsx index 15cec26869..0da2d0ef26 100644 --- a/packages/ui/src/app/header/header.tsx +++ b/packages/ui/src/app/header/header.tsx @@ -3,32 +3,60 @@ import cx from 'classnames'; import config from '../../config.json'; import I18N from '../../i18n'; +import { useTheme } from '../../context/theme'; import { Container } from '../../ui/container'; import { Icon } from '../../ui/icon'; import { FlexStack } from '../../layout/flex-stack'; import { JobsHeader } from '../../components/jobs-header'; import css from './header.module.css'; +import { Button } from '../../ui/button'; interface HeaderProps { jobs: React.ComponentProps
['jobs']; } -export const Header = ({ className = '', jobs }: HeaderProps & React.ComponentProps<'header'>) => ( -
-
-
-
-
-
-
-
-
-
-); +export const Header = ({ className = '', jobs }: HeaderProps & React.ComponentProps<'header'>) => { + const theme = useTheme(); + + return ( +
+
+
+
+ {theme.name === 'dark' ? ( +
theme.update('light')} + className={css.toolsButton} + > +
+
+ ) : ( +
theme.update('dark')} + className={css.toolsButton} + > +
+
+ )} +
+
+
+
+
+
+ ); +}; diff --git a/packages/ui/src/assets/icons.svg b/packages/ui/src/assets/icons.svg index 1b0e11fb8f..a66bd03459 100644 --- a/packages/ui/src/assets/icons.svg +++ b/packages/ui/src/assets/icons.svg @@ -64,6 +64,13 @@
+
+
+
+
+
+
+
@@ -73,6 +80,10 @@
+
+
+
+
diff --git a/packages/ui/src/assets/icons.svg.jsx b/packages/ui/src/assets/icons.svg.jsx index 8e34f82032..8769312b7c 100644 --- a/packages/ui/src/assets/icons.svg.jsx +++ b/packages/ui/src/assets/icons.svg.jsx @@ -9,6 +9,7 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="feather feather-arrow-down" id="arrow" xmlns="http://www.w3.org/2000/svg" > @@ -20,6 +21,7 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="feather feather-arrow-right-circle" viewBox="0 0 24 24" id="arrow-right-circle" xmlns="http://www.w3.org/2000/svg" @@ -45,6 +47,7 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="lucide lucide-chevron-down" viewBox="0 0 24 24" id="chevron-down" xmlns="http://www.w3.org/2000/svg" @@ -57,6 +60,7 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="lucide lucide-chevron-up" viewBox="0 0 24 24" id="chevron-up" xmlns="http://www.w3.org/2000/svg" @@ -97,6 +101,7 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="feather feather-clock" id="clock" xmlns="http://www.w3.org/2000/svg" > @@ -109,6 +114,7 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="feather feather-x-circle" viewBox="0 0 24 24" id="close" xmlns="http://www.w3.org/2000/svg" @@ -123,6 +129,7 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="feather feather-git-commit" id="commit" xmlns="http://www.w3.org/2000/svg" > @@ -157,6 +164,7 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="feather feather-external-link" viewBox="0 0 24 24" id="external-link" xmlns="http://www.w3.org/2000/svg" @@ -170,6 +178,7 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="feather feather-bar-chart" id="filter" xmlns="http://www.w3.org/2000/svg" > @@ -190,6 +199,7 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="feather feather-help-circle" id="help" xmlns="http://www.w3.org/2000/svg" > @@ -216,11 +226,37 @@ export const SvgIcons = (props) => ( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="feather feather-menu" id="menu" xmlns="http://www.w3.org/2000/svg" >
+
+
+
+
+
+
+
(
+
+
+
+
( strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" + className="feather feather-alert-triangle" id="warning" xmlns="http://www.w3.org/2000/svg" > diff --git a/packages/ui/src/assets/icons/monitor.svg b/packages/ui/src/assets/icons/monitor.svg new file mode 100644 index 0000000000..2cf5563d33 --- /dev/null +++ b/packages/ui/src/assets/icons/monitor.svg @@ -0,0 +1,5 @@ +
+
+
+
+ diff --git a/packages/ui/src/assets/icons/moon.svg b/packages/ui/src/assets/icons/moon.svg new file mode 100644 index 0000000000..3e1e2d6350 --- /dev/null +++ b/packages/ui/src/assets/icons/moon.svg @@ -0,0 +1,4 @@ +
+
+
+ diff --git a/packages/ui/src/assets/icons/sun.svg b/packages/ui/src/assets/icons/sun.svg new file mode 100644 index 0000000000..548abb4fe8 --- /dev/null +++ b/packages/ui/src/assets/icons/sun.svg @@ -0,0 +1,5 @@ +
+
+
+
+ diff --git a/packages/ui/src/components/asset-info/asset-info.module.css b/packages/ui/src/components/asset-info/asset-info.module.css index 57a859417c..ab5c5ecac8 100644 --- a/packages/ui/src/components/asset-info/asset-info.module.css +++ b/packages/ui/src/components/asset-info/asset-info.module.css @@ -9,7 +9,7 @@ } .assetNameTagEntry { - background: var(--color-info-dark); + background: var(--color-info-intense); } .assetNameTagInitial { @@ -17,7 +17,7 @@ } .assetNameTagChunk { - background: var(--color-info-light); + background: var(--color-info-muted); } .label { @@ -32,7 +32,7 @@ .runNameTags { display: flex; align-items: center; - gap: calc(var(--space-xxxsmall) / 2); + gap: calc(var(--space) / 2); } .runNameTags:empty { diff --git a/packages/ui/src/components/asset-meta-tag/asset-meta-tag.module.css b/packages/ui/src/components/asset-meta-tag/asset-meta-tag.module.css index f8fb49d437..6c4fffd838 100644 --- a/packages/ui/src/components/asset-meta-tag/asset-meta-tag.module.css +++ b/packages/ui/src/components/asset-meta-tag/asset-meta-tag.module.css @@ -22,7 +22,7 @@ /* tag */ .entry { - --background-color: var(--color-info-dark); + --background-color: var(--color-info-intense); } .entry:empty::before { @@ -38,7 +38,7 @@ } .chunk { - --background-color: var(--color-info-light); + --background-color: var(--color-info-muted); } .chunk:empty::before { @@ -47,10 +47,10 @@ /* status */ .added { - background: linear-gradient(-45deg, var(--color-danger-light) 50%, var(--background-color) 50%) !important; + background: linear-gradient(-45deg, var(--color-danger-muted) 50%, var(--background-color) 50%) !important; } .removed { - background: linear-gradient(135deg, var(--color-danger-light) 50%, var(--background-color) 50%) !important; + background: linear-gradient(135deg, var(--color-danger-muted) 50%, var(--background-color) 50%) !important; } diff --git a/packages/ui/src/components/asset-name/asset-name.module.css b/packages/ui/src/components/asset-name/asset-name.module.css index a7a983123c..d03f5b7f0b 100644 --- a/packages/ui/src/components/asset-name/asset-name.module.css +++ b/packages/ui/src/components/asset-name/asset-name.module.css @@ -1,12 +1,12 @@ .notPredictive { - margin-right: var(--space-xxsmall); + margin-right: var(--space-2x); display: inline-block; - width: var(--space-small); - height: var(--space-small); + width: var(--space-4x); + height: var(--space-4x); } .notPredictiveIcon { - color: var(--color-warning-dark); + color: var(--color-warning-intense); } .notPredictiveHoverCard { @@ -15,11 +15,11 @@ .metaTags { display: inline; - margin-right: var(--space-xxxsmall); + margin-right: var(--space); } .metaTag + .metaTag { - margin-left: calc(var(--space-xxxsmall) / 2); + margin-left: calc(var(--space) / 2); } .metaTags:empty { diff --git a/packages/ui/src/components/bundle-modules/bundle-modules.module.css b/packages/ui/src/components/bundle-modules/bundle-modules.module.css index f063d03c7c..4ab88c2ae0 100644 --- a/packages/ui/src/components/bundle-modules/bundle-modules.module.css +++ b/packages/ui/src/components/bundle-modules/bundle-modules.module.css @@ -1,5 +1,5 @@ .title { - color: var(--color-text-light); + color: var(--color-text-muted); } .toolbarSearch { @@ -12,7 +12,7 @@ } .nameTagDuplicated { - margin-right: var(--space-xxxsmall); + margin-right: var(--space); vertical-align: baseline; } diff --git a/packages/ui/src/components/bundle-packages/bundle-packages.module.css b/packages/ui/src/components/bundle-packages/bundle-packages.module.css index f5d63a7cb4..a333e299e2 100644 --- a/packages/ui/src/components/bundle-packages/bundle-packages.module.css +++ b/packages/ui/src/components/bundle-packages/bundle-packages.module.css @@ -1,5 +1,5 @@ .title { - color: var(--color-text-light); + color: var(--color-text-muted); } .toolbarSearch { @@ -13,7 +13,7 @@ .packageName { display: inline-block; - color: var(--color-text-light); + color: var(--color-text-muted); } .packageName:last-child { @@ -22,13 +22,13 @@ .packageName + .packageName::before { display: inline-block; - margin: 0 var(--space-xxxsmall); + margin: 0 var(--space); content: '/'; - color: var(--color-text-ultra-light); + color: var(--color-text-ultra-muted); } .packageNameTagDuplicate { - margin-right: var(--space-xxxsmall); + margin-right: var(--space); vertical-align: middle; } diff --git a/packages/ui/src/components/delta/delta.module.css b/packages/ui/src/components/delta/delta.module.css index 2d9a12e75e..1624dafd61 100644 --- a/packages/ui/src/components/delta/delta.module.css +++ b/packages/ui/src/components/delta/delta.module.css @@ -1,5 +1,5 @@ .root { - color: var(--color-gray-ultra-light); + color: var(--color-text-ultra-muted); font-family: var(--font-family-fixed); white-space: nowrap; } @@ -9,60 +9,60 @@ } .HIGH_NEGATIVE { - color: var(--color-red-dark); + color: var(--color-danger-intense); } .NEGATIVE { - color: var(--color-red-dark); + color: var(--color-danger-intense); } .LOW_NEGATIVE { - color: var(--color-red-light); + color: var(--color-danger-muted); } .LOW_POSITIVE { - color: var(--color-green-light); + color: var(--color-success-muted); } .POSITIVE { - color: var(--color-green-dark); + color: var(--color-success-intense); } .HIGH_POSITIVE { - color: var(--color-green-dark); + color: var(--color-success-intense); } .inverted { padding: 0 2px; border-radius: var(--radius-xsmall); - background-color: var(--color-gray-ultra-light); - color: var(--color-light); + background-color: var(--color-text-ultra-muted); + color: var(--color-background); } .inverted.CHANGE { - background: var(--color-info-light); + background: var(--color-info-muted); } .inverted.HIGH_NEGATIVE { - background: var(--color-red-dark); + background: var(--color-danger-intense); } .inverted.NEGATIVE { - background: var(--color-red-dark); + background: var(--color-danger-intense); } .inverted.LOW_NEGATIVE { - background: var(--color-red-light); + background: var(--color-danger-muted); } .inverted.LOW_POSITIVE { - background: var(--color-green-light); + background: var(--color-success-muted); } .inverted.POSITIVE { - background: var(--color-green-dark); + background: var(--color-success-intense); } .inverted.HIGH_POSITIVE { - background: var(--color-green-dark); + background: var(--color-success-intense); } diff --git a/packages/ui/src/components/entry-info/entry-info.module.css b/packages/ui/src/components/entry-info/entry-info.module.css index a97bcc9650..38b91a28a3 100644 --- a/packages/ui/src/components/entry-info/entry-info.module.css +++ b/packages/ui/src/components/entry-info/entry-info.module.css @@ -6,7 +6,7 @@ width: 100vw; max-width: var(--entry-info-width); z-index: calc(var(--layer-high) - 1); - background: #fff; + background: var(--color-background); box-shadow: var(--shadow-layer-high); } @@ -28,21 +28,21 @@ /** header */ .header { /** space for close icon */ - padding-right: calc(var(--space-xlarge) + var(--space-xxxsmall) + var(--space-xsmall)); + padding-right: calc(var(--space-10x) + var(--space) + var(--space-3x)); border-bottom: 1px solid var(--color-outline); } .headerClose { position: absolute; - right: calc(var(--space-small) - var(--space-xxxsmall)); - top: calc(var(--space-small) - var(--space-xxxsmall)); - color: var(--color-text-ultra-light); + right: calc(var(--space-4x) - var(--space)); + top: calc(var(--space-4x) - var(--space)); + color: var(--color-text-ultra-muted); } .headerClose:hover, .headerClose:active, .headerClose:focus { - color: var(--color-text-light); + color: var(--color-text-muted); } /** comon components */ @@ -84,15 +84,15 @@ .meta {} .metaLabel { - margin-right: var(--space-xxxsmall); + margin-right: var(--space); min-width: 8em; flex: 0 1 6em; - color: var(--color-text-light); + color: var(--color-text-muted); } .metaLabelTooltip { - margin-left: var(--space-xxxsmall); - color: var(--color-text-ultra-light); + margin-left: var(--space); + color: var(--color-text-ultra-muted); } .metaContent { @@ -101,7 +101,7 @@ } .metaLink { - padding: 1px var(--space-xxxsmall); + padding: 1px var(--space); display: inline-block; line-height: var(--line-height-heading); border-radius: var(--radius-small); @@ -118,14 +118,14 @@ } .metaLink { - margin-right: var(--space-xxxsmall); + margin-right: var(--space); } .metaLink:hover, .metaLink:active, .metaLink:focus { background: var(--color-outline); - color: var(--color-primary-dark); + color: var(--color-primary-intense); } @media (min-width: 640px) { diff --git a/packages/ui/src/components/insight-icon/insight-icon.module.css b/packages/ui/src/components/insight-icon/insight-icon.module.css index 04e693d398..4c4d9695b6 100644 --- a/packages/ui/src/components/insight-icon/insight-icon.module.css +++ b/packages/ui/src/components/insight-icon/insight-icon.module.css @@ -1,20 +1,20 @@ .root { - width: calc(var(--space-small) + 6px); - height: calc(var(--space-small) + 6px); + width: calc(var(--space-4x) + 6px); + height: calc(var(--space-4x) + 6px); padding: 3px; border-radius: 50%; background: var(--color-highlight); } .error { - background: var(--color-red-50); + background: var(--color-highlight-danger); color: var(--color-danger); } .warning { padding-top: 1px; - background: var(--color-yellow-100); - color: var(--color-yellow-900); + background: var(--color-highlight-warning); + color: var(--color-warning); } .info { diff --git a/packages/ui/src/components/jobs-header/jobs-header.module.css b/packages/ui/src/components/jobs-header/jobs-header.module.css index 14f4b19d40..927f9dfdfd 100644 --- a/packages/ui/src/components/jobs-header/jobs-header.module.css +++ b/packages/ui/src/components/jobs-header/jobs-header.module.css @@ -1,5 +1,5 @@ .root { - padding: var(--space-small) 0; + padding: var(--space-4x) 0; width: 100%; display: flex; } @@ -9,7 +9,7 @@ flex: 1 0 10%; max-width: 50%; overflow: hidden; - padding: 0 var(--space-small); + padding: 0 var(--space-4x); border-left: 1px solid var(--color-outline); } @@ -20,7 +20,7 @@ top: 0; right: 0; bottom: 0; - width: var(--space-xxsmall); + width: var(--space-2x); background: linear-gradient(90deg, transparent, var(--color-background)); } @@ -37,21 +37,21 @@ } .itemTag { - margin-left: var(--space-xxsmall); + margin-left: var(--space-2x); vertical-align: top; outline: 1px solid var(--color-outline); background: var(--color-highlight); - color: var(--color-text-light); + color: var(--color-text-muted); } .itemMeta { - color: var(--color-text-light); + color: var(--color-text-muted); font-size: var(--size-small); } .itemMetaIcon { flex: 0 0 auto; - color: var(--color-text-ultra-light); + color: var(--color-text-ultra-muted); } .itemMetaText { diff --git a/packages/ui/src/components/metric-run-info/metric-run-info.module.css b/packages/ui/src/components/metric-run-info/metric-run-info.module.css index 702d8c400f..1f70ee00b2 100644 --- a/packages/ui/src/components/metric-run-info/metric-run-info.module.css +++ b/packages/ui/src/components/metric-run-info/metric-run-info.module.css @@ -12,6 +12,6 @@ .readMoreLink:hover, .readMoreLink:focus, .readMoreLink:active { - color: var(--color-primary-dark); + color: var(--color-primary-intense); text-decoration: none; } diff --git a/packages/ui/src/components/metric/metric.module.css b/packages/ui/src/components/metric/metric.module.css index 359c4a7b16..87f1253b04 100644 --- a/packages/ui/src/components/metric/metric.module.css +++ b/packages/ui/src/components/metric/metric.module.css @@ -17,5 +17,5 @@ .inline .content { display: inline-block; - margin: 0 0 0 var(--space-xxsmall); + margin: 0 0 0 var(--space-2x); } diff --git a/packages/ui/src/components/metrics-display-selector/metrics-display-selector.module.css b/packages/ui/src/components/metrics-display-selector/metrics-display-selector.module.css index ad8c0e71ab..cdb2b71bdd 100644 --- a/packages/ui/src/components/metrics-display-selector/metrics-display-selector.module.css +++ b/packages/ui/src/components/metrics-display-selector/metrics-display-selector.module.css @@ -4,7 +4,7 @@ } .dropdownGroupButton { - padding: calc(var(--space-xxsmall) - 1px); + padding: calc(var(--space-2x) - 1px); } .dropdownGroupAnchor { @@ -17,11 +17,11 @@ content: ''; display: block; width: 1px; - background: var(--color-outline-dark); + background: var(--color-outline); position: absolute; left: 0; - top: var(--space-xxxsmall); - bottom: var(--space-xxxsmall); + top: var(--space); + bottom: var(--space); } .dropdownGroupAnchor:hover, @@ -33,7 +33,7 @@ } .dropdownGroup:hover { - border-color: var(--color-outline-dark); + border-color: var(--color-outline-intense); transition: var(--transition-in); } diff --git a/packages/ui/src/components/metrics-table-header/metrics-table-header.module.css b/packages/ui/src/components/metrics-table-header/metrics-table-header.module.css index 21f46c0d8a..f57a736cd5 100644 --- a/packages/ui/src/components/metrics-table-header/metrics-table-header.module.css +++ b/packages/ui/src/components/metrics-table-header/metrics-table-header.module.css @@ -1,7 +1,7 @@ /* columns */ .root .col { - padding-top: var(--space-xxsmall); - padding-bottom: var(--space-xxsmall); + padding-top: var(--space-2x); + padding-bottom: var(--space-2x); } .root .metric { @@ -10,7 +10,7 @@ } .root .job { - padding-top: var(--space-xxsmall); + padding-top: var(--space-2x); text-align: right; } diff --git a/packages/ui/src/components/metrics-table-options/metrics-table-options.module.css b/packages/ui/src/components/metrics-table-options/metrics-table-options.module.css index 7b1d948e21..213bfe6220 100644 --- a/packages/ui/src/components/metrics-table-options/metrics-table-options.module.css +++ b/packages/ui/src/components/metrics-table-options/metrics-table-options.module.css @@ -3,9 +3,9 @@ } .group { - margin-bottom: calc(var(--space-xxxsmall) / 2); + margin-bottom: calc(var(--space) / 2); border-bottom: 1px solid var(--color-outline); - padding-bottom: calc(var(--space-xxxsmall) / 2); + padding-bottom: calc(var(--space) / 2); } .group:last-child { diff --git a/packages/ui/src/components/metrics-table-title/metrics-table-title.module.css b/packages/ui/src/components/metrics-table-title/metrics-table-title.module.css index c3c167e6a4..0d7d83b462 100644 --- a/packages/ui/src/components/metrics-table-title/metrics-table-title.module.css +++ b/packages/ui/src/components/metrics-table-title/metrics-table-title.module.css @@ -1,5 +1,5 @@ .root { - color: var(--color-text-ultra-light); + color: var(--color-text-ultra-muted); } .title { diff --git a/packages/ui/src/components/metrics-table/metrics-table.module.css b/packages/ui/src/components/metrics-table/metrics-table.module.css index 72322f784a..247f8d6366 100644 --- a/packages/ui/src/components/metrics-table/metrics-table.module.css +++ b/packages/ui/src/components/metrics-table/metrics-table.module.css @@ -18,20 +18,20 @@ /** rows */ .multipleRuns .unchanged th, .multipleRuns .unchanged td { - color: var(--color-text-light); + color: var(--color-text-muted); } .root .empty { background: none !important; - padding-top: calc(var(--space-xxxlarge) * 2); - padding-bottom: calc(var(--space-xxxlarge) * 2); + padding-top: calc(var(--space-16x) * 2); + padding-bottom: calc(var(--space-16x) * 2); text-align: center; } .emptyIcon { - color: var(--color-outline-dark); - width: var(--space-large); - height: var(--space-large); + color: var(--color-outline-intense); + width: var(--space-8x); + height: var(--space-8x); } .root .showAllItems { diff --git a/packages/ui/src/components/metrics-treemap/metrics-treemap.module.css b/packages/ui/src/components/metrics-treemap/metrics-treemap.module.css index 13caa24277..97c56d201c 100644 --- a/packages/ui/src/components/metrics-treemap/metrics-treemap.module.css +++ b/packages/ui/src/components/metrics-treemap/metrics-treemap.module.css @@ -30,13 +30,13 @@ .tileGroupTitleContent { width: 100%; - padding: var(--space-xxxsmall) 2px var(--space-xxxsmall) var(--space-xxsmall); + padding: var(--space) 2px var(--space) var(--space-2x); display: flex; align-items: center; color: var(--color-text); font-family: var(--font-family-fixed); font-size: 10px; - line-height: var(--space-small); + line-height: var(--space-4x); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; @@ -49,8 +49,8 @@ } .tileGroupTitleTotal { - margin-left: var(--space-xxsmall); - color: var(--color-text-light); + margin-left: var(--space-2x); + color: var(--color-text-muted); } .tileGroupTitle { @@ -80,41 +80,41 @@ /** Tile group nested variation */ .nested .tileGroup { - background-color: rgba(27, 26, 33, 0.03); - outline: 1px solid rgba(255, 255, 255, 0.8); + background-color: rgba(var(--color-background-rgba), 0.1); + outline: 1px solid rgba(var(--color-background-rgba), 0.8); } .nested .tileGroup:has(> .tileGroupTitle:hover), .nested .tileGroup:has(> .tile:hover) { - background-color: rgba(27, 26, 33, 0.06); - outline: 1px solid rgba(255, 255, 255, 1); + background-color: rgba(var(--color-background-rgba), 0.06); + outline: 1px solid rgba(var(--color-background-rgba), 1); transition: var(--transition-in); transition-property: background-color, outline; } .nested .tileGroup--NEGATIVE { - background-color: rgba(194, 31, 37, 0.04); + background-color: rgba(240, 0, 0, 0.04); } .nested .tileGroup--NEGATIVE:has(> .tileGroupTitle:hover), .nested .tileGroup--NEGATIVE:has(> .tile:hover) { - background-color: rgba(194, 31, 37, 0.1); + background-color: rgba(240, 0, 0, 0.1); } .nested .tileGroup--POSITIVE { - background-color: rgba(42, 147, 39, 0.04); + background-color: rgba(0, 240, 0, 0.04); } .nested .tileGroup--POSITIVE:has(> .tileGroupTitle:hover), .nested .tileGroup--POSITIVE:has(> .tile:hover) { - background-color: rgba(42, 147, 39, 0.1); + background-color: rgba(0, 240, 0, 0.1); } /* reset bacground color when having a not changed group */ .nested .tileGroup--POSITIVE > .tileGroup--NO_CHANGE, .nested .tileGroup--NEGATIVE > .tileGroup--NO_CHANGE { background-color: var(--color-background); - background-image: linear-gradient(rgba(27, 26, 33, 0.1), rgba(27, 26, 33, 0.1)); + background-image: linear-gradient(var(--color-background-rgba), 0.1); } .nested .tileGroup--POSITIVE > .tileGroup--NO_CHANGE:has(> .tileGroupTitle:hover), @@ -122,7 +122,7 @@ .nested .tileGroup--NEGATIVE > .tileGroup--NO_CHANGE:has(> .tileGroupTitle:hover), .nested .tileGroup--NEGATIVE > .tileGroup--NEGATIVE > .tileGroup--NO_CHANGE:has(> .tile:hover) { background-color: var(--color-background); - background-image: linear-gradient(rgba(27, 26, 33, 0.1), rgba(27, 26, 33, 0.1)); + background-image: linear-gradient(var(--color-background-rgba), 0.1); } /** Leaf wrapper button */ @@ -163,14 +163,14 @@ display: flex; flex-flow: column; justify-content: center; - padding: var(--space-xxsmall) var(--space-xxsmall); - gap: var(--space-xxxsmall); + padding: var(--space-2x) var(--space-2x); + gap: var(--space); line-height: var(--line-height-heading); } /** Align label to other elements on the first column cells */ .tileFirstCol .tileContent { - padding-left: var(--space-small); + padding-left: var(--space-4x); } .tileContentLabel { @@ -190,7 +190,7 @@ .tileContentValue { flex: 0 0 auto; - max-width: calc(100% + var(--space-xxsmall)); + max-width: calc(100% + var(--space-2x)); white-space: nowrap; overflow: hidden; } @@ -200,12 +200,12 @@ } .tileContentDelta { - margin-left: var(--space-xxxsmall); + margin-left: var(--space); } /** Tile size variation */ .tileSizeSmall .tileContent { - padding: var(--space-xxxsmall); + padding: var(--space); font-size: 10px; } @@ -215,7 +215,7 @@ /** Tile diff variation */ .tile { - outline: 1px solid rgba(255, 255, 255, 1); + outline: 1px solid rgba(var(--color-background-rgba), 1); color: var(--color-text); } @@ -237,11 +237,11 @@ } .tile-NO_CHANGE { - color: var(--color-text-light); + color: var(--color-text-muted); } .tile-NO_CHANGE::before { - color: var(--color-gray-50); + color: var(--gray-3); opacity: 0.4; } @@ -250,27 +250,27 @@ } .tile-HIGH_NEGATIVE::before { - color: var(--color-red-100); + color: var(--red-5); } .tile-NEGATIVE::before { - color: var(--color-red-50); + color: var(--red-4); } .tile-LOW_NEGATIVE::before { - color: var(--color-red-50); + color: var(--red-3); } .tile-LOW_POSITIVE::before { - color: var(--color-green-50); + color: var(--green-3); } .tile-POSITIVE::before { - color: var(--color-green-50); + color: var(--green-4); } .tile-HIGH_POSITIVE::before { - color: var(--color-green-100); + color: var(--green-5); } /** empty message */ @@ -298,14 +298,14 @@ .tooltip { z-index: var(--layer-xxhigh); - padding: var(--space-xsmall) var(--space-small); + padding: var(--space-3x) var(--space-4x); border-radius: var(--radius-medium); - width: calc(100vw - 2 * var(--space-small)); + width: calc(100vw - 2 * var(--space-4x)); max-width: 340px; outline: none; filter: drop-shadow(var(--shadow-layer-high)); will-change: filter; - background: var(--color-light); + background: var(--color-background); font-size: var(--size-small); pointer-events: none; } diff --git a/packages/ui/src/components/module-info/module-info.module.css b/packages/ui/src/components/module-info/module-info.module.css index 9e23e52bae..e0fc56e5ec 100644 --- a/packages/ui/src/components/module-info/module-info.module.css +++ b/packages/ui/src/components/module-info/module-info.module.css @@ -13,7 +13,7 @@ .chunksItem-info:hover, .chunksItem-info:active, .chunksItem-info:focus { - color: var(--color-info-dark); + color: var(--color-info-intense); } .chunksItem-danger { @@ -23,11 +23,11 @@ .chunksItem-danger:hover, .chunksItem-danger:active, .chunksItem-danger:focus { - color: var(--color-danger-dark); + color: var(--color-danger-intense); } .chunksItem-default { - color: var(--color-text-light); + color: var(--color-text-muted); } .chunksItem-default:hover, diff --git a/packages/ui/src/components/package-info/package-info.module.css b/packages/ui/src/components/package-info/package-info.module.css index 7cadb01564..6510863c27 100644 --- a/packages/ui/src/components/package-info/package-info.module.css +++ b/packages/ui/src/components/package-info/package-info.module.css @@ -9,5 +9,5 @@ } .packageTitleId { - color: var(--color-text-ultra-light); + color: var(--color-text-ultra-muted); } diff --git a/packages/ui/src/components/preview-source/preview-source.module.css b/packages/ui/src/components/preview-source/preview-source.module.css index c254577dee..971c9ec0f9 100644 --- a/packages/ui/src/components/preview-source/preview-source.module.css +++ b/packages/ui/src/components/preview-source/preview-source.module.css @@ -5,8 +5,8 @@ .toolbar { position: absolute; z-index: 2; - top: var(--space-xsmall); - right: var(--space-xsmall); + top: var(--space-3x); + right: var(--space-3x); background: var(--color-background); border-radius: var(--radius-medium); } diff --git a/packages/ui/src/components/run-info/run-info.module.css b/packages/ui/src/components/run-info/run-info.module.css index c0f73602aa..1b217af3f7 100644 --- a/packages/ui/src/components/run-info/run-info.module.css +++ b/packages/ui/src/components/run-info/run-info.module.css @@ -1,5 +1,5 @@ .title { - color: var(--color-text-ultra-light); + color: var(--color-text-ultra-muted); font-weight: bold; font-size: var(--size-xsmall); text-transform: uppercase; @@ -15,13 +15,13 @@ } .titleIcon { - flex: 0 0 var(--space-small); + flex: 0 0 var(--space-4x); margin-top: -3px !important; margin-bottom: -3px !important; } .title + .info { - margin-top: var(--space-xxsmall); + margin-top: var(--space-2x); } .currentMetric { @@ -37,14 +37,14 @@ } .deltaValue + .deltaValue::before { - margin-left: calc(var(--space-xxxsmall) / 2); - margin-right: calc(var(--space-xxxsmall) / 2); + margin-left: calc(var(--space) / 2); + margin-right: calc(var(--space) / 2); content: '/'; - color: var(--color-text-ultra-light); + color: var(--color-text-ultra-muted); } .baselineMetric { - color: var(--color-text-ultra-light); + color: var(--color-text-muted); font-size: var(--size-small); line-height: var(--line-height-number); height: var(--line-height-number); diff --git a/packages/ui/src/components/sort-button/sort-button.module.css b/packages/ui/src/components/sort-button/sort-button.module.css index 1702051235..dadb4054ec 100644 --- a/packages/ui/src/components/sort-button/sort-button.module.css +++ b/packages/ui/src/components/sort-button/sort-button.module.css @@ -3,11 +3,11 @@ display: inline-block; border-radius: var(--radius-small); position: relative; - color: var(--color-text-ultra-light); + color: var(--color-text-ultra-muted); } .toggle { - padding: 1px var(--space-xxxsmall); + padding: 1px var(--space); padding-right: calc(1px + var(--icon-dimension)); } @@ -17,7 +17,7 @@ display: block; overflow: hidden; right: -2px; /* compensate for the button padding */ - color: var(--color-text-ultra-light); + color: var(--color-text-ultra-muted); transition: var(--transition-out); } @@ -35,7 +35,7 @@ .direction:hover, .direction:active, .direction:focus { - color: var(--color-text-dark); + color: var(--color-text-intense); transition: var(--transition-in); } @@ -58,7 +58,7 @@ } .interactive { - margin: calc(0px - var(--space-xxxsmall)); + margin: calc(0px - var(--space)); margin-right: calc(0px - 1px - var(--icon-dimension)); } diff --git a/packages/ui/src/components/summary/summary.module.css b/packages/ui/src/components/summary/summary.module.css index 23a308c9e0..430bb391b3 100644 --- a/packages/ui/src/components/summary/summary.module.css +++ b/packages/ui/src/components/summary/summary.module.css @@ -1,5 +1,5 @@ .root { - --summary-gap: var(--space-small); + --summary-gap: var(--space-4x); width: 100%; } diff --git a/packages/ui/src/context/index.ts b/packages/ui/src/context/index.ts new file mode 100644 index 0000000000..7b1f54ecf9 --- /dev/null +++ b/packages/ui/src/context/index.ts @@ -0,0 +1 @@ +export * from './theme'; diff --git a/packages/ui/src/context/theme.tsx b/packages/ui/src/context/theme.tsx new file mode 100644 index 0000000000..f209d33d01 --- /dev/null +++ b/packages/ui/src/context/theme.tsx @@ -0,0 +1,52 @@ +import type { ReactNode } from 'react'; +import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; + +import { getCurrentTheme, switchTheme, useCookieTheme, type ThemeName } from '../utils/theme'; + +type ThemeContextProps = { + name: ThemeName; + update: (newTheme: ThemeName) => void; +}; + +const ThemeContext = createContext
({ + name: 'light', + update: () => {}, +}); + +export type ThemeProviderProps = { + children: ReactNode; +}; + +export const ThemeProvider = (props: ThemeProviderProps) => { + const { children } = props; + + const [cookieValue, setCookieValue] = useCookieTheme(); + const [theme, setTheme] = useState
((cookieValue as ThemeName) || getCurrentTheme()); + + const updateTheme = useCallback( + (nextTheme: ThemeName) => { + setCookieValue(nextTheme); + switchTheme(nextTheme); + }, + [setTheme, setCookieValue], + ); + + // Sync classNames on load + useEffect(() => { + switchTheme(theme); + }, [theme]); + + const value = useMemo( + () => ({ + name: theme, + update: updateTheme, + }), + [theme, updateTheme], + ); + + return
{children}
; +}; + +export const useTheme = (): ThemeContextProps => { + return useContext(ThemeContext); +}; diff --git a/packages/ui/src/css/default.css b/packages/ui/src/css/default.css index fd5cb6750d..92fbb8fc05 100644 --- a/packages/ui/src/css/default.css +++ b/packages/ui/src/css/default.css @@ -60,6 +60,6 @@ a { a:hover, a:active, a:focus { - color: var(--color-primary-dark); + color: var(--color-primary-intense); outline: none; } diff --git a/packages/ui/src/css/variables.css b/packages/ui/src/css/variables.css index 2d85d53bf5..c612ad1fad 100644 --- a/packages/ui/src/css/variables.css +++ b/packages/ui/src/css/variables.css @@ -1,17 +1,244 @@ +/* + * Color scheme: + * https://coolors.co/287acc-da444e-55b950-efcc1a-192339 + * https://hihayk.github.io/scale/#4/5/50/90/-51/0/0/14/353138/53/49/56/white + * https://www.radix-ui.com/colors/custom + */ +:root, .light-theme { + --branding-1: #fafdff; + --branding-2: #f2f9ff; + --branding-3: #e3f4ff; + --branding-4: #d3ecff; + --branding-5: #c2e2ff; + --branding-6: #aad5ff; + --branding-7: #8cc3ff; + --branding-8: #5fa9ff; + --branding-9: #1a477f; + --branding-10: #2b5892; + --branding-11: #1f6cc7; + --branding-12: #08376e; + + --gray-1: #fcfcfe; + --gray-2: #f9f9fc; + --gray-3: #f0eff5; + --gray-4: #e8e7ef; + --gray-5: #e0e0ea; + --gray-6: #d9d8e3; + --gray-7: #cecddb; + --gray-8: #bbb9cc; + --gray-9: #8d8c9d; + --gray-10: #838192; + --gray-11: #646371; + --gray-12: #201f29; + + --red-1: #fffcfc; + --red-2: #fff8f7; + --red-3: #feebea; + --red-4: #ffdcdb; + --red-5: #ffcecc; + --red-6: #fbbfbc; + --red-7: #f2aba9; + --red-8: #e8918f; + --red-9: #da444e; + --red-10: #cc3341; + --red-11: #c93340; + --red-12: #631a1f; + + --blue-1: #fcfdff; + --blue-2: #f5f9fe; + --blue-3: #ebf3fc; + --blue-4: #ddecfe; + --blue-5: #cde2fc; + --blue-6: #b9d5f5; + --blue-7: #a1c4ed; + --blue-8: #7dade4; + --blue-9: #287acc; + --blue-10: #166cbd; + --blue-11: #2275c7; + --blue-12: #123559; + + --green-1: #fbfefa; + --green-2: #f5fbf5; + --green-3: #e7f7e5; + --green-4: #d8f2d5; + --green-5: #c6eac2; + --green-6: #b0dfac; + --green-7: #93cf8e; + --green-8: #67bb62; + --green-9: #55b950; + --green-10: #4aad46; + --green-11: #2e7f2b; + --green-12: #223e20; + + --yellow-1: #fefdfb; + --yellow-2: #fffbe9; + --yellow-3: #fff5c0; + --yellow-4: #ffec9b; + --yellow-5: #ffe278; + --yellow-6: #f5d674; + --yellow-7: #e2c568; + --yellow-8: #d0ae3b; + --yellow-9: #ffd00c; + --yellow-10: #f2c724; + --yellow-11: #947300; + --yellow-12: #443b1f; + + --color-background-rgba: 255, 255, 255; + --color-background: rgba(var(--color-background-rgba), 1); + --color-backdrop: rgba(0, 0, 0, 0.05); + --color-shadow: rgba(0, 0, 0, 0.25); +} + +.dark-theme { + --branding-1: #0a111c; + --branding-2: #0f1925; + --branding-3: #0f2746; + --branding-4: #0b3160; + --branding-5: #133d72; + --branding-6: #1e4b83; + --branding-7: #295a99; + --branding-8: #306bb6; + --branding-9: #3984e1; + --branding-10: #2b77d3; + --branding-11: #7fb7ff; + --branding-12: #cee3ff; + + --gray-1: #111015; + --gray-2: #19191e; + --gray-3: #222229; + --gray-4: #2a2933; + --gray-5: #31303c; + --gray-6: #3a3947; + --gray-7: #474656; + --gray-8: #605f70; + --gray-9: #6e6c7e; + --gray-10: #7b7a8c; + --gray-11: #b3b2c5; + --gray-12: #eeeef2; + + --red-1: #160f0f; + --red-2: #1f1313; + --red-3: #3a1314; + --red-4: #4f1116; + --red-5: #60191e; + --red-6: #712629; + --red-7: #8a3638; + --red-8: #b3474b; + --red-9: #da444e; + --red-10: #b94c50; + --red-11: #ff8e8e; + --red-12: #ffd2d0; + + --blue-1: #08121d; + --blue-2: #0d1927; + --blue-3: #072848; + --blue-4: #003265; + --blue-5: #003e78; + --blue-6: #094d8a; + --blue-7: #175ea2; + --blue-8: #1c71c2; + --blue-9: #287acc; + --blue-10: #166cbd; + --blue-11: #6db9ff; + --blue-12: #c8e4ff; + + --green-1: #0d130c; + --green-2: #141a13; + --green-3: #1b2a1a; + --green-4: #1e3a1c; + --green-5: #264824; + --green-6: #2e582b; + --green-7: #366833; + --green-8: #3e7a3a; + --green-9: #55b950; + --green-10: #48ad44; + --green-11: #71d26b; + --green-12: #bef2ba; + + --yellow-1: #13110b; + --yellow-2: #1b1810; + --yellow-3: #2a230a; + --yellow-4: #382b00; + --yellow-5: #453500; + --yellow-6: #52430c; + --yellow-7: #65551e; + --yellow-8: #806c29; + --yellow-9: #ebc013; + --yellow-10: #e0b500; + --yellow-11: #fbd13d; + --yellow-12: #f9e9b8; + + --color-background-rgba: 17, 17, 17; + --color-background: rgba(var(--color-background-rgba), 1); + --color-backdrop: rgba(255, 255, 255, 0.05); + --color-shadow: rgba(0, 0, 0, 0.6); +} + :root { + /* Functional color variables */ + --color-text-ultra-muted: var(--gray-8); + --color-text-muted: var(--gray-9); + --color-text: var(--gray-10); + --color-text-intense: var(--gray-11); + --color-heading: var(--gray-12); + + --color-branding-muted: var(--branding-8); + --color-branding: var(--branding-10); + --color-branding-intense: var(--branding-12); + + --color-success-muted: var(--green-8); + --color-success: var(--green-9); + --color-success-intense: var(--green-10); + + --color-info-muted: var(--blue-8); + --color-info: var(--blue-10); + --color-info-intense: var(--blue-12); + + --color-warning-muted: var(--yellow-9); + --color-warning: var(--yellow-10); + --color-warning-intense: var(--yellow-11); + + --color-danger-muted: var(--red-8); + --color-danger: var(--red-9); + --color-danger-intense: var(--red-11); + + --color-primary-muted: var(--color-info-muted); + --color-primary: var(--color-info); + --color-primary-intense: var(--color-info-intense); + + --color-secondary-muted: var(--color-success-muted); + --color-secondary: var(--color-success); + --color-secondary-intense: var(--color-success-intense); + + --color-highlight: var(--gray-2); + --color-highlight-primary: var(--blue-2); + --color-highlight-secondary: var(--green-2); + --color-highlight-success: var(--green-2); + --color-highlight-info: var(--blue-3); + --color-highlight-warning: var(--yellow-2); + --color-highlight-danger: var(--red-3); + + --color-outline: var(--gray-4); + --color-outline-intense: var(--gray-5); + --color-outline-success: var(--green-4); + --color-outline-info: var(--blue-4); + --color-outline-warning: var(--yellow-5); + --color-outline-danger: var(--red-4); + + /** Font family */ --font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif; --font-family-fixed: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* Spaces */ - --space-xxxsmall: 4px; - --space-xxsmall: 8px; - --space-xsmall: 12px; - --space-small: 16px; - --space-medium: 24px; - --space-large: 32px; - --space-xlarge: 40px; - --space-xxlarge: 48px; - --space-xxxlarge: 64px; + --space: 4px; + --space-2x: 8px; + --space-3x: 12px; + --space-4x: 16px; + --space-6x: 24px; + --space-8x: 32px; + --space-10x: 40px; + --space-12x: 48px; + --space-16x: 64px; /* Typography scale */ --size-xsmall: 0.77rem; @@ -28,158 +255,6 @@ --line-height-heading: 1.33; --line-height-number: 1.2em; - /* - * Color scheme: - * https://coolors.co/287acc-da444e-55b950-efcc1a-192339 - * http://mcg.mbitson.com/#!?mcgpalette0=%23da444e&mcgpalette1=%2355b950&mcgpalette2=%23ebc013&mcgpalette3=%232a2933&mcgpalette4=%23287acc&themename=bundle-stats - * https://hihayk.github.io/scale/#4/5/50/90/-51/0/0/14/353138/53/49/56/white - */ - --color-gray-25: #f9f9f9; - --color-gray-50: #e5e5e7; - --color-gray-100: #d2d2d4; - --color-gray-200: #959499; - --color-gray-300: #6a6970; - --color-gray-400: #4a4952; - --color-gray-500: #2a2933; - --color-gray-600: #25242e; - --color-gray-700: #1f1f27; - --color-gray-800: #191920; - --color-gray-900: #0f0f14; - - --color-gray-ultra-light: var(--color-gray-200); - --color-gray-light: var(--color-gray-300); - --color-gray: var(--color-gray-500); - --color-gray-dark: var(--color-gray-700); - --color-gray-ultra-dark: var(--color-gray-900); - - --color-red-25: #fdf5f6; - --color-red-50: #fbe9ea; - --color-red-100: #f4c7ca; - --color-red-200: #eda2a7; - --color-red-300: #e57c83; - --color-red-400: #e06069; - --color-red-500: #da444e; - --color-red-600: #d63e47; - --color-red-700: #d0353d; - --color-red-800: #cb2d35; - --color-red-900: #c21f25; - --color-red-ultra-light: var(--color-red-100); - --color-red-light: var(--color-red-300); - --color-red: var(--color-red-500); - --color-red-dark: var(--color-red-700); - --color-red-ultra-dark: var(--color-red-900); - - --color-blue-25: #f3f8fd; - --color-blue-50: #e5eff9; - --color-blue-100: #bfd7f0; - --color-blue-200: #94bde6; - --color-blue-300: #69a2db; - --color-blue-400: #488ed4; - --color-blue-500: #287acc; - --color-blue-600: #2472c7; - --color-blue-700: #1e67c0; - --color-blue-800: #185db9; - --color-blue-900: #0f4aad; - - --color-blue-ultra-light: var(--color-blue-100); - --color-blue-light: var(--color-blue-300); - --color-blue: var(--color-blue-500); - --color-blue-dark: var(--color-blue-700); - --color-blue-ultra-dark: var(--color-blue-900); - - --color-green-25: #f6fbf6; - --color-green-50: #ebf7ea; - --color-green-100: #cceacb; - --color-green-200: #aadca8; - --color-green-300: #88ce85; - --color-green-400: #6fc46a; - --color-green-500: #55b950; - --color-green-600: #4eb249; - --color-green-700: #44aa40; - --color-green-800: #3ba237; - --color-green-900: #2a9327; - - --color-green-ultra-light: var(--color-green-100); - --color-green-light: var(--color-green-300); - --color-green: var(--color-green-500); - --color-green-dark: var(--color-green-700); - --color-green-ultra-dark: var(--color-green-900); - - --color-yellow-25: #fffdf2; - --color-yellow-50: #fdf7e3; - --color-yellow-100: #f9ecb8; - --color-yellow-200: #f5e089; - --color-yellow-300: #f1d35a; - --color-yellow-400: #eec936; - --color-yellow-500: #ebc013; - --color-yellow-600: #e9ba11; - --color-yellow-700: #e5b20e; - --color-yellow-800: #e2aa0b; - --color-yellow-900: #dd9c06; - - --color-yellow-light-background: var(--color-yellow-25); - --color-yellow-ultra-light: var(--color-yellow-100); - --color-yellow-light: var(--color-yellow-300); - --color-yellow: var(--color-yellow-500); - --color-yellow-ultra-dark: var(--color-yellow-700); - --color-yellow-dark: var(--color-yellow-900); - - --color-dark: #111; - --color-light: #fff; - - /* Functional color variables */ - --color-branding-light: #2B76D4; - --color-branding: #1a477f; - --color-branding-dark: #09182A; - - --color-text-ultra-light: var(--color-gray-ultra-light); - --color-text-light: var(--color-gray-light); - --color-text: var(--color-gray); - --color-text-dark: var(--color-gray-dark); - --color-text-ultra-dark: var(--color-gray-ultra-dark); - --color-heading: var(--color-gray-ultra-dark); - - --color-success-light: var(--color-green-light); - --color-success: var(--color-green); - --color-success-dark: var(--color-green-dark); - --color-info-light: var(--color-blue-light); - --color-info: var(--color-blue); - --color-info-dark: var(--color-blue-dark); - --color-warning-light: var(--color-yellow-light); - --color-warning: var(--color-yellow); - --color-warning-dark: var(--color-yellow-dark); - --color-danger-light: var(--color-red-light); - --color-danger: var(--color-red); - --color-danger-dark: var(--color-red-dark); - - --color-primary-light: var(--color-blue-light); - --color-primary: var(--color-blue); - --color-primary-dark: var(--color-blue-dark); - - --color-secondary-light: var(--color-green-light); - --color-secondary: var(--color-green); - --color-secondary-dark: var(--color-green-dark); - - --color-background: #fff; - --color-highlight: var(--color-gray-25); - --color-highlight-primary: var(--color-blue-25); - --color-highlight-secondary: var(--color-green-25); - --color-highlight-success: var(--color-green-25); - --color-highlight-info: var(--color-blue-25); - --color-highlight-warning: var(--color-yellow-25); - --color-highlight-danger: var(--color-red-25); - - --color-outline: var(--color-gray-50); - --color-outline-dark: var(--color-gray-100); - - --color-outline-success: var(--color-green-100); - --color-outline-info: var(--color-blue-100); - --color-outline-warning: var(--color-yellow-200); - --color-outline-danger: var(--color-red-100); - - --color-backdrop: rgba(0, 0, 0, 0.05); - --color-shadow: rgba(0, 0, 0, 0.25); - --transition-duration-in: 0.2s; --transition-duration-out: 0.17s; --transition-in: all var(--transition-duration-in) ease-in; @@ -192,8 +267,8 @@ --layer-xhigh: 10000; --layer-xxhigh: 100000; - --shadow-layer: 0 0 var(--space-xxxsmall) var(--color-shadow); - --shadow-layer-high: 0 0 var(--space-xxsmall) var(--color-shadow); + --shadow-layer: 0 0 var(--space) var(--color-shadow); + --shadow-layer-high: 0 0 var(--space-2x) var(--color-shadow); --radius-xsmall: 3px; --radius-small: 5px; @@ -209,3 +284,8 @@ --entry-info-width: 64rem; --entry-info-top: var(--header-height); } + +.no-motion * { + transition: none !important; + animation: none !important; +} diff --git a/packages/ui/src/index.js b/packages/ui/src/index.js index eb3b4cb0ef..42305df59b 100644 --- a/packages/ui/src/index.js +++ b/packages/ui/src/index.js @@ -1,5 +1,6 @@ export * from './ui'; export * from './layout'; +export * from './context'; export * from './components'; export * from './utils'; export * from './app'; diff --git a/packages/ui/src/layout/box/box.module.css b/packages/ui/src/layout/box/box.module.css index 45a70f4fa5..3df0b2e42e 100644 --- a/packages/ui/src/layout/box/box.module.css +++ b/packages/ui/src/layout/box/box.module.css @@ -24,138 +24,138 @@ .outlineHover:focus, .outlineHover:active, .outlineHover:hover { - border-color: var(--color-outline-dark); + border-color: var(--color-outline-intense); transition: var(--transition-in); } .padding-xxxsmall { - padding: var(--space-xxxsmall); + padding: var(--space); } .padding-xxsmall { - padding: var(--space-xxsmall); + padding: var(--space-2x); } .padding-xsmall { - padding: var(--space-xsmall); + padding: var(--space-3x); } .padding-small { - padding: var(--space-small); + padding: var(--space-4x); } .padding-medium { - padding: var(--space-medium); + padding: var(--space-6x); } .padding-large { - padding: var(--space-large); + padding: var(--space-8x); } .padding-xlarge { - padding: var(--space-xlarge); + padding: var(--space-10x); } .padding-xxlarge { - padding: var(--space-xxlarge); + padding: var(--space-12x); } .padding-xxxlarge { - padding: var(--space-xxxlarge); + padding: var(--space-16x); } /** * Horizontal padding modifier */ .horizontal-padding-xxxsmall { - padding-left: var(--space-xxxsmall); - padding-right: var(--space-xxxsmall); + padding-left: var(--space); + padding-right: var(--space); } .horizontal-padding-xxsmall { - padding-left: var(--space-xxsmall); - padding-right: var(--space-xxsmall); + padding-left: var(--space-2x); + padding-right: var(--space-2x); } .horizontal-padding-xsmall { - padding-left: var(--space-xsmall); - padding-right: var(--space-xsmall); + padding-left: var(--space-3x); + padding-right: var(--space-3x); } .horizontal-padding-small { - padding-left: var(--space-small); - padding-right: var(--space-small); + padding-left: var(--space-4x); + padding-right: var(--space-4x); } .horizontal-padding-medium { - padding-left: var(--space-medium); - padding-right: var(--space-medium); + padding-left: var(--space-6x); + padding-right: var(--space-6x); } .horizontal-padding-large { - padding-left: var(--space-large); - padding-right: var(--space-large); + padding-left: var(--space-8x); + padding-right: var(--space-8x); } .horizontal-padding-xlarge { - padding-left: var(--space-xlarge); - padding-right: var(--space-xlarge); + padding-left: var(--space-10x); + padding-right: var(--space-10x); } .horizontal-padding-xxlarge { - padding-left: var(--space-xxlarge); - padding-right: var(--space-xxlarge); + padding-left: var(--space-12x); + padding-right: var(--space-12x); } .horizontal-padding-xxxlarge { - padding-left: var(--space-xxxlarge); - padding-right: var(--space-xxxlarge); + padding-left: var(--space-16x); + padding-right: var(--space-16x); } /** * Vertical padding modifier */ .vertical-padding-xxxsmall { - padding-top: var(--space-xxxsmall); - padding-bottom: var(--space-xxxsmall); + padding-top: var(--space); + padding-bottom: var(--space); } .vertical-padding-xxsmall { - padding-top: var(--space-xxsmall); - padding-bottom: var(--space-xxsmall); + padding-top: var(--space-2x); + padding-bottom: var(--space-2x); } .vertical-padding-xsmall { - padding-top: var(--space-xsmall); - padding-bottom: var(--space-xsmall); + padding-top: var(--space-3x); + padding-bottom: var(--space-3x); } .vertical-padding-small { - padding-top: var(--space-small); - padding-bottom: var(--space-small); + padding-top: var(--space-4x); + padding-bottom: var(--space-4x); } .vertical-padding-medium { - padding-top: var(--space-medium); - padding-bottom: var(--space-medium); + padding-top: var(--space-6x); + padding-bottom: var(--space-6x); } .vertical-padding-large { - padding-top: var(--space-large); - padding-bottom: var(--space-large); + padding-top: var(--space-8x); + padding-bottom: var(--space-8x); } .vertical-padding-xlarge { - padding-top: var(--space-xlarge); - padding-bottom: var(--space-xlarge); + padding-top: var(--space-10x); + padding-bottom: var(--space-10x); } .vertical-padding-xxlarge { - padding-top: var(--space-xxlarge); - padding-bottom: var(--space-xxlarge); + padding-top: var(--space-12x); + padding-bottom: var(--space-12x); } .vertical-padding-xxxlarge { - padding-top: var(--space-xxxlarge); - padding-bottom: var(--space-xxxlarge); + padding-top: var(--space-16x); + padding-bottom: var(--space-16x); } diff --git a/packages/ui/src/layout/flex-stack/flex-stack.module.css b/packages/ui/src/layout/flex-stack/flex-stack.module.css index e92ff3ac73..a0328d6da0 100644 --- a/packages/ui/src/layout/flex-stack/flex-stack.module.css +++ b/packages/ui/src/layout/flex-stack/flex-stack.module.css @@ -6,39 +6,39 @@ /** Space variation */ .space--xxxsmall { - gap: var(--space-xxxsmall); + gap: var(--space); } .space--xxsmall { - gap: var(--space-xxsmall); + gap: var(--space-2x); } .space--xsmall { - gap: var(--space-xsmall); + gap: var(--space-3x); } .space--small { - gap: var(--space-small); + gap: var(--space-4x); } .space--medium { - gap: var(--space-medium); + gap: var(--space-6x); } .space--large { - gap: var(--space-large); + gap: var(--space-8x); } .space--xlarge { - gap: var(--space-xlarge); + gap: var(--space-10x); } .space--xxlarge { - gap: var(--space-xxlarge); + gap: var(--space-12x); } .space--xxxlarge { - gap: var(--space-xxxlarge); + gap: var(--space-16x); } /** Align items variation */ diff --git a/packages/ui/src/layout/footer/footer.module.css b/packages/ui/src/layout/footer/footer.module.css index fd4d868a78..ce6999b719 100644 --- a/packages/ui/src/layout/footer/footer.module.css +++ b/packages/ui/src/layout/footer/footer.module.css @@ -8,12 +8,12 @@ .navItem { display: inline-block; - margin: 0 var(--space-xxxsmall); + margin: 0 var(--space); } .navItem + .navItem::before { content: '•'; - margin-right: var(--space-xxsmall); - color: var(--color-text-ultra-light); + margin-right: var(--space-2x); + color: var(--color-text-ultra-muted); font-size: var(--size-large); } diff --git a/packages/ui/src/layout/stack/stack.module.css b/packages/ui/src/layout/stack/stack.module.css index 4aa09cdc9c..4c6cbccf24 100644 --- a/packages/ui/src/layout/stack/stack.module.css +++ b/packages/ui/src/layout/stack/stack.module.css @@ -8,37 +8,37 @@ } .space--xxxsmall > .item { - margin-bottom: var(--space-xxxsmall); + margin-bottom: var(--space); } .space--xxsmall > .item { - margin-bottom: var(--space-xxsmall); + margin-bottom: var(--space-2x); } .space--xsmall > .item { - margin-bottom: var(--space-xsmall); + margin-bottom: var(--space-3x); } .space--small > .item { - margin-bottom: var(--space-small); + margin-bottom: var(--space-4x); } .space--medium > .item { - margin-bottom: var(--space-medium); + margin-bottom: var(--space-6x); } .space--large > .item { - margin-bottom: var(--space-large); + margin-bottom: var(--space-8x); } .space--xlarge > .item { - margin-bottom: var(--space-xlarge); + margin-bottom: var(--space-10x); } .space--xxlarge > .item { - margin-bottom: var(--space-xxlarge); + margin-bottom: var(--space-12x); } .space--xxxlarge > .item { - margin-bottom: var(--space-xxxlarge); + margin-bottom: var(--space-16x); } diff --git a/packages/ui/src/prototypes/typography.module.css b/packages/ui/src/prototypes/typography.module.css index e06d43fc13..0ea7821353 100644 --- a/packages/ui/src/prototypes/typography.module.css +++ b/packages/ui/src/prototypes/typography.module.css @@ -8,12 +8,12 @@ align-items: center; font-size: var(--size-xlarge); font-weight: 700; - color: var(--color-light); + color: var(--color-background); } .headerLogo { - margin-right: var(--space-xsmall); - width: var(--space-large); + margin-right: var(--space-3x); + width: var(--space-8x); } .subheader { diff --git a/packages/ui/src/prototypes/typography.stories.jsx b/packages/ui/src/prototypes/typography.stories.jsx index fbdfb93b9d..5d3dec1679 100644 --- a/packages/ui/src/prototypes/typography.stories.jsx +++ b/packages/ui/src/prototypes/typography.stories.jsx @@ -12,22 +12,20 @@ export default { }; export const Typography = () => ( -
-
-
+
+
+
); // eslint-disable-next-line react/prop-types const Item = ({ colorName, valueName = 'normal' }) => { - const colorFullName = valueName === 'normal' - ? colorName - : [colorName, valueName].join('-'); + const colorFullName = valueName === 'normal' ? colorName : [colorName, valueName].join('-'); return (
(
); -const COLORS = [ - 'blue', - 'red', - 'green', - 'yellow', - 'gray', -]; +const COLORS = ['branding', 'primary', 'secondary', 'success', 'info', 'warning', 'danger']; -const NAMES = [ - 'ultra-light', - 'light', - 'normal', - 'dark', - 'ultra-dark', -]; +const NAMES = ['muted', 'normal', 'intense']; export const ColorScheme = () => (
-
-
-
- -
- -
+
+
+
+
+
{COLORS.map((colorName) => (
{NAMES.map((valueName) => ( -
+
))}
))} @@ -96,10 +76,7 @@ export const ColorScheme = () => (
Chart colors
{CHART_COLORS.map((color) => ( -
+
))}
diff --git a/packages/ui/src/ui/button/button.module.css b/packages/ui/src/ui/button/button.module.css index 1d27662ab7..8d8c608212 100644 --- a/packages/ui/src/ui/button/button.module.css +++ b/packages/ui/src/ui/button/button.module.css @@ -7,13 +7,13 @@ display: inline-flex; align-items: center; justify-content: center; - gap: calc(max(var(--button-space), var(--space-xxsmall)) * 0.66); + gap: calc(max(var(--button-space), var(--space-2x)) * 0.66); appearance: none; padding: 0; border: var(--border-width) solid transparent; background: none; transition: var(--transition-out); - color: var(--color-text-ultra-light); + color: var(--color-text-muted); font-family: var(--font-family); white-space: nowrap; } @@ -26,7 +26,7 @@ a.root { .root:active, .root:focus { outline: none; - color: var(--color-text-light); + color: var(--color-text); transition: var(--transition-in); } @@ -49,7 +49,7 @@ a.root { .primary:hover, .primary:active, .primary:focus { - color: var(--color-primary-dark); + color: var(--color-primary-intense); } .secondary { @@ -59,7 +59,7 @@ a.root { .secondary:hover, .secondary:active, .secondary:focus { - color: var(--color-secondary-dark); + color: var(--color-secondary-intense); } .danger { @@ -69,7 +69,7 @@ a.root { .danger:hover, .danger:active, .danger:focus { - color: var(--color-danger-dark); + color: var(--color-danger-intense); } .warning { @@ -79,7 +79,7 @@ a.root { .warning:hover, .warning:active, .warning:focus { - color: var(--color-warning-dark); + color: var(--color-warning-intense); } .info { @@ -89,7 +89,7 @@ a.root { .info:hover, .info:active, .info:focus { - color: var(--color-info-dark); + color: var(--color-info-intense); } .success { @@ -99,21 +99,21 @@ a.root { .success:hover, .success:active, .success:focus { - color: var(--color-success-dark); + color: var(--color-success-intense); } /** * Solid Kind variation */ .solid { - background: var(--color-text-ultra-light); + background: var(--color-text-ultra-muted); color: var(--color-background); } .solid:hover, .solid:active, .solid:focus { - background: var(--color-text-light); + background: var(--color-text-muted); color: var(--color-background); } @@ -124,7 +124,7 @@ a.root { .solid--primary:hover, .solid--primary:active, .solid--primary:focus { - background: var(--color-primary-dark); + background: var(--color-primary-intense); } .solid--secondary { @@ -134,7 +134,7 @@ a.root { .solid--secondary:hover, .solid--secondary:active, .solid--secondary:focus { - background: var(--color-secondary-dark); + background: var(--color-secondary-intense); } .solid--danger { @@ -144,7 +144,7 @@ a.root { .solid--danger:hover, .solid--danger:active, .solid--danger:focus { - background: var(--color-danger-dark); + background: var(--color-danger-intense); } .solid--warning { @@ -154,7 +154,7 @@ a.root { .solid--warning:hover, .solid--warning:active, .solid--warning:focus { - background: var(--color-warning-dark); + background: var(--color-warning-intense); } .solid--info { @@ -164,7 +164,7 @@ a.root { .solid--info:hover, .solid--info:active, .solid--info:focus { - background: var(--color-info-dark); + background: var(--color-info-intense); } .solid--success { @@ -174,46 +174,46 @@ a.root { .solid--success:hover, .solid--success:active, .solid--success:focus { - background: var(--color-success-dark); + background: var(--color-success-intense); } /** * Size variation */ .small { - --button-space: var(--space-xxsmall); + --button-space: var(--space-2x); font-size: var(--size-small); - line-height: var(--space-small); + line-height: var(--space-4x); } .small .glyph { - width: var(--space-small); - height: var(--space-small); + width: var(--space-4x); + height: var(--space-4x); } .medium { - --button-space: var(--space-xsmall); + --button-space: var(--space-3x); font-size: var(--size-medium); - line-height: calc(var(--space-small) + var(--space-xxxsmall)); + line-height: calc(var(--space-4x) + var(--space)); } .medium .glyph { - width: calc(var(--space-small) + var(--space-xxxsmall)); - height: calc(var(--space-small) + var(--space-xxxsmall)); + width: calc(var(--space-4x) + var(--space)); + height: calc(var(--space-4x) + var(--space)); } .large { - --button-space: var(--space-small); + --button-space: var(--space-4x); font-size: var(--size-large); - line-height: var(--space-medium); + line-height: var(--space-6x); } .large .glyph { - width: var(--space-medium); - height: var(--space-medium); + width: var(--space-6x); + height: var(--space-6x); } /** @@ -227,7 +227,7 @@ a.root { .outline:hover, .outline:active, .outline:focus { - border-color: var(--color-outline-dark); + border-color: var(--color-outline-intense); } .outline--primary { @@ -237,7 +237,7 @@ a.root { .outline--primary:hover, .outline--primary:active, .outline--primary:focus { - border-color: var(--color-outline-primary-dark); + border-color: var(--color-outline-primary-intense); } .outline--secondary { @@ -247,7 +247,7 @@ a.root { .outline--secondary:hover, .outline--secondary:active, .outline--secondary:focus { - border-color: var(--color-outline-secondary-dark); + border-color: var(--color-outline-secondary-intense); } .outline--danger { @@ -257,7 +257,7 @@ a.root { .outline--danger:hover, .outline--danger:active, .outline--danger:focus { - border-color: var(--color-outline-danger-dark); + border-color: var(--color-outline-danger-intense); } .outline--warning { @@ -267,7 +267,7 @@ a.root { .outline--warning:hover, .outline--warning:active, .outline--warning:focus { - border-color: var(--color-outline-warning-dark); + border-color: var(--color-outline-warning-intense); } .outline--info { @@ -277,7 +277,7 @@ a.root { .outline--info:hover, .outline--info:active, .outline--info:focus { - border-color: var(--color-outline-info-dark); + border-color: var(--color-outline-info-intense); } .outline--success { @@ -287,7 +287,7 @@ a.root { .outline--success:hover, .outline--success:active, .outline--success:focus { - border-color: var(--color-outline-success-dark); + border-color: var(--color-outline-success-intense); } diff --git a/packages/ui/src/ui/container/container.module.css b/packages/ui/src/ui/container/container.module.css index 1ddfbbb864..d341c3e24e 100644 --- a/packages/ui/src/ui/container/container.module.css +++ b/packages/ui/src/ui/container/container.module.css @@ -1,5 +1,5 @@ .inner { - width: calc(100% - var(--space-small) * 2); + width: calc(100% - var(--space-4x) * 2); max-width: var(--max-width); margin: 0 auto; } diff --git a/packages/ui/src/ui/copy-to-clipboard/copy-to-clipboard.module.css b/packages/ui/src/ui/copy-to-clipboard/copy-to-clipboard.module.css index 549b7c205d..9861eeeaff 100644 --- a/packages/ui/src/ui/copy-to-clipboard/copy-to-clipboard.module.css +++ b/packages/ui/src/ui/copy-to-clipboard/copy-to-clipboard.module.css @@ -1,7 +1,7 @@ .root { white-space: nowrap; /** override tooltip styles */ - color: var(--color-text-ultra-light) !important; + color: var(--color-text-ultra-muted) !important; } /** done state */ diff --git a/packages/ui/src/ui/dialog/dialog.module.css b/packages/ui/src/ui/dialog/dialog.module.css index ffc228e56d..bba3df6d73 100644 --- a/packages/ui/src/ui/dialog/dialog.module.css +++ b/packages/ui/src/ui/dialog/dialog.module.css @@ -17,16 +17,16 @@ } .dialog { - --dialog-header-height: var(--space-medium); - --dialog-vspace: var(--space-xsmall); - --dialog-padding: var(--space-xsmall); + --dialog-header-height: var(--space-6x); + --dialog-vspace: var(--space-3x); + --dialog-padding: var(--space-3x); width: calc(100vw - 2 * var(--dialog-padding)); position: relative; border-radius: var(--radius-medium); padding: var(--dialog-padding); background: var(--color-background); - box-shadow: 0 0 var(--space-medium) var(--color-shadow); + box-shadow: 0 0 var(--space-6x) var(--color-shadow); } .header { @@ -43,22 +43,22 @@ .headerClose { position: absolute; - right: var(--space-xxsmall); - top: var(--space-xxsmall); - padding: var(--space-xxxsmall); + right: var(--space-2x); + top: var(--space-2x); + padding: var(--space); flex: 0 0 auto; - color: var(--color-outline-dark); + color: var(--color-outline-intense); } .headerClose:hover, .headerClose:focus, .headerClose:active { - color: var(--color-text-ultra-light); + color: var(--color-text-ultra-muted); } .content { width: 100%; - max-height: calc(100vh - 2 * var(--space-medium) - 2 * var(--dialog-padding) - var(--dialog-header-height) - var(--dialog-vspace)); + max-height: calc(100vh - 2 * var(--space-6x) - 2 * var(--dialog-padding) - var(--dialog-header-height) - var(--dialog-vspace)); padding-bottom: 0.3em; /* extra space to compensate for the title line-height and allow to show focus state correctly on buttons */ overflow: auto; } @@ -77,7 +77,7 @@ } .width--extra-wide { - max-width: calc(var(--max-width) + 2 * var(--space-medium)); + max-width: calc(var(--max-width) + 2 * var(--space-6x)); } /** Center variation */ @@ -87,7 +87,7 @@ @media (min-width: 768px) { .dialog { - --dialog-vspace: var(--space-medium); - --dialog-padding: var(--space-large); + --dialog-vspace: var(--space-6x); + --dialog-padding: var(--space-8x); } } diff --git a/packages/ui/src/ui/dropdown/dropdown.module.css b/packages/ui/src/ui/dropdown/dropdown.module.css index 43ce8e2379..ee044c7d08 100644 --- a/packages/ui/src/ui/dropdown/dropdown.module.css +++ b/packages/ui/src/ui/dropdown/dropdown.module.css @@ -3,7 +3,7 @@ } .button[disabled] { - color: var(--color-text-ultra-light); + color: var(--color-text-ultra-muted); } .dropdown { @@ -15,7 +15,7 @@ background: var(--color-background); min-width: 12em; z-index: var(--layer-high); - padding: calc(var(--space-xxxsmall) / 2); + padding: calc(var(--space) / 2); } .dropdown:focus { @@ -29,10 +29,10 @@ outline: none; border: 0; border-radius: var(--radius-small); - padding: calc(var(--space-xxxsmall) + var(--space-xxxsmall) / 2); + padding: calc(var(--space) + var(--space) / 2); background: none; text-align: left; - color: var(--color-text-light); + color: var(--color-text-muted); font-size: var(--size-small); line-height: var(--line-height); text-decoration: none; @@ -56,5 +56,5 @@ .itemActive:focus, .itemActive:active { background: var(--color-highlight-info); - color: var(--color-primary-dark); + color: var(--color-primary-intense); } diff --git a/packages/ui/src/ui/empty-set/empty-set.module.css b/packages/ui/src/ui/empty-set/empty-set.module.css index 95a169861d..c2b63d373b 100644 --- a/packages/ui/src/ui/empty-set/empty-set.module.css +++ b/packages/ui/src/ui/empty-set/empty-set.module.css @@ -1,3 +1,3 @@ .root { - color: var(--color-text-light); + color: var(--color-text-muted); } diff --git a/packages/ui/src/ui/filters/filters.module.css b/packages/ui/src/ui/filters/filters.module.css index 22b3c0d1a4..a75f79f02d 100644 --- a/packages/ui/src/ui/filters/filters.module.css +++ b/packages/ui/src/ui/filters/filters.module.css @@ -9,13 +9,14 @@ position: relative; width: 100%; max-width: 240px; - color: var(--color-text); + color: var(--color-text-muted); } .filterControl { margin: 0; flex: 0 0 auto; height: 1em; + background: var(--color-background); } .filterLabel { @@ -27,34 +28,35 @@ } .filterControl[disabled] + .filterLabel { - color: var(--color-text-light); + color: var(--color-text-ultra-muted); } .filter:hover { - color: var(--color-dark); + color: var(--color-text); } /** Filter single */ .filterSingle { - padding: calc(var(--space-xxsmall) - 1px); + padding: calc(var(--space-2x) - 1px); border: 1px solid var(--color-outline); border-radius: var(--radius-small); font-size: var(--size-small); - line-height: var(--space-small); - color: var(--color-text-ultra-light); + line-height: var(--space-4x); + color: var(--color-text-muted); transition: var(--transition-out); } .filterSingle:hover, .filterSingle:active, .filterSingle:focus { - border-color: var(--color-outline-dark); + border-color: var(--color-outline-intense); + color: var(--color-text); transition: var(--transition-in); } /** Filter group */ .filterGroupItems { - max-height: calc(10 * (var(--space-small) + 2 * var(--space-xxxsmall))); + max-height: calc(10 * (var(--space-4x) + 2 * var(--space))); overflow: auto; } @@ -72,7 +74,7 @@ right: 2px; top: 50%; transform: translateY(-50%); - padding: var(--space-xxxsmall); + padding: var(--space); font-size: var(--size-xsmall); line-height: 1.1; } @@ -86,8 +88,8 @@ top: 0; right: 100%; bottom: 0; - width: var(--space-small); - background: linear-gradient(90deg, rgba(255, 255, 255, 0), var(--color-highlight) 75%); + width: var(--space-4x); + background: linear-gradient(90deg, rgba(var(--color-background-rgb), 0), var(--color-highlight) 75%); } /** filter hover state */ @@ -102,22 +104,22 @@ } .filterGroupSearchWrapper { - padding-bottom: var(--space-xxxsmall); - margin-bottom: var(--space-xxxsmall); + padding-bottom: var(--space); + margin-bottom: var(--space); border-bottom: 1px solid var(--color-outline); } .filterGroupSearchNotFound { - padding: var(--space-xxsmall) 0; + padding: var(--space-2x) 0; text-align: center; font-size: var(--size-small); - color: var(--color-text-light); + color: var(--color-text-muted); } .filterGroupActions { - margin-top: var(--space-xxxsmall); - padding-top: var(--space-xxxsmall); - padding-bottom: var(--space-xxxsmall); - margin-bottom: calc(0px - var(--space-xxxsmall)); + margin-top: var(--space); + padding-top: var(--space); + padding-bottom: var(--space); + margin-bottom: calc(0px - var(--space)); border-top: 1px solid var(--color-outline); } diff --git a/packages/ui/src/ui/hover-card/hover-card.module.css b/packages/ui/src/ui/hover-card/hover-card.module.css index 11b5ea3d94..44221544ea 100644 --- a/packages/ui/src/ui/hover-card/hover-card.module.css +++ b/packages/ui/src/ui/hover-card/hover-card.module.css @@ -18,13 +18,13 @@ .hoverCard { z-index: var(--layer-xxhigh); - padding: var(--space-small); + padding: var(--space-4x); border-radius: var(--radius-medium); - width: calc(100vw - 2 * var(--space-small)); + width: calc(100vw - 2 * var(--space-4x)); max-width: 340px; outline: none; filter: drop-shadow(var(--shadow-layer-high)); will-change: filter; - background: var(--color-light); + background: var(--color-background); font-size: var(--size-small); } diff --git a/packages/ui/src/ui/icon/icon.module.css b/packages/ui/src/ui/icon/icon.module.css index 16d490906c..2f83543be5 100644 --- a/packages/ui/src/ui/icon/icon.module.css +++ b/packages/ui/src/ui/icon/icon.module.css @@ -11,16 +11,16 @@ /** Size variation */ .small { - width: var(--space-xsmall); - height: var(--space-xsmall); + width: var(--space-3x); + height: var(--space-3x); } .medium { - width: var(--space-small); - height: var(--space-small); + width: var(--space-4x); + height: var(--space-4x); } .large { - width: var(--space-medium); - height: var(--space-medium); + width: var(--space-6x); + height: var(--space-6x); } diff --git a/packages/ui/src/ui/icon/icon.tsx b/packages/ui/src/ui/icon/icon.tsx index c25805358b..edfeff537b 100644 --- a/packages/ui/src/ui/icon/icon.tsx +++ b/packages/ui/src/ui/icon/icon.tsx @@ -7,26 +7,29 @@ const ICONS = { ARROW: 'arrow', ARROW_RIGHT_CIRCLE: 'arrow-right-circle', CANCEL: 'close', + CHECK: 'check', CHEVRON_DOWN: 'chevron-down', CHEVRON_UP: 'chevron-up', - CHECK: 'check', - CLOSE: 'close', - CLOCK: 'clock', - COMMIT: 'commit', CLIPBOARD: 'clipboard', CLIPBOARD_CHECK: 'clipboard-check', + CLOCK: 'clock', + CLOSE: 'close', + COMMIT: 'commit', DOWNLOAD: 'download', ERROR: 'error', EXTERNAL_LINK: 'external-link', FILTER: 'filter', GITHUB: 'github', - INFO: 'info', HELP: 'help', - TABLE: 'table', - TREEMAP: 'treemap', + INFO: 'info', MENU: 'menu', + MONITOR: 'monitor', + MOON: 'moon', MORE_VERTICAL: 'more-vertical', SORT: 'sort', + SUN: 'sun', + TABLE: 'table', + TREEMAP: 'treemap', WARNING: 'warning', } as const; diff --git a/packages/ui/src/ui/input-search/input-search.module.css b/packages/ui/src/ui/input-search/input-search.module.css index e25b9a0fbe..3bdcbbca40 100644 --- a/packages/ui/src/ui/input-search/input-search.module.css +++ b/packages/ui/src/ui/input-search/input-search.module.css @@ -5,14 +5,14 @@ } .input { - height: var(--space-large); + height: var(--space-8x); } .cancelButton { position: absolute; - right: var(--space-xxxsmall); + right: var(--space); top: 50%; transform: translateY(-50%); - padding: var(--space-xxxsmall); + padding: var(--space); background: radial-gradient(var(--color-background) 50%, transparent); } diff --git a/packages/ui/src/ui/input/input.module.css b/packages/ui/src/ui/input/input.module.css index 7c74ecdfd1..414b62779e 100644 --- a/packages/ui/src/ui/input/input.module.css +++ b/packages/ui/src/ui/input/input.module.css @@ -1,7 +1,8 @@ .root { border: 1px solid var(--color-outline); border-radius: var(--radius-small); - color: var(--color-text-light); + color: var(--color-text-muted); + background: var(--color-background); width: 100%; transition: var(--transition-in); appearance: none; @@ -9,23 +10,23 @@ } .root::-webkit-input-placeholder { - color: var(--color-text-light); + color: var(--color-text-muted); } .root::-moz-placeholder { - color: var(--color-text-light); + color: var(--color-text-muted); } .root:-ms-input-placeholder { - color: var(--color-text-light); + color: var(--color-text-muted); } .root:-moz-placeholder { - color: var(--color-text-light); + color: var(--color-text-muted); } .root:focus { - border-color: var(--color-outline-dark); + border-color: var(--color-outline-intense); color: inherit; transition: var(--transition-out); } @@ -33,19 +34,19 @@ /** Size modifier */ /* default - medium */ .root { - padding: var(--space-xsmall); + padding: var(--space-3x); font-size: 1rem; - line-height: calc(var(--space-small) - 2px); + line-height: calc(var(--space-4x) - 2px); } .small { - padding: var(--space-xxsmall); + padding: var(--space-2x); font-size: var(--size-small); - line-height: calc(var(--space-small) - 2px); + line-height: calc(var(--space-4x) - 2px); } .large { - padding: var(--space-small); + padding: var(--space-4x); font-size: var(--size-large); - line-height: calc(var(--space-large) - 2px); + line-height: calc(var(--space-8x) - 2px); } diff --git a/packages/ui/src/ui/loader/loader.module.css b/packages/ui/src/ui/loader/loader.module.css index 1506b958cf..22ea9d5050 100644 --- a/packages/ui/src/ui/loader/loader.module.css +++ b/packages/ui/src/ui/loader/loader.module.css @@ -42,18 +42,18 @@ /** Size modifiers */ .small { --border-width: 2px; - width: var(--space-small); - height: var(--space-small); + width: var(--space-4x); + height: var(--space-4x); } .medium { --border-width: 3px; - width: var(--space-medium); - height: var(--space-medium); + width: var(--space-6x); + height: var(--space-6x); } .large { --border-width: 4px; - width: var(--space-large); - height: var(--space-large); + width: var(--space-8x); + height: var(--space-8x); } diff --git a/packages/ui/src/ui/markdown/markdown.module.css b/packages/ui/src/ui/markdown/markdown.module.css index d5f73f6aed..3df68c584a 100644 --- a/packages/ui/src/ui/markdown/markdown.module.css +++ b/packages/ui/src/ui/markdown/markdown.module.css @@ -1,5 +1,5 @@ .root code { - padding: 2px var(--space-xxxsmall); + padding: 2px var(--space); background: var(--color-highlight); outline: 1px solid var(--color-outline); border-radius: var(--radius-small); diff --git a/packages/ui/src/ui/table/table.module.css b/packages/ui/src/ui/table/table.module.css index 9ee2fdf20b..9877b8f704 100644 --- a/packages/ui/src/ui/table/table.module.css +++ b/packages/ui/src/ui/table/table.module.css @@ -11,7 +11,7 @@ .root td { border: 1px solid var(--color-outline); border-width: 1px 0 0; - padding: var(--space-small); + padding: var(--space-4x); } .root thead th { @@ -55,7 +55,7 @@ .empty { border: 1px solid var(--color-outline); border-width: 1px 0; - padding: var(--space-xlarge) var(--space-medium); + padding: var(--space-10x) var(--space-6x); background: var(--color-background) !important; text-align: center; } @@ -122,6 +122,6 @@ /* compact variation */ .compact td, .compact th { - padding-top: var(--space-xsmall); - padding-bottom: var(--space-xsmall); + padding-top: var(--space-3x); + padding-bottom: var(--space-3x); } diff --git a/packages/ui/src/ui/tabs/tabs.module.css b/packages/ui/src/ui/tabs/tabs.module.css index be926f0eee..b203220d93 100644 --- a/packages/ui/src/ui/tabs/tabs.module.css +++ b/packages/ui/src/ui/tabs/tabs.module.css @@ -9,8 +9,8 @@ border: 0; position: relative; display: inline-block; - padding: var(--space-xsmall) var(--space-small); - color: var(--color-text-ultra-light); + padding: var(--space-3x) var(--space-4x); + color: var(--color-text-ultra-muted); font-weight: bold; text-decoration: none; transition: var(--ui-transition-out); diff --git a/packages/ui/src/ui/tag/tag.module.css b/packages/ui/src/ui/tag/tag.module.css index bcc30aa849..6a5414b44b 100644 --- a/packages/ui/src/ui/tag/tag.module.css +++ b/packages/ui/src/ui/tag/tag.module.css @@ -2,8 +2,8 @@ display: inline-block; font-family: var(--font-family); font-weight: bold; - background: var(--color-text-ultra-light); - color: var(--color-light); + background: var(--color-text-ultra-muted); + color: var(--color-background); text-align: center; text-transform: uppercase; } @@ -17,7 +17,7 @@ a.root:hover, a.root:focus, a.root:active { opacity: 0.8; - color: var(--color-light); + color: var(--color-background); text-decoration: none; transition: var(--transition-in); } @@ -32,7 +32,7 @@ a.root:active { } .warning { - background: var(--color-warning-dark); + background: var(--color-warning-intense); } .danger { @@ -43,27 +43,27 @@ a.root:active { /** default: medium */ .root { border-radius: var(--radius-small); - padding: calc(var(--space-xxxsmall) / 2) var(--space-xxxsmall); - min-width: var(--space-small); - height: var(--space-small); + padding: calc(var(--space) / 2) var(--space); + min-width: var(--space-4x); + height: var(--space-4x); font-size: 9px; - line-height: var(--space-xsmall); + line-height: var(--space-3x); } .small { border-radius: var(--radius-xsmall); - padding: calc(var(--space-xxxsmall) / 2); - height: var(--space-xsmall); - min-width: var(--space-xsmall); + padding: calc(var(--space) / 2); + height: var(--space-3x); + min-width: var(--space-3x); font-size: 8px; line-height: 1; } .large { border-radius: var(--radius-medium); - padding: var(--space-xxxsmall) var(--space-xxsmall); - min-width: var(--space-medium); - height: var(--space-medium); + padding: var(--space) var(--space-2x); + min-width: var(--space-6x); + height: var(--space-6x); font-size: 12px; - line-height: var(--space-small); + line-height: var(--space-4x); } diff --git a/packages/ui/src/ui/textarea/textarea.module.css b/packages/ui/src/ui/textarea/textarea.module.css index 3adf14eb88..08c12a15d1 100644 --- a/packages/ui/src/ui/textarea/textarea.module.css +++ b/packages/ui/src/ui/textarea/textarea.module.css @@ -1,7 +1,7 @@ .root { border: 1px solid var(--color-outline); border-radius: var(--radius-small); - color: var(--color-text-light); + color: var(--color-text-muted); width: 100%; resize: vertical; transition: var(--transition-in); @@ -10,47 +10,47 @@ } .root::-webkit-input-placeholder { - color: var(--color-text-light); + color: var(--color-text-muted); } .root::-moz-placeholder { - color: var(--color-text-light); + color: var(--color-text-muted); } .root:-ms-input-placeholder { - color: var(--color-text-light); + color: var(--color-text-muted); } .root:-moz-placeholder { - color: var(--color-text-light); + color: var(--color-text-muted); } .root:focus { - border-color: var(--color-outline-dark); + border-color: var(--color-outline-intense); color: inherit; transition: var(--transition-out); } .root[readonly=""] { - color: var(--color-text-light); + color: var(--color-text-muted); } /** Size modifier */ /* default - medium */ .root { - padding: var(--space-xsmall); + padding: var(--space-3x); font-size: var(--size-medium); - line-height: calc(var(--space-medium) - 2px); + line-height: calc(var(--space-6x) - 2px); } .small { - padding: var(--space-xxsmall); + padding: var(--space-2x); font-size: var(--size-small); - line-height: calc(var(--space-small) - 2px); + line-height: calc(var(--space-4x) - 2px); } .large { - padding: var(--space-small); + padding: var(--space-4x); font-size: var(--size-large); - line-height: calc(var(--space-large) - 2px); + line-height: calc(var(--space-8x) - 2px); } diff --git a/packages/ui/src/ui/toolbar/toolbar.module.css b/packages/ui/src/ui/toolbar/toolbar.module.css index 07baffe1ff..a8b9f3f8bf 100644 --- a/packages/ui/src/ui/toolbar/toolbar.module.css +++ b/packages/ui/src/ui/toolbar/toolbar.module.css @@ -3,7 +3,7 @@ .content {} .actions { - margin-top: var(--space-xsmall); + margin-top: var(--space-3x); display: flex; align-items: center; } @@ -13,7 +13,7 @@ } .action + .action { - margin-left: var(--space-xsmall); + margin-left: var(--space-3x); } @media (min-width: 768px) { @@ -28,7 +28,7 @@ .actions { margin-top: 0; - margin-left: var(--space-small); + margin-left: var(--space-4x); flex: 0 0 auto; } } diff --git a/packages/ui/src/ui/tooltip/tooltip.module.css b/packages/ui/src/ui/tooltip/tooltip.module.css index 229cf2b343..a1e6f68064 100644 --- a/packages/ui/src/ui/tooltip/tooltip.module.css +++ b/packages/ui/src/ui/tooltip/tooltip.module.css @@ -12,9 +12,9 @@ .tooltip { z-index: var(--layer-xxhigh); - padding: var(--space-xxxsmall) var(--space-xxsmall); + padding: var(--space) var(--space-2x); border-radius: var(--radius-small); - background: var(--color-text); + background: var(--color-text-intense); max-width: 28em; color: var(--color-background); font-size: var(--size-small); @@ -25,5 +25,5 @@ .arrow svg { display: block; - fill: var(--color-text); + fill: var(--color-text-intense); } diff --git a/packages/ui/src/ui/tooltip/tooltip.stories.module.css b/packages/ui/src/ui/tooltip/tooltip.stories.module.css index dc02ef919f..6fc9653d2a 100644 --- a/packages/ui/src/ui/tooltip/tooltip.stories.module.css +++ b/packages/ui/src/ui/tooltip/tooltip.stories.module.css @@ -1,5 +1,5 @@ .customTooltip { - padding: var(--space-large); + padding: var(--space-8x); color: var(--color-danger); font-size: var(--size-large); text-align: left; diff --git a/packages/ui/src/utils/index.ts b/packages/ui/src/utils/index.ts index 0c490affe6..7f522192be 100644 --- a/packages/ui/src/utils/index.ts +++ b/packages/ui/src/utils/index.ts @@ -1,3 +1,4 @@ export * from './colors'; +export * from './theme'; export * from './jobs'; export * from './components'; diff --git a/packages/ui/src/utils/theme.ts b/packages/ui/src/utils/theme.ts new file mode 100644 index 0000000000..d6321be7ea --- /dev/null +++ b/packages/ui/src/utils/theme.ts @@ -0,0 +1,53 @@ +import { useCookie } from 'react-use'; +import Cookies from 'js-cookie'; +import { wait } from '@bundle-stats/utils'; + +export type ThemeName = 'light' | 'dark'; + +// classList required timeout to allow to disable motion during the switch +const CLASSLIST_UPDATE_TIMEOUT = 10; + +const COOKIE_NAME = 'theme'; + +export const getCurrentTheme = (): ThemeName => { + const { matches } = window.matchMedia('(prefers-color-scheme: dark)'); + return matches ? 'dark' : 'light'; +}; + +export const getCookieTheme = (): ThemeName | null => { + const nextTheme = Cookies.get(COOKIE_NAME); + + if (!nextTheme) { + return null; + } + + if (['light', 'dark'].includes(nextTheme)) { + return nextTheme as ThemeName; + } + + return null; +}; + +export const switchTheme = async (newTheme: ThemeName) => { + const htmlElm = document.querySelector('html'); + + htmlElm?.classList.add('no-motion'); + + await wait(CLASSLIST_UPDATE_TIMEOUT); + + if (newTheme === 'dark') { + htmlElm?.classList.remove('light-theme'); + htmlElm?.classList.add('dark-theme'); + } else { + htmlElm?.classList.remove('dark-theme'); + htmlElm?.classList.add('light-theme'); + } + + await wait(CLASSLIST_UPDATE_TIMEOUT); + + htmlElm?.classList.remove('no-motion'); +}; + +export const useCookieTheme = () => { + return useCookie(COOKIE_NAME); +}; diff --git a/packages/utils/src/utils/index.js b/packages/utils/src/utils/index.js index ec2361b496..d95124df60 100644 --- a/packages/utils/src/utils/index.js +++ b/packages/utils/src/utils/index.js @@ -5,3 +5,4 @@ export * from './insights'; export * from './file-types'; export * from './format'; export * from './metrics'; +export * from './wait'; diff --git a/packages/utils/src/utils/wait.ts b/packages/utils/src/utils/wait.ts new file mode 100644 index 0000000000..7b1a4bf9c8 --- /dev/null +++ b/packages/utils/src/utils/wait.ts @@ -0,0 +1,6 @@ +export const wait = (timeout = 0): Promise
=> + new Promise((resolve) => { + setTimeout(() => { + return resolve(); + }, timeout); +});