From 66256ef2e19425c36295f97a9bb6e71535d8c74b Mon Sep 17 00:00:00 2001 From: yuanyxh <15766118362@139.com> Date: Wed, 14 Aug 2024 23:36:50 +0800 Subject: [PATCH] feat: Modify markdown editor style --- src/assets/iconfont/md-editor/iconfont.css | 96 ++++++ src/assets/iconfont/md-editor/iconfont.ttf | Bin 0 -> 4604 bytes src/assets/iconfont/md-editor/iconfont.woff | Bin 0 -> 3064 bytes src/assets/iconfont/md-editor/iconfont.woff2 | Bin 0 -> 2276 bytes src/components/Dialog/Dialog.module.less | 2 +- src/components/Dialog/Dialog.tsx | 2 +- src/filehandle/components/FileSideMenu.tsx | 18 +- .../styles/FileSideMenu.module.less | 5 +- .../md_editor/component/MDContent.tsx | 28 +- .../md_editor/component/MDHandle.tsx | 7 +- .../component/styles/MDContent.module.less | 29 +- .../component/styles/MDEditor.module.less | 54 +++- src/tools/json2typescript/Index.tsx | 59 ++-- src/tools/json2typescript/JSON2TypeScript.ts | 279 ++++++++---------- src/variables.less | 2 + 15 files changed, 362 insertions(+), 219 deletions(-) create mode 100644 src/assets/iconfont/md-editor/iconfont.css create mode 100644 src/assets/iconfont/md-editor/iconfont.ttf create mode 100644 src/assets/iconfont/md-editor/iconfont.woff create mode 100644 src/assets/iconfont/md-editor/iconfont.woff2 diff --git a/src/assets/iconfont/md-editor/iconfont.css b/src/assets/iconfont/md-editor/iconfont.css new file mode 100644 index 0000000..4f1455d --- /dev/null +++ b/src/assets/iconfont/md-editor/iconfont.css @@ -0,0 +1,96 @@ +@font-face { + font-family: 'iconfont'; /* Project id 4145942 */ + /* Color fonts */ + src: + url('iconfont.woff2?t=1689582142318') format('woff2'), + url('iconfont.woff?t=1689582142318') format('woff'), + url('iconfont.ttf?t=1689582142318') format('truetype'); +} + +.iconfont { + font-family: 'iconfont' !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-dian:before { + content: '\e640'; +} + +.icon-xuanzeyixuan:before { + content: '\e63c'; +} + +.icon-danger:before { + content: '\e614'; +} + +.icon-Success:before { + content: '\e605'; +} + +.icon-warning:before { + content: '\e600'; +} + +.icon-info:before { + content: '\e601'; +} + +.icon-dingwei:before { + content: '\e650'; +} + +.icon-wenjian:before { + content: '\e652'; +} + +.icon-shuju:before { + content: '\e653'; +} + +.icon-biaoqian:before { + content: '\e64a'; +} + +.icon-biaoqing:before { + content: '\e64b'; +} + +.icon-jinggao:before { + content: '\e64c'; +} + +.icon-dianzan:before { + content: '\e64d'; +} + +.icon-xiangqing:before { + content: '\e64e'; +} + +.icon-tishi:before { + content: '\e64f'; +} + +.icon-bangzhu:before { + content: '\e651'; +} + +.icon-wenjianjia:before { + content: '\e652'; +} + +.icon-touxiang:before { + content: '\e626'; +} + +.icon-jiedian:before { + content: '\e649'; +} + +.icon-cengji:before { + content: '\e67f'; +} diff --git a/src/assets/iconfont/md-editor/iconfont.ttf b/src/assets/iconfont/md-editor/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ac2580d005c5a501a74d8450b77bf0157fa5b217 GIT binary patch literal 4604 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 literal 0 HcmV?d00001 diff --git a/src/assets/iconfont/md-editor/iconfont.woff b/src/assets/iconfont/md-editor/iconfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..fc6f659e569c4f1318cf0f18be4dcbd017cd10eb GIT binary patch literal 3064 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 literal 0 HcmV?d00001 diff --git a/src/assets/iconfont/md-editor/iconfont.woff2 b/src/assets/iconfont/md-editor/iconfont.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..78f25549261c1b0b68519dfa509aa960b6924388 GIT binary patch literal 2276 zcmVMybPuE`KN9DeawLV85U88-oUSo4YFa?RxqFq;=sPhM0U78dKt*)o@3#a9FwcMUfw2E^zgBOUKkz7;35`VQl(Ow~XZ|_N zJ!z;OMJ4hR2)4G84{)U#_Vv$CKgH+)lRUR%)JUUk2`Uw<+-;u^_{?@4! zoYsLeMdkyHvll{qtXYA>i8^qR@e{_E;~MkJ5+ngA0j326lUZJ01Ym|`1r!9_ z%u?IS@z1Flyz=2>`P^3tU*&yO^puy8stq3rR->*VeQJ~$B*U-ECx(ZHdxmR<^)0n6 zWEMouhCD!tfIN0)nhjtuh!pG%WK6;0u>C=)05MAlp%Ney=Tb+iIhy7aN)@NksZ?sC zTB%?IS|e9-YLzM~+D|b@DOFJ|r`D0WM4Vbf(`pZgBsyc1rn7CtqGr+pzNEcl3lr40 zZ92?GioH6rVH$*kEW5XtkU)rGf(KB&QM<#wfjc$u1euXX##0 zV@juzd*j>kXT^ z=1p-yCa868AX{}CSy99Lx3c0Qu>+B^5S&wR@FOR4P1_j$ z&FLK_6C?Ln!rt%XW`+FAtXO!Ju)Vr)`_c4{BX;IgYTG6d!El(37CYLbI;*FC6N)fs z4CY;eti&@$h`ASs)NUkXNBR|p*=l;*`IggORWGl7GwpEZu7Q~YM9q4A)i!1>JqrOF z2o>NueafM73gOj?4PPf6vH`RzY$|Jqhq0JuhGJz5SkJ!TFDvUT$s8BPU;b>@+axf% zc59+{fAT?n)uuRiPfEz^ayTBBY9f~*q`olrfPNFekbtSzrJH#&V`MQnCQvx-WvbRg z;CjYHFBQd3=awss>d%WjV2FIjYfM`tt(KDr-V^1qWOHEXN-Nr^t=y*FdkD3oW^)*; zP{~<3Vw@ZKiKz4LCxL{feFJz32=SivOaMh zY*hZbQ2qu`;T0<2#YRLI*mJl?-Q(9CSC$nQmhsmvr8d81%*;JM3fnS1-V=$D`U^_7W)Xns0<{UZ(a3A{iiq2y7Q_o z3VEjFvcy%)Vo5A3ODJ_|Qty{+NiHi*O!_lvpC##FQleq24l~tuvhVMc|7YOe|3_9{ zI`7pPE0>SHw4{9L=xf60>oBems$v%UV|KPLJlq%a)GpWLUy{ue!ot8RQML2un4e;_ z>83C8`xmWIilgQDV$u6?v-mQ(GjeTYloLx5#V7}T!5W+R9KI|krwohd4s*MQ=jICc z!!ah)(G@bUn6mKIuvZtFpPzC{4_&vIt+vLVJZN4qSq(qIa@tknI_`8i5lFW44%?v| zhr_-vBQLMZ5wa-dkKLG2aL3^`)eI@K)IXP`zrx!bI9)d0)R;8z*B>7*(7g1L%@Oj% zB}!Ntb@5@;p~y!UqcGwGpOW%sTx6^>HZm>*)iqux;0!sJEyi0ox^f;k-r1{91=6x= zB08zEG`%veJ)dr@H+t>H`ZY08ZSI;%4(6Udm6vyl^LwNw<5rRN_@(ONXHS}xla$Hd zDl103SZRvm9m%%o!!st0{jYDz= z-={mFlzV|IO&F0`-`&;yZT+ahb=Yi3xtQX!j2v6aMT^hZ7`o4nDSjO+cB;jijpWiv zdlL>N>`f|mzwFI6pAGQi#Vx)qkjk+ur@uH_ugjhO&e*ZqC|9Q+J^jU%F@L3=kS}ro z!{@BW;>CAozmYY4(K~k+FP{GPUGJl*FW!9{NI(jJFf&dnfY`nWfJeGuJ4pycJ=|*M z&YG6Sh`c|;jlO1n@?Pk&y`>}x{)iF)C=^G2VS$3VX!?rO=b;}deO4A3t?Q+~Y*$b_ z`)D(U&`D$;4UCNv76XW{;*sj8UgpF9p^=94A1&lI7q2xA9-xf$Hm?c_Bpf+=foLr2@1f7+;trqVs?cQoubY|uxd2=xjEzsTELWfv&6hv&&NwESxjzup3 literal 0 HcmV?d00001 diff --git a/src/components/Dialog/Dialog.module.less b/src/components/Dialog/Dialog.module.less index 967fd0e..cf4ef66 100644 --- a/src/components/Dialog/Dialog.module.less +++ b/src/components/Dialog/Dialog.module.less @@ -31,7 +31,7 @@ left: 0; display: flex; width: 100%; - height: 30px; + height: 40px; } .header .bar { diff --git a/src/components/Dialog/Dialog.tsx b/src/components/Dialog/Dialog.tsx index 45342ee..483ce88 100644 --- a/src/components/Dialog/Dialog.tsx +++ b/src/components/Dialog/Dialog.tsx @@ -198,7 +198,7 @@ const Dialog = forwardRef>(function Dialog return ( <> -
+
{item.type === FileType.DIRECTORY ? ( - + <> + + + ) : null} {item.name} diff --git a/src/filehandle/components/styles/FileSideMenu.module.less b/src/filehandle/components/styles/FileSideMenu.module.less index b31384d..8dc6762 100644 --- a/src/filehandle/components/styles/FileSideMenu.module.less +++ b/src/filehandle/components/styles/FileSideMenu.module.less @@ -32,11 +32,11 @@ user-select: none; span { - margin-left: 8px; + margin-left: 18px; } .directoryIcon + span { - margin-left: 0; + margin-left: 3px; } > .list { @@ -63,6 +63,7 @@ } .list .item .row { + padding-block: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; diff --git a/src/filehandle/md_editor/component/MDContent.tsx b/src/filehandle/md_editor/component/MDContent.tsx index 8e33dcd..931f7b9 100644 --- a/src/filehandle/md_editor/component/MDContent.tsx +++ b/src/filehandle/md_editor/component/MDContent.tsx @@ -1,3 +1,4 @@ +import type { HTMLAttributes } from 'react'; import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react'; import { addGlobalListener, confirm, error } from '@/utils'; @@ -11,7 +12,7 @@ import type { IMDEditorExpose } from './MDEditor'; import MDEditor from './MDEditor'; import styles from './styles/MDContent.module.less'; -interface IMDContentProps { +interface IMDContentProps extends HTMLAttributes { handle: DH | FH; update(): void; } @@ -22,7 +23,7 @@ export interface IMDContentExpose { export const MDContent = forwardRef( function MDContent(props, ref) { - const { handle, update } = props; + const { handle, update, ...rest } = props; const [changed, setChanged] = useState(false); const [currentHandle, setCurrentHandle] = useState(null); @@ -127,7 +128,7 @@ export const MDContent = forwardRef( }; return ( -
+
{isDirectoryHandle(handle) ? ( ( ) : null}
- +
+ {currentHandle?.name} + {changed ? - 已编辑 : null} +
+ +
+ +
); diff --git a/src/filehandle/md_editor/component/MDHandle.tsx b/src/filehandle/md_editor/component/MDHandle.tsx index b478847..41aad27 100644 --- a/src/filehandle/md_editor/component/MDHandle.tsx +++ b/src/filehandle/md_editor/component/MDHandle.tsx @@ -177,7 +177,12 @@ const MDHandle: React.FC = (props) => { onMinimize={handleMinimize} onClose={onClose} > - + ); }; diff --git a/src/filehandle/md_editor/component/styles/MDContent.module.less b/src/filehandle/md_editor/component/styles/MDContent.module.less index de4ac16..d07a0c9 100644 --- a/src/filehandle/md_editor/component/styles/MDContent.module.less +++ b/src/filehandle/md_editor/component/styles/MDContent.module.less @@ -7,8 +7,35 @@ } .mdEditor { + position: relative; + padding: 0 50px 30px; flex: 1; height: 100%; - padding: 30px; overflow-y: auto; + background-color: rgb(199, 229, 252); +} + +.editStatus { + position: sticky; + top: 0; + height: 45px; + background-color: rgb(199, 229, 252); + text-align: center; + line-height: 45px; + font-weight: 700; + z-index: var(--z-normal); +} + +.changed { + color: var(--color-info); +} + +.editorWrapper { + margin: 4px auto; + max-width: 1140px; + padding: 30px; + background-color: #fff; + min-height: 100%; + border-radius: var(--border-radius-base); + box-shadow: 0 0 1px 4px #495060; } diff --git a/src/filehandle/md_editor/component/styles/MDEditor.module.less b/src/filehandle/md_editor/component/styles/MDEditor.module.less index f30dfd2..6f72899 100644 --- a/src/filehandle/md_editor/component/styles/MDEditor.module.less +++ b/src/filehandle/md_editor/component/styles/MDEditor.module.less @@ -1,3 +1,5 @@ +@import url('@/assets/iconfont/md-editor/iconfont.css'); + .editorContainer { :global(.milkdown) { height: 100%; @@ -47,17 +49,21 @@ h5, h6 { margin-bottom: 1em; + width: max-content; font-weight: 600; } h1 { + width: 100%; font-size: 38px; line-height: 1.21; + text-align: center; } h2 { font-size: 30px; line-height: 1.266; + border-bottom: 3px solid #fe5f58; } h3 { @@ -102,6 +108,25 @@ } } + h1::before { + margin-right: 3px; + font-family: 'iconfont'; + content: '\e626'; + vertical-align: middle; + } + + h2::before { + margin-right: 3px; + content: '#'; + color: #fe5f58; + } + + h3::before { + margin-right: 8px; + font-family: 'iconfont'; + content: '\e67f'; + } + strong { font-weight: 600; } @@ -188,7 +213,7 @@ } ul { - list-style: initial; + list-style: none; } // li[data-checked='false']::before { @@ -199,6 +224,26 @@ // content: 'done'; // } + li { + position: relative; + } + + li::before { + position: absolute; + top: 8px; + left: -20px; + display: inline-block; + content: ''; + width: 8px; + height: 8px; + text-align: center; + vertical-align: middle; + color: #000; + background-color: #fff; + border: 2px solid #fe5f58; + border-radius: 50%; + } + pre { position: relative; z-index: var(--z-ignore); @@ -238,9 +283,12 @@ } img { + margin: 0 auto; display: block; - max-width: 598px; - text-align: center; + max-width: 720px; + height: auto; + box-shadow: 0 0 5px 0px rgba(0, 0, 0, 0.18); + object-fit: cover; } a { diff --git a/src/tools/json2typescript/Index.tsx b/src/tools/json2typescript/Index.tsx index d60b81b..8c1540b 100644 --- a/src/tools/json2typescript/Index.tsx +++ b/src/tools/json2typescript/Index.tsx @@ -1,44 +1,35 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import style from './Index.module.less'; -import { createType, generate } from './JSON2TypeScript'; +import { json2ts } from './JSON2TypeScript'; import Editor from '@monaco-editor/react'; -// const transform = (obj: any) => { -// const type = typeof obj; - -// switch (type) { -// case 'string': -// case 'number': -// case 'bigint': -// case 'boolean': -// case 'object': -// } -// } - -const json2ts = (json: string) => { - try { - const obj = JSON.parse(json); - - console.log(createType(obj)); - - return generate(createType(obj)); - } catch (err) { - console.log(err); - - return void 0; - } -}; - const JSON2TypeScript: React.FC = () => { const [typescript, setTypeScript] = useState(''); + useEffect(() => { + handleChange(`{ + "userId": 1, + "id": 1, + "title": "delectus aut autem", + "completed": false +}`); + }, []); + const handleChange = (e: string | undefined) => { - const ts = json2ts(e || ''); + try { + const obj = JSON.parse(e || ''); + + const ts = json2ts(obj); + + // console.log(ts); - if (typeof ts === 'string') { - setTypeScript(ts); + if (typeof ts === 'string') { + setTypeScript(ts); + } + } catch (err) { + // console.log(err); } }; @@ -49,6 +40,12 @@ const JSON2TypeScript: React.FC = () => { diff --git a/src/tools/json2typescript/JSON2TypeScript.ts b/src/tools/json2typescript/JSON2TypeScript.ts index 91ec9a2..16e227d 100644 --- a/src/tools/json2typescript/JSON2TypeScript.ts +++ b/src/tools/json2typescript/JSON2TypeScript.ts @@ -1,202 +1,155 @@ -import { isArray, isBoolean, isNull, isNumber, isObject, isString, upperFirst } from 'lodash-es'; +import { isArray, isNull, isObject } from 'lodash-es'; -type type = 'string' | 'number' | 'boolean' | 'null' | Record | Type[]; +type BaseType = 'string' | 'number' | 'boolean' | 'null' | 'any' | JointType; + +type JointType = Record; type Type = { - type: type; - require: boolean; + type: BaseType; + required: boolean; + count?: number; }; const createStringType = (): Type => { - return { type: 'string', require: true }; + return { type: 'string', required: true }; }; const createNumberType = (): Type => { - return { type: 'number', require: true }; + return { type: 'number', required: true }; }; const createBooleanType = (): Type => { - return { type: 'boolean', require: true }; + return { type: 'boolean', required: true }; }; const createNullType = (): Type => { - return { type: 'null', require: true }; + return { type: 'null', required: true }; }; -const createObjectType = (data: Record): Type => { - const keys = Object.keys(data); - - const companion: Record = {}; - - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - - companion[key] = createType(data[key]); +/** + * + * @param obj 需要检索类型的对象 + * @param sibling 可选的同级类型 + * @returns 返回对象类型 + */ +function createObjectType(obj: Record, sibling?: BaseType): Type { + // 如果有同级类型,且同级类型不是对象,则返回 any + if (sibling && (typeof sibling === 'string' || isArray(sibling))) { + return { type: 'any', required: true }; } - return { type: companion, require: true }; -}; - -const createArrayType = (data: any[]): Type => { - const companion: Type[] = []; - - for (let i = 0; i < data.length; i++) { - const curr = data[i]; + const names = Object.getOwnPropertyNames(obj); + const oldNames = sibling ? Object.getOwnPropertyNames(sibling) : []; - companion.push(createType(curr)); - } + const typeObj: JointType = sibling || {}; - return { type: companion, require: true }; -}; + const merge = (t: Type, name: string) => { + // 没有同级类型,不做特殊处理 + if (!sibling) { + return (typeObj[name] = t); + } -export function createType(data: any) { - let type!: Type; + // 存在同级类型,但没有相同属性,标记为可选 + const oldType = typeObj[name]; + if (!oldType) { + t.required = false; + return (typeObj[name] = t); + } - switch (true) { - case isString(data): - type = createStringType(); - break; - case isNumber(data): - type = createNumberType(); - break; - case isNull(data): - type = createNullType(); - break; - case isBoolean(data): - type = createBooleanType(); - break; - case isArray(data): - type = createArrayType(data); - break; - case isObject(data): - type = createObjectType(data); - break; + // 类型不一致,标记为 any + if (oldType.type !== t.type) { + oldType.type = 'any'; + } + }; + + for (let i = 0; i < names.length; i++) { + const name = names[i]; + + const value = obj[name]; + const type = typeof value; + + switch (type) { + case 'string': + merge(createStringType(), name); + break; + case 'number': + merge(createNumberType(), name); + break; + case 'boolean': + merge(createBooleanType(), name); + break; + default: + if (isNull(value)) { + merge(createNullType(), name); + } else if (isArray(value)) { + merge(createArrayType(value), name); + } else if (isObject(value)) { + // 如果存在同级元素,将它向下传递 + merge(createObjectType(value, typeObj[name]?.type), name); + } + } } - return type; -} - -export function generate(tree: Type) { - const typeStr: string[] = []; - - const names = new Map(); - - const generateString = () => 'string;\n'; - const generateNumber = () => 'number;\n'; - const generateBoolean = () => 'boolean;\n'; - const generateNull = () => 'null;\n'; - - function getName(key: string) { - let typeName = key; + // obj 中如果没有 sibling 的属性,需要标记为可选 + oldNames + .filter((o) => !names.includes(o)) + .forEach((o) => { + typeObj[o].required = false; + }); - if (!Number.isNaN(window.parseInt(typeName))) { - const name = 'N' + typeName; - - let count = names.get(name); - - if (typeof count === 'number') { - typeName = name.padStart(name.length + ++count, 'N'); - - names.set(name, count); - } else { - typeName = name; - - names.set(name, 0); - } - } else { - let count = names.get(typeName); - - if (typeof count === 'number') { - count++; + return { type: typeObj, required: true }; +} - typeName += count; +function createArrayType(array: any[]): Type { + let type!: Type; - names.set(typeName, count); - } else { - names.set(typeName, 0); - } + for (let i = 0; i < array.length; i++) { + const ele = array[i]; + + const eleType = typeof ele; + + switch (eleType) { + case 'string': + createStringType(); + break; + case 'number': + createNumberType(); + break; + case 'boolean': + createBooleanType(); + break; + default: + if (isNull(ele)) { + createNullType(); + } else if (isArray(ele)) { + createArrayType(ele); + } else if (isObject(ele)) { + createObjectType(ele); + } } - - typeName = upperFirst(typeName); - - return typeName; } - function generateObject(data: Record, name?: string) { - let type = '{\n'; - - const keys = Object.keys(data); - - for (let i = 0; i < keys.length; i++) { - const key = keys[i] as keyof typeof data; - const prop = data[key]; - - const typeName = getName(key); - - switch (prop.type) { - case 'string': - type += ` ${key}: ${generateString()}`; - break; - case 'number': - type += ` ${key}: ${generateNumber()}`; - break; - case 'null': - type += ` ${key}: ${generateNull()}`; - break; - case 'boolean': - type += ` ${key}: ${generateBoolean()}`; - break; - default: - if (isArray(prop.type)) { - generateArray(prop.type, typeName); - - type += ` ${key}: ${typeName};\n`; - } else if (isObject(prop.type)) { - generateObject(prop.type, typeName); - - type += ` ${key}: ${typeName};\n`; - } - } - } - - if (!name) { - return typeStr.push(`export interface Root ${type}}`); - } + return type; +} - typeStr.push(`export interface ${name} ${type}}`); +export function transform(json: Record | any[]) { + if (isArray(json)) { + return createArrayType(json); + } else if (isObject(json)) { + return createObjectType(json); } - function generateArray(data: Type[], name?: string) { - let type = ''; - - if (data.length === 0) { - type += 'any[];\n'; - } else if (data.every((e) => e.type === 'string')) { - type += 'string[];\n'; - } else if (data.every((e) => e.type === 'number')) { - type += 'string[];\n'; - } else if (data.every((e) => e.type === 'boolean')) { - type += 'boolean[];\n'; - } else if (data.every((e) => e.type === 'null')) { - type += 'null[];\n'; - } else { - // for (let i = 0; i < data.length; i++) { - // const element = data[i]; - // } - } + throw new Error('Invail type of the json.'); +} - if (!name) { - return `export type Root = ` + type; - } +export const getTag = (count: number) => { + return '[]'.repeat(count); +}; - typeStr.push(`type ${name} = ${type}[];\n`); - } +export function json2ts(json: Record | any[]) { + const tree = transform(json); - if (isArray(tree.type)) { - generateArray(tree.type); - } else if (isObject(tree.type)) { - generateObject(tree.type); - } + console.log(tree); - return typeStr.reverse().join('\n\n'); + return ''; } diff --git a/src/variables.less b/src/variables.less index ccb5c70..b7a9777 100644 --- a/src/variables.less +++ b/src/variables.less @@ -20,6 +20,7 @@ 'Microsoft YaHei', simsun, sans-serif; --font-family-code: consolas, monaco, 'Andale Mono', 'Ubuntu Mono', monospace; --border-radius-base: 5px; + --border-color-primary: #d9d9d9ff; } :root[mode='dark'] { @@ -27,6 +28,7 @@ --color-primary-light: #dccec6; --color-info: #a9b0b7; --color-info-light: #cdcdcd; + --border-color-primary: #424242ff; --text-color-primary: #d9d9d9; --background-color: #202020; --mask-color: rgb(0 0 0 / 40%);