From ee1d708c043559e776156c41a31cc386e35c2fd4 Mon Sep 17 00:00:00 2001 From: xiejay97 Date: Sat, 8 Jan 2022 13:28:16 +0800 Subject: [PATCH] feat: add dark theme --- .stylelintrc | 2 +- packages/site/src/app/App.tsx | 22 +- .../src/app/components/header/Header.scss | 21 +- .../site/src/app/components/header/Header.tsx | 51 +++- .../components/route/component/DemoBox.scss | 4 +- packages/site/src/app/styles/_app.scss | 9 +- packages/site/src/app/styles/_variables.scss | 3 +- packages/site/src/app/styles/index.scss | 1 - packages/site/src/app/styles/theme-dark.scss | 219 ++++++++++++++++++ packages/site/src/styles.scss | 3 + packages/ui/src/components/empty/Empty.tsx | 61 +++-- packages/ui/src/components/root/Root.tsx | 30 ++- packages/ui/src/components/tag/Tag.tsx | 7 +- .../ui/src/components/tag/demos/3.Color.md | 10 +- packages/ui/src/hooks/d-config.ts | 10 +- packages/ui/src/hooks/index.ts | 2 +- .../ui/src/hooks/transition/transition.ts | 3 +- packages/ui/src/hooks/wave.ts | 2 +- packages/ui/src/styles/_animations.scss | 14 +- packages/ui/src/styles/_variables.scss | 29 ++- .../ui/src/styles/components/_button.scss | 18 +- .../ui/src/styles/components/_checkbox.scss | 52 ++--- .../ui/src/styles/components/_drawer.scss | 3 +- .../ui/src/styles/components/_dropdown.scss | 2 +- packages/ui/src/styles/components/_input.scss | 9 +- packages/ui/src/styles/components/_radio.scss | 4 +- .../ui/src/styles/components/_select-box.scss | 11 +- .../ui/src/styles/components/_select.scss | 5 +- .../ui/src/styles/components/_switch.scss | 30 ++- packages/ui/src/styles/components/_tag.scss | 2 +- .../ui/src/styles/components/_textarea.scss | 7 +- packages/ui/src/styles/index.scss | 2 + packages/ui/src/styles/theme-dark.scss | 89 +++++++ packages/ui/src/utils/color.ts | 19 ++ packages/ui/src/utils/index.ts | 2 +- 35 files changed, 594 insertions(+), 164 deletions(-) create mode 100644 packages/site/src/app/styles/theme-dark.scss create mode 100644 packages/ui/src/styles/theme-dark.scss diff --git a/.stylelintrc b/.stylelintrc index b8dd7ccc..7c89be1d 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -19,7 +19,7 @@ "declaration-property-value-allowed-list": { "/color/": ["/var/", "currentColor", "transparent", "unset", "inherit"], "font-size": ["/var/", "/[0-9]+em$/", "unset", "inherit"], - "border-radius": ["/var/", "50%", "0"] + "border-radius": ["/var/", "50%", "0", "inherit"] }, "declaration-property-value-disallowed-list": { "transition": ["/all/"] diff --git a/packages/site/src/app/App.tsx b/packages/site/src/app/App.tsx index 1bdb1c24..37396a1b 100644 --- a/packages/site/src/app/App.tsx +++ b/packages/site/src/app/App.tsx @@ -1,3 +1,5 @@ +import type { DLang, DTheme } from '@react-devui/ui/hooks/d-config'; + import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation } from 'react-router-dom'; @@ -13,6 +15,8 @@ import { AppRoutes } from './routes/Routes'; export interface AppContextData { menuOpen: boolean; pageMounted: boolean; + theme: DTheme; + changeTheme: (theme: DTheme) => void; onMount: () => void; onMenuOpenChange: (open: boolean) => void; } @@ -24,6 +28,7 @@ export function App() { const [menuOpen, setMenuOpen] = useState(false); const [pageMounted, setPageMounted] = useState(false); + const [theme, setTheme] = useState(() => (localStorage.getItem('theme') as DTheme) ?? 'light'); const [mainEl, setMainEl] = useState(null); const mainRef = useCallback( @@ -56,6 +61,14 @@ export function App() { } }, [asyncCapture, mainEl]); + useEffect(() => { + const el = document.createElement('div'); + el.setAttribute('style', 'position: absolute;top: -999px;left: -999px;overflow: scroll;width: 100px;height: 100px;'); + document.body.appendChild(el); + document.body.classList.toggle('scrollbar-dark', theme === 'dark' && el.clientHeight < 100); + document.body.removeChild(el); + }, [theme]); + const location = useLocation(); useEffect(() => { NotificationService.closeAll(false); @@ -66,6 +79,11 @@ export function App() { () => ({ menuOpen, pageMounted, + theme, + changeTheme: (theme) => { + setTheme(theme); + localStorage.setItem('theme', theme); + }, onMount: () => { setPageMounted(true); if (mainEl) { @@ -82,11 +100,11 @@ export function App() { setMenuOpen(open); }, }), - [mainEl, menuOpen, pageMounted, setMenuOpen, setPageMounted] + [mainEl, menuOpen, pageMounted, theme] ); return ( - + diff --git a/packages/site/src/app/components/header/Header.scss b/packages/site/src/app/components/header/Header.scss index df842cb1..1061ce48 100644 --- a/packages/site/src/app/components/header/Header.scss +++ b/packages/site/src/app/components/header/Header.scss @@ -70,7 +70,7 @@ height: 64px; padding: 0 20px; - background-color: var(--d-background-color); + background-color: var(--app-header-background-color); &.is-shadow { box-shadow: 0 2px 8px 0 var(--d-shadow-color); @@ -94,26 +94,11 @@ @include font-size(1.5rem); } - .app-header__github { - display: inline-flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; + .app-header__button { margin-left: 12px; - padding: 0; + border: 1px solid var(--d-border-color); /* stylelint-disable-next-line declaration-property-value-allowed-list */ border-radius: 8px; } - - .app-header__github-icon { - width: 20px; - height: 20px; - - /* stylelint-disable-next-line */ - background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjQwcHgiIGhlaWdodD0iNDBweCIgdmlld0JveD0iMTIgMTIgNDAgNDAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMTIgMTIgNDAgNDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwYXRoIGZpbGw9IiMzMzMzMzMiIGQ9Ik0zMiAxMy40Yy0xMC41IDAtMTkgOC41LTE5IDE5YzAgOC40IDUuNSAxNS41IDEzIDE4YzEgMC4yIDEuMy0wLjQgMS4zLTAuOWMwLTAuNSAwLTEuNyAwLTMuMiBjLTUuMyAxLjEtNi40LTIuNi02LjQtMi42QzIwIDQxLjYgMTguOCA0MSAxOC44IDQxYy0xLjctMS4yIDAuMS0xLjEgMC4xLTEuMWMxLjkgMC4xIDIuOSAyIDIuOSAyYzEuNyAyLjkgNC41IDIuMSA1LjUgMS42IGMwLjItMS4yIDAuNy0yLjEgMS4yLTIuNmMtNC4yLTAuNS04LjctMi4xLTguNy05LjRjMC0yLjEgMC43LTMuNyAyLTUuMWMtMC4yLTAuNS0wLjgtMi40IDAuMi01YzAgMCAxLjYtMC41IDUuMiAyIGMxLjUtMC40IDMuMS0wLjcgNC44LTAuN2MxLjYgMCAzLjMgMC4yIDQuNyAwLjdjMy42LTIuNCA1LjItMiA1LjItMmMxIDIuNiAwLjQgNC42IDAuMiA1YzEuMiAxLjMgMiAzIDIgNS4xYzAgNy4zLTQuNSA4LjktOC43IDkuNCBjMC43IDAuNiAxLjMgMS43IDEuMyAzLjVjMCAyLjYgMCA0LjYgMCA1LjJjMCAwLjUgMC40IDEuMSAxLjMgMC45YzcuNS0yLjYgMTMtOS43IDEzLTE4LjFDNTEgMjEuOSA0Mi41IDEzLjQgMzIgMTMuNHoiLz48L3N2Zz4=); - background-repeat: no-repeat; - background-size: 100% 100%; - } } diff --git a/packages/site/src/app/components/header/Header.tsx b/packages/site/src/app/components/header/Header.tsx index b89c5f7f..74d3c9f2 100644 --- a/packages/site/src/app/components/header/Header.tsx +++ b/packages/site/src/app/components/header/Header.tsx @@ -1,7 +1,7 @@ import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { DButton, DRow } from '@react-devui/ui'; +import { DButton, DIcon, DRow } from '@react-devui/ui'; import { useCustomContext } from '@react-devui/ui/hooks'; import { getClassName } from '@react-devui/ui/utils'; @@ -11,16 +11,16 @@ import './Header.scss'; export function AppHeader() { const { i18n } = useTranslation(); - const [{ menuOpen = false, onMenuOpenChange }] = useCustomContext(AppContext); + const [{ theme, changeTheme: _changeTheme, menuOpen = false, onMenuOpenChange }] = useCustomContext(AppContext); const changeLanguage = useCallback(() => { - if (i18n.language === 'en-US') { - i18n.changeLanguage('zh-Hant'); - } else { - i18n.changeLanguage('en-US'); - } + i18n.changeLanguage(i18n.language === 'en-US' ? 'zh-Hant' : 'en-US'); }, [i18n]); + const changeTheme = useCallback(() => { + _changeTheme?.(theme === 'light' ? 'dark' : 'light'); + }, [_changeTheme, theme]); + return (
{i18n.language === 'en-US' ? '中 文' : 'English'} + + {theme === 'light' ? ( + + ) : ( + <> + + + + + + + + + + + )} + + } + onClick={changeTheme} + > - - - + + + + + } + >
); diff --git a/packages/site/src/app/components/route/component/DemoBox.scss b/packages/site/src/app/components/route/component/DemoBox.scss index 7e89213c..8e3e4610 100644 --- a/packages/site/src/app/components/route/component/DemoBox.scss +++ b/packages/site/src/app/components/route/component/DemoBox.scss @@ -3,6 +3,8 @@ .app-demo-box { border: 1px solid var(--d-divider-color); + background-color: var(--app-demo-box-background-color); + &.is-active { border-color: var(--d-color-primary); } @@ -35,7 +37,7 @@ padding: 1px 8px; - background-color: var(--d-background-color); + background-color: var(--app-demo-box-background-color); } .app-demo-box__description { diff --git a/packages/site/src/app/styles/_app.scss b/packages/site/src/app/styles/_app.scss index fed44f28..ec6fdf42 100644 --- a/packages/site/src/app/styles/_app.scss +++ b/packages/site/src/app/styles/_app.scss @@ -1,4 +1,4 @@ -/* stylelint-disable selector-id-pattern */ +/* stylelint-disable declaration-property-value-allowed-list */ *, *::before, *::after { @@ -15,10 +15,8 @@ body { line-height: 1.5; text-align: null; - /* stylelint-disable-next-line declaration-property-value-allowed-list */ - background-color: white; // 2 + background-color: #fff; // 2 text-size-adjust: 100%; // 3 - /* stylelint-disable-next-line declaration-property-value-allowed-list */ -webkit-tap-highlight-color: rgb(0 0 0 / 0%); // 4 @include font-size(1rem); @@ -100,7 +98,6 @@ pre code.hljs { code:not(pre > code) { margin: 0 1px; padding: 4px 6px; - /* stylelint-disable-next-line declaration-property-value-allowed-list */ border-radius: 2px; font-family: Consolas, Menlo, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; @@ -235,7 +232,6 @@ h3 { width: 160px; height: 40px; - /* stylelint-disable-next-line declaration-property-value-allowed-list */ color: #fff; background-color: var(--d-color-primary); @@ -271,7 +267,6 @@ h3 { justify-content: center; height: 48px; - /* stylelint-disable-next-line declaration-property-value-allowed-list */ color: #fff; background-color: var(--d-color-primary); diff --git a/packages/site/src/app/styles/_variables.scss b/packages/site/src/app/styles/_variables.scss index fa75f290..ca652843 100644 --- a/packages/site/src/app/styles/_variables.scss +++ b/packages/site/src/app/styles/_variables.scss @@ -1,6 +1,7 @@ /* stylelint-disable declaration-property-value-allowed-list */ - :root { --app-th-background-color: #f9f9f9; --app-code-background-color: #f2f4f5; + --app-demo-box-background-color: #fff; + --app-header-background-color: #fff; } diff --git a/packages/site/src/app/styles/index.scss b/packages/site/src/app/styles/index.scss index 172610d1..d09a611a 100644 --- a/packages/site/src/app/styles/index.scss +++ b/packages/site/src/app/styles/index.scss @@ -1,4 +1,3 @@ -@use 'sass:color'; @import 'variables'; @import 'app'; diff --git a/packages/site/src/app/styles/theme-dark.scss b/packages/site/src/app/styles/theme-dark.scss new file mode 100644 index 00000000..4d3b5194 --- /dev/null +++ b/packages/site/src/app/styles/theme-dark.scss @@ -0,0 +1,219 @@ +/* stylelint-disable no-descending-specificity */ +/* stylelint-disable declaration-property-value-allowed-list */ +@import '../../../../ui/src/styles/theme-dark'; + +body.dark { + --app-th-background-color: rgb(13 13 13); + --app-code-background-color: #2d2d2f; + --app-demo-box-background-color: rgb(8 8 8); + --app-header-background-color: rgb(26 26 26); + + background-color: rgb(18 18 18); + + pre code.hljs { + display: block; + padding: 1em; + overflow-x: auto; + } + + code.hljs { + padding: 3px 5px; + } + + .hljs { + color: #c9d1d9; + } + + .hljs-doctag, + .hljs-keyword, + .hljs-meta .hljs-keyword, + .hljs-template-tag, + .hljs-template-variable, + .hljs-type, + .hljs-variable.language_ { + color: #ff7b72; + } + + .hljs-title, + .hljs-title.class_, + .hljs-title.class_.inherited__, + .hljs-title.function_ { + color: #d2a8ff; + } + + .hljs-attr, + .hljs-attribute, + .hljs-literal, + .hljs-meta, + .hljs-number, + .hljs-operator, + .hljs-selector-attr, + .hljs-selector-class, + .hljs-selector-id, + .hljs-variable { + color: #79c0ff; + } + + .hljs-meta .hljs-string, + .hljs-regexp, + .hljs-string { + color: #a5d6ff; + } + + .hljs-built_in, + .hljs-symbol { + color: #ffa657; + } + + .hljs-code, + .hljs-comment, + .hljs-formula { + color: #8b949e; + } + + .hljs-name, + .hljs-quote, + .hljs-selector-pseudo, + .hljs-selector-tag { + color: #7ee787; + } + + .hljs-subst { + color: #c9d1d9; + } + + .hljs-section { + color: #1f6feb; + font-weight: 700; + } + + .hljs-bullet { + color: #f2cc60; + } + + .hljs-emphasis { + color: #c9d1d9; + font-style: italic; + } + + .hljs-strong { + color: #c9d1d9; + font-weight: 700; + } + + .hljs-addition { + color: #aff5b4; + + background-color: #033a16; + } + + .hljs-deletion { + color: #ffdcd7; + + background-color: #67060c; + } +} + +.scrollbar-dark { + *::-webkit-scrollbar { + width: 16px; + height: 16px; + } + + *::-webkit-scrollbar-corner, + *::-webkit-scrollbar-track { + background-color: rgb(64 64 64); + } + + *::-webkit-scrollbar-thumb { + border: 2px solid transparent; + + background-color: rgb(96 96 96); + background-clip: padding-box; + } + + *::-webkit-scrollbar-thumb:hover { + background-color: rgb(112 112 112); + } + + *::-webkit-scrollbar-thumb:active { + background-color: rgb(128 128 128); + } + + /* Buttons */ + *::-webkit-scrollbar-button:single-button { + display: block; + + background-color: rgb(64 64 64); + background-repeat: no-repeat; + background-size: 10px; + } + + /* Up */ + *::-webkit-scrollbar-button:single-button:vertical:decrement { + width: 16px; + height: 12px; + + background-image: url("data:image/svg+xml;utf8,"); + background-position: center 4px; + } + + *::-webkit-scrollbar-button:single-button:vertical:decrement:hover { + background-image: url("data:image/svg+xml;utf8,"); + } + + *::-webkit-scrollbar-button:single-button:vertical:decrement:active { + background-image: url("data:image/svg+xml;utf8,"); + } + + /* Down */ + *::-webkit-scrollbar-button:single-button:vertical:increment { + width: 16px; + height: 12px; + + background-image: url("data:image/svg+xml;utf8,"); + background-position: center 2px; + } + + *::-webkit-scrollbar-button:single-button:vertical:increment:hover { + background-image: url("data:image/svg+xml;utf8,"); + } + + *::-webkit-scrollbar-button:single-button:vertical:increment:active { + background-image: url("data:image/svg+xml;utf8,"); + } + + /* Left */ + *::-webkit-scrollbar-button:single-button:horizontal:decrement { + width: 12px; + height: 12px; + + background-image: url("data:image/svg+xml;utf8,"); + background-position: 3px 3px; + } + + *::-webkit-scrollbar-button:single-button:horizontal:decrement:hover { + background-image: url("data:image/svg+xml;utf8,"); + } + + *::-webkit-scrollbar-button:single-button:horizontal:decrement:active { + background-image: url("data:image/svg+xml;utf8,"); + } + + /* Right */ + *::-webkit-scrollbar-button:single-button:horizontal:increment { + width: 12px; + height: 12px; + + background-image: url("data:image/svg+xml;utf8,"); + background-position: 3px 3px; + } + + *::-webkit-scrollbar-button:single-button:horizontal:increment:hover { + background-image: url("data:image/svg+xml;utf8,"); + } + + *::-webkit-scrollbar-button:single-button:horizontal:increment:active { + background-image: url("data:image/svg+xml;utf8,"); + } +} diff --git a/packages/site/src/styles.scss b/packages/site/src/styles.scss index 48b02251..4cdd0f8f 100644 --- a/packages/site/src/styles.scss +++ b/packages/site/src/styles.scss @@ -1,4 +1,7 @@ /* You can add global styles to this file, and also import other style files */ +@use 'sass:color'; + @import '~highlight.js/scss/github'; @import '../../ui/src/styles/index'; @import './app/styles/index'; +@import './app/styles/theme-dark'; diff --git a/packages/ui/src/components/empty/Empty.tsx b/packages/ui/src/components/empty/Empty.tsx index 9bae3e52..c31b6ebb 100644 --- a/packages/ui/src/components/empty/Empty.tsx +++ b/packages/ui/src/components/empty/Empty.tsx @@ -1,7 +1,7 @@ import { isUndefined } from 'lodash'; import { useMemo } from 'react'; -import { usePrefixConfig, useComponentConfig, useTranslation } from '../../hooks'; +import { usePrefixConfig, useComponentConfig, useTranslation, useThemeConfig } from '../../hooks'; import { getClassName } from '../../utils'; import { DIcon } from '../icon'; @@ -14,6 +14,7 @@ export function DEmpty(props: DEmptyProps) { //#region Context const dPrefix = usePrefixConfig(); + const theme = useThemeConfig(); //#endregion const [t] = useTranslation('Common'); @@ -26,81 +27,73 @@ export function DEmpty(props: DEmptyProps) { - - + + + - ) : ( diff --git a/packages/ui/src/components/root/Root.tsx b/packages/ui/src/components/root/Root.tsx index d06c7276..fe439b38 100644 --- a/packages/ui/src/components/root/Root.tsx +++ b/packages/ui/src/components/root/Root.tsx @@ -1,6 +1,6 @@ import type { DConfigContextData } from '../../hooks/d-config'; -import { useEffect } from 'react'; +import { useEffect, useMemo } from 'react'; import { DConfigContext } from '../../hooks/d-config'; import { Notification } from './Notification'; @@ -11,20 +11,32 @@ export interface DRootProps extends DConfigContextData { } export function DRoot(props: DRootProps) { - const { children, ...restProps } = props; + const { prefix, theme, componentConfigs, i18n, icons, contentSelector, children } = props; - const lang = restProps.i18n?.lang ?? 'en-US'; + const lang = i18n?.lang ?? 'en-US'; useEffect(() => { - if (lang === 'en-US') { - document.body.classList.add('CJK'); - } else { - document.body.classList.remove('CJK'); - } + document.body.classList.toggle('CJK', lang === 'zh-Hant'); }, [lang]); + useEffect(() => { + document.body.classList.toggle('dark', theme === 'dark'); + }, [theme]); + + const context = useMemo( + () => ({ + prefix, + theme, + componentConfigs, + i18n, + icons, + contentSelector, + }), + [componentConfigs, contentSelector, i18n, icons, prefix, theme] + ); + return ( - + {children} diff --git a/packages/ui/src/components/tag/Tag.tsx b/packages/ui/src/components/tag/Tag.tsx index ee75699b..65db0f22 100644 --- a/packages/ui/src/components/tag/Tag.tsx +++ b/packages/ui/src/components/tag/Tag.tsx @@ -1,7 +1,7 @@ import { useCallback } from 'react'; -import { usePrefixConfig, useComponentConfig, useTranslation, useGeneralState } from '../../hooks'; -import { getClassName, pSBC } from '../../utils'; +import { usePrefixConfig, useComponentConfig, useTranslation, useGeneralState, useThemeConfig } from '../../hooks'; +import { convertHex, getClassName, pSBC } from '../../utils'; import { DIcon } from '../icon'; export interface DTagProps extends React.HTMLAttributes { @@ -29,6 +29,7 @@ export function DTag(props: DTagProps) { //#region Context const dPrefix = usePrefixConfig(); + const theme = useThemeConfig(); const { gDisabled } = useGeneralState(); //#endregion @@ -55,7 +56,7 @@ export function DTag(props: DTagProps) { ? { [`--${dPrefix}tag-color`]: dColor, [`--${dPrefix}tag-border-color`]: pSBC(0.3, dColor), - [`--${dPrefix}tag-background-color`]: pSBC(0.92, dColor), + [`--${dPrefix}tag-background-color`]: convertHex(dColor, theme === 'light' ? 0.08 : 0.12), } : undefined } diff --git a/packages/ui/src/components/tag/demos/3.Color.md b/packages/ui/src/components/tag/demos/3.Color.md index f9a2bb2c..87fc40db 100644 --- a/packages/ui/src/components/tag/demos/3.Color.md +++ b/packages/ui/src/components/tag/demos/3.Color.md @@ -6,11 +6,11 @@ title: # en-US -Supports `hex` and `rgb(a)` color formats. +Support custom colors. # zh-Hant -支持 `hex` 以及 `rgb(a)` 的色彩格式。 +支持自定义颜色。 ```tsx import { DTag } from '@react-devui/ui'; @@ -29,11 +29,11 @@ export default function Demo() {
- Primary Tag - + Primary Tag + Fill Tag - + Outline Tag
diff --git a/packages/ui/src/hooks/d-config.ts b/packages/ui/src/hooks/d-config.ts index cc8b0a66..c904d955 100644 --- a/packages/ui/src/hooks/d-config.ts +++ b/packages/ui/src/hooks/d-config.ts @@ -8,12 +8,15 @@ interface Resources { [index: string]: string | Resources; } +export type DTheme = 'light' | 'dark'; +export type DLang = 'en-US' | 'zh-Hant'; export interface DConfigContextData { prefix?: string; + theme?: DTheme; // eslint-disable-next-line @typescript-eslint/no-explicit-any componentConfigs?: { [index: string]: any }; i18n?: { - lang?: 'en-US' | 'zh-Hant'; + lang?: DLang; resources?: Resources; }; icons?: Array<{ @@ -33,6 +36,11 @@ export function usePrefixConfig() { return prefix; } +export function useThemeConfig() { + const theme = useContext(DConfigContext).theme ?? 'light'; + return theme; +} + export function useComponentConfig(component: string, props: T): T { const componentConfigs = useContext(DConfigContext).componentConfigs ?? {}; const customConfig = componentConfigs[component] ?? {}; diff --git a/packages/ui/src/hooks/index.ts b/packages/ui/src/hooks/index.ts index a9ced754..21a368bd 100644 --- a/packages/ui/src/hooks/index.ts +++ b/packages/ui/src/hooks/index.ts @@ -2,7 +2,7 @@ export { useAsync } from './async'; export { useTranslation } from './i18n'; export { useDTransition, useDCollapseTransition } from './transition'; export { useCustomContext } from './context'; -export { usePrefixConfig, useContentRefConfig, useComponentConfig } from './d-config'; +export { usePrefixConfig, useThemeConfig, useContentRefConfig, useComponentConfig } from './d-config'; export { useRefSelector } from './element-ref'; export { useGeneralState, DGeneralStateContext } from './general-state'; export { useImmer, useImmerReducer } from './immer'; diff --git a/packages/ui/src/hooks/transition/transition.ts b/packages/ui/src/hooks/transition/transition.ts index 3fc7c8f4..7517d7c7 100644 --- a/packages/ui/src/hooks/transition/transition.ts +++ b/packages/ui/src/hooks/transition/transition.ts @@ -4,7 +4,8 @@ import { isFunction } from 'lodash'; import { useEffect, useLayoutEffect, useRef, useState } from 'react'; import { flushSync } from 'react-dom'; -import { useAsync, useImmer } from '../../hooks'; +import { useAsync } from '../async'; +import { useImmer } from '../immer'; import { CssRecord, getMaxTime } from './utils'; export interface DTransitionStateList { diff --git a/packages/ui/src/hooks/wave.ts b/packages/ui/src/hooks/wave.ts index 9b800b4b..eaafe8eb 100644 --- a/packages/ui/src/hooks/wave.ts +++ b/packages/ui/src/hooks/wave.ts @@ -33,7 +33,7 @@ export function useWave() { waveEl.style.boxShadow = `0px 0px 0px 0px ${color}`; waveEl.style.opacity = '0.2'; waveEl.style.setProperty(`--${dPrefix}wave-color`, color); - waveEl.style.animation = animation ?? 'wave 0.4s cubic-bezier(0.08, 0.82, 0.17, 1), wave-fade 2s cubic-bezier(0.08, 0.82, 0.17, 1)'; + waveEl.style.animation = animation ?? 'wave 0.4s cubic-bezier(0.08, 0.82, 0.17, 1), fade-out 2s cubic-bezier(0.08, 0.82, 0.17, 1)'; waveEl.style.animationFillMode = 'forwards'; el.appendChild(waveEl); diff --git a/packages/ui/src/styles/_animations.scss b/packages/ui/src/styles/_animations.scss index bd669a57..c515664d 100644 --- a/packages/ui/src/styles/_animations.scss +++ b/packages/ui/src/styles/_animations.scss @@ -10,13 +10,7 @@ } } -@keyframes wave-fade { - 100% { - opacity: 0; - } -} - -@keyframes radio-wave { +@keyframes wave-spread { 0% { transform: scale(1); opacity: 0.5; @@ -27,3 +21,9 @@ opacity: 0; } } + +@keyframes fade-out { + 100% { + opacity: 0; + } +} diff --git a/packages/ui/src/styles/_variables.scss b/packages/ui/src/styles/_variables.scss index 13d55e6d..3e58e9d6 100644 --- a/packages/ui/src/styles/_variables.scss +++ b/packages/ui/src/styles/_variables.scss @@ -37,8 +37,9 @@ $themes: ( --#{$variable-prefix}border-radius-larger: 4px; /** basic **/ - --#{$variable-prefix}text-color: #212529; - --#{$variable-prefix}background-color: #fff; + --#{$variable-prefix}text-color: rgb(33 37 41); + --#{$variable-prefix}text-color-rgb: 33 37 41; + --#{$variable-prefix}background-color: rgb(255 255 255); --#{$variable-prefix}background-color-rgb: 255 255 255; --#{$variable-prefix}shadow-color: rgb(0 0 0 / 20%); --#{$variable-prefix}divider-color: #eee; @@ -46,6 +47,8 @@ $themes: ( --#{$variable-prefix}indicator-background-color: #dfe1e6; --#{$variable-prefix}disabled-background-color: #f5f5f5; --#{$variable-prefix}disabled-color: #d5d5d5; + --#{$variable-prefix}hover-background-color: rgb(0 0 0 / 4%); + --#{$variable-prefix}input-background-color: #fff; /** step **/ --#{$variable-prefix}color-step-10: hsl(0deg 0% 99%); @@ -90,16 +93,16 @@ $themes: ( --#{$variable-prefix}color-#{$theme}-darker: #{color.scale(rgb($rgb), $lightness: -10%, $saturation: -10%)}; /** background **/ - --#{$variable-prefix}color-#{$theme}-background: #{color.scale(rgb($rgb), $lightness: 90%)}; - --#{$variable-prefix}color-#{$theme}-background-1: #{color.scale(rgb($rgb), $lightness: 91%)}; - --#{$variable-prefix}color-#{$theme}-background-2: #{color.scale(rgb($rgb), $lightness: 92%)}; - --#{$variable-prefix}color-#{$theme}-background-3: #{color.scale(rgb($rgb), $lightness: 93%)}; - --#{$variable-prefix}color-#{$theme}-background-4: #{color.scale(rgb($rgb), $lightness: 94%)}; - --#{$variable-prefix}color-#{$theme}-background-5: #{color.scale(rgb($rgb), $lightness: 95%)}; - --#{$variable-prefix}color-#{$theme}-background-6: #{color.scale(rgb($rgb), $lightness: 96%)}; - --#{$variable-prefix}color-#{$theme}-background-7: #{color.scale(rgb($rgb), $lightness: 97%)}; - --#{$variable-prefix}color-#{$theme}-background-8: #{color.scale(rgb($rgb), $lightness: 98%)}; - --#{$variable-prefix}color-#{$theme}-background-9: #{color.scale(rgb($rgb), $lightness: 99%)}; + --#{$variable-prefix}color-#{$theme}-background: #{color.scale(rgb($rgb), $alpha: -90%)}; + --#{$variable-prefix}color-#{$theme}-background-1: #{color.scale(rgb($rgb), $alpha: -91%)}; + --#{$variable-prefix}color-#{$theme}-background-2: #{color.scale(rgb($rgb), $alpha: -92%)}; + --#{$variable-prefix}color-#{$theme}-background-3: #{color.scale(rgb($rgb), $alpha: -93%)}; + --#{$variable-prefix}color-#{$theme}-background-4: #{color.scale(rgb($rgb), $alpha: -94%)}; + --#{$variable-prefix}color-#{$theme}-background-5: #{color.scale(rgb($rgb), $alpha: -95%)}; + --#{$variable-prefix}color-#{$theme}-background-6: #{color.scale(rgb($rgb), $alpha: -96%)}; + --#{$variable-prefix}color-#{$theme}-background-7: #{color.scale(rgb($rgb), $alpha: -97%)}; + --#{$variable-prefix}color-#{$theme}-background-8: #{color.scale(rgb($rgb), $alpha: -98%)}; + --#{$variable-prefix}color-#{$theme}-background-9: #{color.scale(rgb($rgb), $alpha: -99%)}; } /** component **/ @@ -107,4 +110,6 @@ $themes: ( --#{$variable-prefix}tooltip-background-color: #464d6e; --#{$variable-prefix}mask-background-color: rgb(0 0 0 / 20%); --#{$variable-prefix}empty-color: #a8afbc; + --#{$variable-prefix}switch-background-color: #d4d6d9; + --#{$variable-prefix}tag-background-color: rgb(0 0 0 / 6%); } diff --git a/packages/ui/src/styles/components/_button.scss b/packages/ui/src/styles/components/_button.scss index 8f3ff94c..82015dd7 100644 --- a/packages/ui/src/styles/components/_button.scss +++ b/packages/ui/src/styles/components/_button.scss @@ -47,7 +47,21 @@ @include when(loading) { cursor: wait; - filter: opacity(50%); + + &::after { + position: absolute; + top: -1px; + right: -1px; + bottom: -1px; + left: -1px; + + border-radius: inherit; + + /* stylelint-disable-next-line declaration-property-value-allowed-list */ + background-color: rgb(255 255 255 / 30%); + + content: ''; + } } @include m(primary) { @@ -61,7 +75,7 @@ background-color: var(--#{$variable-prefix}button-color); &:disabled:not(.is-loading) { - filter: saturate(50%) opacity(50%); + filter: saturate(50%) grayscale(50%); } @include button-hover { diff --git a/packages/ui/src/styles/components/_checkbox.scss b/packages/ui/src/styles/components/_checkbox.scss index b15686cd..c1b590da 100644 --- a/packages/ui/src/styles/components/_checkbox.scss +++ b/packages/ui/src/styles/components/_checkbox.scss @@ -32,22 +32,37 @@ @include when(checked) { @include e(input-wrapper) { &::before { - animation: radio-wave 0.36s ease-in-out; + animation: wave-spread 0.36s ease-in-out; animation-fill-mode: backwards; } - } - @include e(tick) { - animation: checkbox-tick 133ms ease-in-out; - animation-fill-mode: backwards; + &::after { + opacity: 1; + } } @include e(input) { border-color: var(--#{$variable-prefix}color-primary); } + + @include e(tick) { + animation: checkbox-tick 133ms ease-in-out; + animation-fill-mode: backwards; + } } @include when(indeterminate) { + @include e(input-wrapper) { + &::before { + animation: wave-spread 0.36s ease-in-out; + animation-fill-mode: backwards; + } + + &::after { + opacity: 1; + } + } + @include e(input) { border-color: var(--#{$variable-prefix}color-primary); } @@ -67,10 +82,6 @@ @include when(disabled) { @include e(input-wrapper) { background-color: var(--#{$variable-prefix}disabled-background-color); - - &::after { - background-color: var(--#{$variable-prefix}disabled-color); - } } @include e(tick) { @@ -80,22 +91,6 @@ } } - @include when(checked) { - @include e(input-wrapper) { - &::after { - opacity: 1; - } - } - } - - @include when(indeterminate) { - @include e(input-wrapper) { - &::after { - opacity: 1; - } - } - } - @include e(input-wrapper) { position: relative; @@ -103,6 +98,8 @@ height: 16px; border-radius: var(--#{$variable-prefix}border-radius); + background-color: var(--#{$variable-prefix}input-background-color); + &::before { position: absolute; top: 0; @@ -124,7 +121,6 @@ right: 0; bottom: 0; left: 0; - z-index: -1; border-radius: var(--#{$variable-prefix}border-radius); @@ -143,6 +139,7 @@ right: 0; bottom: 0; left: 0; + z-index: 1; border-radius: var(--#{$variable-prefix}border-radius); @@ -169,6 +166,7 @@ position: absolute; top: 7px; left: 4px; + z-index: 1; width: 8px; height: 2px; @@ -181,7 +179,7 @@ position: absolute; top: 0; left: 0; - z-index: 1; + z-index: 5; width: 100%; height: 100%; diff --git a/packages/ui/src/styles/components/_drawer.scss b/packages/ui/src/styles/components/_drawer.scss index 150caf81..872e987b 100644 --- a/packages/ui/src/styles/components/_drawer.scss +++ b/packages/ui/src/styles/components/_drawer.scss @@ -9,10 +9,9 @@ height: 100%; background-color: var(--#{$variable-prefix}background-color); + outline: none; box-shadow: 0 8px 40px 0 var(--#{$variable-prefix}shadow-color); - @include utils-outline; - @include m(top) { top: 0; left: 0; diff --git a/packages/ui/src/styles/components/_dropdown.scss b/packages/ui/src/styles/components/_dropdown.scss index d649b41e..d0cbc16e 100644 --- a/packages/ui/src/styles/components/_dropdown.scss +++ b/packages/ui/src/styles/components/_dropdown.scss @@ -16,7 +16,7 @@ $dropdown-item-height: 32px; &:not(.is-disabled) { &:focus, &:hover { - background-color: var(--#{$variable-prefix}color-step-50); + background-color: var(--#{$variable-prefix}hover-background-color); } } diff --git a/packages/ui/src/styles/components/_input.scss b/packages/ui/src/styles/components/_input.scss index 1633879d..e079b4d4 100644 --- a/packages/ui/src/styles/components/_input.scss +++ b/packages/ui/src/styles/components/_input.scss @@ -9,10 +9,13 @@ border: 1px solid var(--#{$variable-prefix}border-color); border-radius: var(--#{$variable-prefix}border-radius); + color: var(--#{$variable-prefix}text-color); font: inherit; font-size: var(--#{$variable-prefix}font); letter-spacing: inherit; + background-color: var(--#{$variable-prefix}input-background-color); + outline: none; transition: border-color 0.2s linear; @@ -61,13 +64,13 @@ } &::placeholder { - color: var(--#{$variable-prefix}color-step-400); + color: rgb(var(--#{$variable-prefix}text-color-rgb) / 40%); transform: translateX(1px); } &:disabled::placeholder { - color: var(--#{$variable-prefix}color-step-100); + color: rgb(var(--#{$variable-prefix}text-color-rgb) / 10%); } @include m(smaller) { @@ -95,6 +98,8 @@ font-size: var(--#{$variable-prefix}font); + background-color: var(--#{$variable-prefix}input-background-color); + transition: border-color 0.2s linear; @include utils-disabled(true); diff --git a/packages/ui/src/styles/components/_radio.scss b/packages/ui/src/styles/components/_radio.scss index f3850296..0bcd01d9 100644 --- a/packages/ui/src/styles/components/_radio.scss +++ b/packages/ui/src/styles/components/_radio.scss @@ -89,7 +89,7 @@ @include when(checked) { @include e(input-wrapper) { &::before { - animation: radio-wave 0.36s ease-in-out; + animation: wave-spread 0.36s ease-in-out; animation-fill-mode: backwards; } } @@ -136,6 +136,8 @@ height: 16px; border-radius: 50%; + background-color: var(--#{$variable-prefix}input-background-color); + &::before { position: absolute; top: 0; diff --git a/packages/ui/src/styles/components/_select-box.scss b/packages/ui/src/styles/components/_select-box.scss index c231b3c2..4c0d7436 100644 --- a/packages/ui/src/styles/components/_select-box.scss +++ b/packages/ui/src/styles/components/_select-box.scss @@ -18,7 +18,7 @@ text-transform: none; vertical-align: top; - background-color: var(--#{$variable-prefix}background-color); + background-color: var(--#{$variable-prefix}input-background-color); outline: none; cursor: pointer; @@ -65,7 +65,7 @@ color: var(--#{$variable-prefix}disabled-color); } .#{$variable-prefix}select-box__placeholder { - color: var(--#{$variable-prefix}color-step-100); + color: rgb(var(--#{$variable-prefix}text-color-rgb) / 10%); } } @@ -103,12 +103,17 @@ padding: 0; border: none; + color: var(--#{$variable-prefix}text-color); + font: inherit; letter-spacing: inherit; + background-color: transparent; + outline: none; appearance: none; + caret-color: var(--#{$variable-prefix}color-primary); &::-webkit-search-cancel-button { display: none; @@ -127,7 +132,7 @@ display: flex; align-items: center; - color: var(--#{$variable-prefix}color-step-400); + color: rgb(var(--#{$variable-prefix}text-color-rgb) / 40%); & > span { @include utils-ellipsis; diff --git a/packages/ui/src/styles/components/_select.scss b/packages/ui/src/styles/components/_select.scss index b22918ef..f5ea678c 100644 --- a/packages/ui/src/styles/components/_select.scss +++ b/packages/ui/src/styles/components/_select.scss @@ -11,14 +11,11 @@ $select-option-height: 32px; @include when(disabled) { .#{$variable-prefix}tag { &.#{$variable-prefix}select__multiple-count { - background-color: var(--#{$variable-prefix}color-step-100); cursor: pointer; } &:not(.#{$variable-prefix}select__multiple-count) { color: var(--#{$variable-prefix}disabled-color); - - background-color: var(--#{$variable-prefix}color-step-70); } } @@ -61,7 +58,7 @@ $select-option-height: 32px; } &:not(.is-selected):hover { - background-color: var(--#{$variable-prefix}color-step-50); + background-color: var(--#{$variable-prefix}hover-background-color); } } diff --git a/packages/ui/src/styles/components/_switch.scss b/packages/ui/src/styles/components/_switch.scss index 0d949501..75f06622 100644 --- a/packages/ui/src/styles/components/_switch.scss +++ b/packages/ui/src/styles/components/_switch.scss @@ -25,7 +25,17 @@ } @include when(disabled) { - filter: saturate(50%) opacity(50%); + color: var(--#{$variable-prefix}disabled-color); + + filter: brightness(110%) grayscale(50%); + + @include when(checked) { + filter: saturate(50%) grayscale(50%); + } + + @include e(state-dot) { + filter: opacity(50%); + } @include e(input) { cursor: not-allowed; @@ -33,7 +43,21 @@ } @include when(loading) { - filter: opacity(50%); + @include e(state-container) { + &::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + + border-radius: inherit; + + background-color: rgb(255 255 255 / 30%); + + content: ''; + } + } @include e(input) { cursor: wait; @@ -79,7 +103,7 @@ padding: 0 6px; border-radius: 11px; - background-color: var(--#{$variable-prefix}color-step-100); + background-color: var(--#{$variable-prefix}switch-background-color); transition: background-color 0.1s ease-out; } diff --git a/packages/ui/src/styles/components/_tag.scss b/packages/ui/src/styles/components/_tag.scss index 6ec0b143..2941dd51 100644 --- a/packages/ui/src/styles/components/_tag.scss +++ b/packages/ui/src/styles/components/_tag.scss @@ -15,7 +15,7 @@ @include m(primary) { color: var(--#{$variable-prefix}tag-color, var(--#{$variable-prefix}text-color)); - background-color: var(--#{$variable-prefix}tag-background-color, var(--#{$variable-prefix}color-step-40)); + background-color: var(--#{$variable-prefix}tag-background-color, var(--#{$variable-prefix}tag-background-color)); } @include m(fill) { diff --git a/packages/ui/src/styles/components/_textarea.scss b/packages/ui/src/styles/components/_textarea.scss index 421ce7c9..01e43bdd 100644 --- a/packages/ui/src/styles/components/_textarea.scss +++ b/packages/ui/src/styles/components/_textarea.scss @@ -7,10 +7,13 @@ border: 1px solid var(--#{$variable-prefix}border-color); border-radius: var(--#{$variable-prefix}border-radius); + color: var(--#{$variable-prefix}text-color); font: inherit; line-height: 24px; letter-spacing: inherit; + background-color: var(--#{$variable-prefix}input-background-color); + outline: none; transition: border-color 0.2s linear; @@ -38,13 +41,13 @@ } &::placeholder { - color: var(--#{$variable-prefix}color-step-400); + color: rgb(var(--#{$variable-prefix}text-color-rgb) / 40%); transform: translateX(1px); } &:disabled::placeholder { - color: var(--#{$variable-prefix}color-step-100); + color: rgb(var(--#{$variable-prefix}text-color-rgb) / 10%); } @include e(count) { diff --git a/packages/ui/src/styles/index.scss b/packages/ui/src/styles/index.scss index 68353c94..df1b588d 100644 --- a/packages/ui/src/styles/index.scss +++ b/packages/ui/src/styles/index.scss @@ -1,6 +1,8 @@ @use 'sass:color'; + @import 'variables'; @import 'mixins'; @import 'animations'; @import 'reboot'; + @import 'components'; diff --git a/packages/ui/src/styles/theme-dark.scss b/packages/ui/src/styles/theme-dark.scss new file mode 100644 index 00000000..34d39d5a --- /dev/null +++ b/packages/ui/src/styles/theme-dark.scss @@ -0,0 +1,89 @@ +/* stylelint-disable scss/operator-no-unspaced */ +/* stylelint-disable declaration-property-value-allowed-list */ +@use 'sass:color'; + +$dark-themes: ( + 'primary': 94 124 224, + 'success': 47 223 117, + 'warning': 255 213 52, + 'danger': 255 73 97, +) !default; + +body.dark { + /** basic **/ + --#{$variable-prefix}text-color: rgb(205 205 205); + --#{$variable-prefix}text-color-rgb: 205 205 205; + --#{$variable-prefix}background-color: rgb(31 31 31); + --#{$variable-prefix}background-color-rgb: 31 31 31; + --#{$variable-prefix}shadow-color: rgb(0 0 0 / 48%); + --#{$variable-prefix}divider-color: #303030; + --#{$variable-prefix}border-color: #434343; + --#{$variable-prefix}indicator-background-color: #3d3e40; + --#{$variable-prefix}disabled-background-color: #2c2c2c; + --#{$variable-prefix}disabled-color: #4e4e50; + --#{$variable-prefix}hover-background-color: rgb(255 255 255 / 6%); + --#{$variable-prefix}input-background-color: #121212; + + /** step **/ + --#{$variable-prefix}color-step-10: hsl(0deg 0% 1%); + --#{$variable-prefix}color-step-20: hsl(0deg 0% 2%); + --#{$variable-prefix}color-step-30: hsl(0deg 0% 3%); + --#{$variable-prefix}color-step-40: hsl(0deg 0% 4%); + --#{$variable-prefix}color-step-50: hsl(0deg 0% 5%); + --#{$variable-prefix}color-step-60: hsl(0deg 0% 6%); + --#{$variable-prefix}color-step-70: hsl(0deg 0% 7%); + --#{$variable-prefix}color-step-80: hsl(0deg 0% 8%); + --#{$variable-prefix}color-step-90: hsl(0deg 0% 9%); + --#{$variable-prefix}color-step-100: hsl(0deg 0% 10%); + --#{$variable-prefix}color-step-150: hsl(0deg 0% 15%); + --#{$variable-prefix}color-step-200: hsl(0deg 0% 20%); + --#{$variable-prefix}color-step-250: hsl(0deg 0% 25%); + --#{$variable-prefix}color-step-300: hsl(0deg 0% 30%); + --#{$variable-prefix}color-step-350: hsl(0deg 0% 35%); + --#{$variable-prefix}color-step-400: hsl(0deg 0% 40%); + --#{$variable-prefix}color-step-450: hsl(0deg 0% 45%); + --#{$variable-prefix}color-step-500: hsl(0deg 0% 50%); + --#{$variable-prefix}color-step-550: hsl(0deg 0% 55%); + --#{$variable-prefix}color-step-600: hsl(0deg 0% 60%); + --#{$variable-prefix}color-step-650: hsl(0deg 0% 65%); + --#{$variable-prefix}color-step-700: hsl(0deg 0% 70%); + --#{$variable-prefix}color-step-750: hsl(0deg 0% 75%); + --#{$variable-prefix}color-step-800: hsl(0deg 0% 80%); + --#{$variable-prefix}color-step-850: hsl(0deg 0% 85%); + --#{$variable-prefix}color-step-900: hsl(0deg 0% 90%); + --#{$variable-prefix}color-step-950: hsl(0deg 0% 95%); + + @each $theme, $rgb in $dark-themes { + /** rgb **/ + --#{$variable-prefix}color-#{$theme}-rgb: #{$rgb}; + + /** theme **/ + --#{$variable-prefix}color-#{$theme}: rgb(#{$rgb}); + + /** lighter **/ + --#{$variable-prefix}color-#{$theme}-lighter: #{color.scale(rgb($rgb), $lightness: 30%)}; + + /** darker **/ + --#{$variable-prefix}color-#{$theme}-darker: #{color.scale(rgb($rgb), $lightness: -10%, $saturation: -10%)}; + + /** background **/ + --#{$variable-prefix}color-#{$theme}-background: #{color.scale(rgb($rgb), $alpha: -85%)}; + --#{$variable-prefix}color-#{$theme}-background-1: #{color.scale(rgb($rgb), $alpha: -86%)}; + --#{$variable-prefix}color-#{$theme}-background-2: #{color.scale(rgb($rgb), $alpha: -87%)}; + --#{$variable-prefix}color-#{$theme}-background-3: #{color.scale(rgb($rgb), $alpha: -88%)}; + --#{$variable-prefix}color-#{$theme}-background-4: #{color.scale(rgb($rgb), $alpha: -89%)}; + --#{$variable-prefix}color-#{$theme}-background-5: #{color.scale(rgb($rgb), $alpha: -90%)}; + --#{$variable-prefix}color-#{$theme}-background-6: #{color.scale(rgb($rgb), $alpha: -91%)}; + --#{$variable-prefix}color-#{$theme}-background-7: #{color.scale(rgb($rgb), $alpha: -92%)}; + --#{$variable-prefix}color-#{$theme}-background-8: #{color.scale(rgb($rgb), $alpha: -93%)}; + --#{$variable-prefix}color-#{$theme}-background-9: #{color.scale(rgb($rgb), $alpha: -94%)}; + } + + /** component **/ + --#{$variable-prefix}tooltip-text-color: #d0d2d7; + --#{$variable-prefix}tooltip-background-color: #686a72; + --#{$variable-prefix}mask-background-color: rgb(0 0 0 / 40%); + --#{$variable-prefix}empty-color: #868a93; + --#{$variable-prefix}switch-background-color: #5f6164; + --#{$variable-prefix}tag-background-color: rgb(255 255 255 / 10%); +} diff --git a/packages/ui/src/utils/color.ts b/packages/ui/src/utils/color.ts index c7afa9de..30251cb8 100644 --- a/packages/ui/src/utils/color.ts +++ b/packages/ui/src/utils/color.ts @@ -27,3 +27,22 @@ export const pSBC=(p,c0,c1?:any,l?:any)=>{ if(h)return"rgb"+(f?"a(":"(")+r+","+g+","+b+(f?","+m(a*1000)/1000:"")+")"; else return"#"+(4294967296+r*16777216+g*65536+b*256+(f?m(a*255):0)).toString(16).slice(1,f?undefined:-2) } + +export function convertHex(hexCode, opacity = 1){ + var hex = hexCode.replace('#', ''); + + if (hex.length === 3) { + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + } + + var r = parseInt(hex.substring(0,2), 16), + g = parseInt(hex.substring(2,4), 16), + b = parseInt(hex.substring(4,6), 16); + + /* Backward compatibility for whole number based opacity values. */ + if (opacity > 1 && opacity <= 100) { + opacity = opacity / 100; + } + + return 'rgba('+r+','+g+','+b+','+opacity+')'; +} diff --git a/packages/ui/src/utils/index.ts b/packages/ui/src/utils/index.ts index f266b777..28995284 100644 --- a/packages/ui/src/utils/index.ts +++ b/packages/ui/src/utils/index.ts @@ -1,5 +1,5 @@ export { getClassName } from './class-name'; -export { pSBC } from './color'; +export { pSBC, convertHex } from './color'; export { copy } from './copy'; export { getFragmentChildren } from './fragment-children'; export { mergeStyle } from './merge-style';