From b4f5d5d7c026563840d59be3cd12ef1f204e2737 Mon Sep 17 00:00:00 2001 From: folinhilo Date: Tue, 23 Jun 2026 00:44:16 +0800 Subject: [PATCH] mm --- packages/css/package.json | 37 +++ packages/css/scripts/gen-index.ts | 254 ++++++++++++++++++ .../src/styles => css/src}/base/root.css | 101 ++++--- packages/css/src/index.css | 52 ++++ packages/css/src/index.ts | 10 + packages/css/src/recipes/badgeSizeRecipe.ts | 23 ++ .../src/recipes/brandRecipe.ts | 2 +- packages/css/src/recipes/dotSizeRecipe.ts | 13 + packages/css/src/recipes/inlineSizeRecipe.ts | 20 ++ .../src/recipes/itemSizeRecipe.ts | 28 +- .../src/recipes/itemVariantRecipe.ts} | 18 +- packages/css/src/recipes/tabVariantRecipe.ts | 14 + .../align-content.css | 0 .../utility-size-insensitive}/align-items.css | 0 .../utility-size-insensitive}/align-self.css | 0 .../utility-size-insensitive}/animation.css | 0 .../utility-size-insensitive/background.css | 5 + .../box-decoration.css | 0 .../utility-size-insensitive}/box-inside.css | 0 .../utility-size-insensitive}/box-sizing.css | 0 .../src/utility-size-insensitive}/brand.css | 0 .../utility-size-insensitive}/break-after.css | 0 .../break-before.css | 0 .../src/utility-size-insensitive/color.css | 5 + .../src/utility-size-insensitive}/cursor.css | 0 .../src/utility-size-insensitive}/display.css | 0 .../utility-size-insensitive}/drop-shadow.css | 0 .../flex-direction.css | 0 .../utility-size-insensitive}/flex-wrap.css | 0 .../utility-size-insensitive}/font-family.css | 0 .../justify-content.css | 0 .../justify-items.css | 0 .../justify-self.css | 0 .../utility-size-insensitive}/overflow.css | 0 .../overscroll-behavior.css | 0 .../utility-size-insensitive}/position.css | 0 .../screen-reader.css | 0 .../src/utility-size-insensitive}/theme.css | 0 .../utility-size-insensitive}/user-select.css | 0 .../variant-can-hover.css | 51 ++++ .../variant-disabled.css | 89 ++++++ .../variant-non-clickable.css | 55 ++++ .../src/utility-size-insensitive/variant.css | 98 +++++++ .../utility-size-insensitive}/visibility.css | 0 .../src/utility-size-insensitive}/z-index.css | 0 .../utility-size-sensitive}/border-radius.css | 3 + .../font-size-addon.css | 22 ++ .../src/utility-size-sensitive/font-size.css | 30 +++ .../utility-size-sensitive/font-weight.css | 44 +++ .../css/src/utility-size-sensitive/gap.css | 23 ++ .../utility-size-sensitive/height-addon.css | 14 + .../src/utility-size-sensitive/height-dot.css | 14 + .../utility-size-sensitive/height-inline.css | 25 ++ .../utility-size-sensitive/height-item.css | 23 ++ .../src/utility-size-sensitive}/margin.css | 10 +- .../src/utility-size-sensitive/min-width.css | 26 ++ .../utility-size-sensitive/padding-addon.css | 14 + .../utility-size-sensitive/padding-long.css | 20 ++ .../src/utility-size-sensitive}/padding.css | 53 +--- .../utility-size-sensitive/width-addon.css | 14 + .../src/utility-size-sensitive/width-dot.css | 14 + .../utility-size-sensitive/width-inline.css | 25 ++ .../utility-size-sensitive/width-item.css} | 25 -- .../src/styles => css/src}/utils/cpm.ts | 0 .../src/styles => css/src}/utils/cvr.ts | 0 packages/css/tsconfig.build.json | 41 +++ packages/css/tsconfig.json | 30 +++ packages/css/vite.config.ts | 38 +++ packages/ui-react/package.json | 4 +- packages/ui-react/src/assets/svg/CloseSvg.tsx | 12 + .../ui-react/src/componnets/Badge/Badge.tsx | 61 +++++ .../ui-react/src/componnets/Button/Button.tsx | 7 +- .../ui-react/src/componnets/Icon/Icon.tsx | 28 +- packages/ui-react/src/componnets/Tag/Tag.tsx | 62 +++++ packages/ui-react/src/index.css | 3 + packages/ui-react/src/index.ts | 10 +- .../ui-react/src/recipes/inlineSizeRecipe.ts | 15 -- .../utility/size-insensitive/variant.css | 206 -------------- .../utility/size-sensitive/font-size.css | 38 --- .../utility/size-sensitive/font-weight.css | 20 -- .../src/styles/utility/size-sensitive/gap.css | 23 -- .../styles/utility/size-sensitive/height.css | 58 ---- packages/ui-react/src/utils/CommonProps.ts | 8 + .../ui-react/src/utils/downSizeSmTo2xl.ts | 11 + .../ui-react/src/utils/useSlotsRegistry.ts | 69 ----- playground/ui-gallery/src/App.tsx | 4 + playground/ui-gallery/src/common/OW.tsx | 1 + .../ui-gallery/src/gallery/BadgeGallery.tsx | 38 +++ .../ui-gallery/src/gallery/ButtonGallery.tsx | 40 ++- .../ui-gallery/src/gallery/TagGallery.tsx | 18 ++ pnpm-lock.yaml | 21 ++ 91 files changed, 1566 insertions(+), 574 deletions(-) create mode 100644 packages/css/package.json create mode 100644 packages/css/scripts/gen-index.ts rename packages/{ui-react/src/styles => css/src}/base/root.css (91%) create mode 100644 packages/css/src/index.css create mode 100644 packages/css/src/index.ts create mode 100644 packages/css/src/recipes/badgeSizeRecipe.ts rename packages/{ui-react => css}/src/recipes/brandRecipe.ts (84%) create mode 100644 packages/css/src/recipes/dotSizeRecipe.ts create mode 100644 packages/css/src/recipes/inlineSizeRecipe.ts rename packages/{ui-react => css}/src/recipes/itemSizeRecipe.ts (51%) rename packages/{ui-react/src/recipes/variantRecipe.ts => css/src/recipes/itemVariantRecipe.ts} (73%) create mode 100644 packages/css/src/recipes/tabVariantRecipe.ts rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/align-content.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/align-items.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/align-self.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/animation.css (100%) create mode 100644 packages/css/src/utility-size-insensitive/background.css rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/box-decoration.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/box-inside.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/box-sizing.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/brand.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/break-after.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/break-before.css (100%) create mode 100644 packages/css/src/utility-size-insensitive/color.css rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/cursor.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/display.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/drop-shadow.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/flex-direction.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/flex-wrap.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/font-family.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/justify-content.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/justify-items.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/justify-self.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/overflow.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/overscroll-behavior.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/position.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/screen-reader.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/theme.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/user-select.css (100%) create mode 100644 packages/css/src/utility-size-insensitive/variant-can-hover.css create mode 100644 packages/css/src/utility-size-insensitive/variant-disabled.css create mode 100644 packages/css/src/utility-size-insensitive/variant-non-clickable.css create mode 100644 packages/css/src/utility-size-insensitive/variant.css rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/visibility.css (100%) rename packages/{ui-react/src/styles/utility/size-insensitive => css/src/utility-size-insensitive}/z-index.css (100%) rename packages/{ui-react/src/styles/utility/size-sensitive => css/src/utility-size-sensitive}/border-radius.css (88%) create mode 100644 packages/css/src/utility-size-sensitive/font-size-addon.css create mode 100644 packages/css/src/utility-size-sensitive/font-size.css create mode 100644 packages/css/src/utility-size-sensitive/font-weight.css create mode 100644 packages/css/src/utility-size-sensitive/gap.css create mode 100644 packages/css/src/utility-size-sensitive/height-addon.css create mode 100644 packages/css/src/utility-size-sensitive/height-dot.css create mode 100644 packages/css/src/utility-size-sensitive/height-inline.css create mode 100644 packages/css/src/utility-size-sensitive/height-item.css rename packages/{ui-react/src/styles/utility/size-sensitive => css/src/utility-size-sensitive}/margin.css (87%) create mode 100644 packages/css/src/utility-size-sensitive/min-width.css create mode 100644 packages/css/src/utility-size-sensitive/padding-addon.css create mode 100644 packages/css/src/utility-size-sensitive/padding-long.css rename packages/{ui-react/src/styles/utility/size-sensitive => css/src/utility-size-sensitive}/padding.css (55%) create mode 100644 packages/css/src/utility-size-sensitive/width-addon.css create mode 100644 packages/css/src/utility-size-sensitive/width-dot.css create mode 100644 packages/css/src/utility-size-sensitive/width-inline.css rename packages/{ui-react/src/styles/utility/size-sensitive/width.css => css/src/utility-size-sensitive/width-item.css} (50%) rename packages/{ui-react/src/styles => css/src}/utils/cpm.ts (100%) rename packages/{ui-react/src/styles => css/src}/utils/cvr.ts (100%) create mode 100644 packages/css/tsconfig.build.json create mode 100644 packages/css/tsconfig.json create mode 100644 packages/css/vite.config.ts create mode 100644 packages/ui-react/src/assets/svg/CloseSvg.tsx create mode 100644 packages/ui-react/src/componnets/Badge/Badge.tsx create mode 100644 packages/ui-react/src/componnets/Tag/Tag.tsx delete mode 100644 packages/ui-react/src/recipes/inlineSizeRecipe.ts delete mode 100644 packages/ui-react/src/styles/utility/size-insensitive/variant.css delete mode 100644 packages/ui-react/src/styles/utility/size-sensitive/font-size.css delete mode 100644 packages/ui-react/src/styles/utility/size-sensitive/font-weight.css delete mode 100644 packages/ui-react/src/styles/utility/size-sensitive/gap.css delete mode 100644 packages/ui-react/src/styles/utility/size-sensitive/height.css create mode 100644 packages/ui-react/src/utils/CommonProps.ts create mode 100644 packages/ui-react/src/utils/downSizeSmTo2xl.ts delete mode 100644 packages/ui-react/src/utils/useSlotsRegistry.ts create mode 100644 playground/ui-gallery/src/gallery/BadgeGallery.tsx create mode 100644 playground/ui-gallery/src/gallery/TagGallery.tsx diff --git a/packages/css/package.json b/packages/css/package.json new file mode 100644 index 0000000..d8ddddf --- /dev/null +++ b/packages/css/package.json @@ -0,0 +1,37 @@ +{ + "name": "@dg/css", + "version": "0.0.0", + "private": true, + "type": "module", + "sideEffects": [ + "*.css" + ], + "module": "./dist/index.es.js", + "main": "./dist/index.cjs.js", + "types": "./dist/index.d.ts", + "style": "./dist/index.css", + "exports": { + ".": { + "import": "./dist/index.es.js", + "require": "./dist/index.cjs.js", + "types": "./dist/index.d.ts" + }, + "./index.css": "./dist/index.css" + }, + "files": [ + "dist" + ], + "scripts": { + "gen-index": "ts-node scripts/gen-index.ts", + "gen-dts": "tsc -p tsconfig.build.json", + "build": "pnpm gen-index && vite build && pnpm gen-dts" + }, + "dependencies": {}, + "devDependencies": { + "@types/node": "^25.6.0", + "tinyglobby": "^0.2.16", + "ts-node": "^10.9.2", + "typescript": "^6.0.3", + "vite": "^8.0.10" + } +} diff --git a/packages/css/scripts/gen-index.ts b/packages/css/scripts/gen-index.ts new file mode 100644 index 0000000..ffe64b1 --- /dev/null +++ b/packages/css/scripts/gen-index.ts @@ -0,0 +1,254 @@ +import * as fs from "fs"; +import * as path from "path"; + +/** + * 默认测试 / story / example / fixture / type 文件匹配规则 + * 仅用于“识别”,不直接决定是否排除 + */ +const DEFAULT_TEST_FILE_PATTERNS: RegExp[] = [ + // ========================= + // Test / Spec + // ========================= + /\.(test|spec)\.(ts|tsx|js|jsx)$/, + /\.(test|spec)\.(ts|tsx|js|jsx)\?.*$/, // query param safe + + // ========================= + // E2E / Playwright / Cypress + // ========================= + /\.(cy|playwright|e2e)\.(ts|tsx|js|jsx)$/, + + // ========================= + // Storybook + // ========================= + /\.(story|stories)\.(ts|tsx|js|jsx|mdx)$/, + + // ========================= + // Snapshot / Mock / Fixture + // ========================= + /\.snap$/, + /\.mock\.(ts|tsx|js|jsx)$/, + /\.fixture\.(ts|tsx|js|jsx)$/, + + // ========================= + // Type declarations + // ========================= + /\.d\.ts$/, + + // ========================= + // Examples / Demos / Docs + // ========================= + /\.(example|demo|docs)\.(ts|tsx|js|jsx)$/, +]; + +/** + * 测试 / 辅助目录(目录级排除) + */ +const DEFAULT_TEST_DIR_PATTERNS: RegExp[] = [ + /[/\\](__tests__|tests|test|spec|__mocks__|__fixtures__|__snapshots__)[\/\\]/, + /[/\\](cypress|playwright|e2e|__e2e__|__playwright__)[\/\\]/, + /[/\\](story|stories|\.storybook)[\/\\]/, + /[/\\](types|type|typings|interfaces)[\/\\]/, + /[/\\](examples|example|demo|demos|docs)[\/\\]/, +]; + +type Config = { + outputDir: string; + outputFile: string; + scanDirs: string[]; + preamble?: string[]; + importPrefix?: string; + entryFilePatterns?: RegExp[]; + barrelFirstMode?: boolean; + includeFilePatterns?: RegExp[]; + excludeFilePatterns?: RegExp[]; + excludeDirPatterns?: RegExp[]; +}; + +const tsConfig: Config = { + outputDir: "src", + outputFile: "index.ts", + scanDirs: ["src"], + importPrefix: "export * from", + barrelFirstMode: true, + preamble: ["import './index.css';"], + entryFilePatterns: [/^index\.(js|ts|jsx|tsx)$/], + includeFilePatterns: [/\.(js|ts|jsx|tsx)$/], + excludeFilePatterns: DEFAULT_TEST_FILE_PATTERNS, + excludeDirPatterns: DEFAULT_TEST_DIR_PATTERNS, +}; + +const cssConfig: Config = { + outputDir: "src", + outputFile: "index.css", + scanDirs: ["src"], + importPrefix: "@import", + barrelFirstMode: false, + entryFilePatterns: [/^index\.(css)$/], + includeFilePatterns: [/\.(css)$/], + excludeFilePatterns: DEFAULT_TEST_FILE_PATTERNS, + excludeDirPatterns: DEFAULT_TEST_DIR_PATTERNS, +}; + +function isEntryFile(fileName: string, config: Config): boolean { + const regExps = config.entryFilePatterns; + + if (!regExps || regExps.length === 0) return false; + + return regExps.some((regExp) => regExp.test(fileName)); +} + +function isIncludeFile(fileName: string, config: Config): boolean { + const regExps = config.includeFilePatterns; + + if (!regExps || regExps.length === 0) return false; + + return regExps.some((regExp) => regExp.test(fileName)); +} + +function isExcludeFile(fileName: string, config: Config): boolean { + const regExps = config.excludeFilePatterns; + + if (!regExps || regExps.length === 0) return false; + + return regExps.some((regExp) => regExp.test(fileName)); +} + +function isExcludeDir(filePath: string, config: Config): boolean { + const regExps = config.excludeDirPatterns; + + if (!regExps || regExps.length === 0) return false; + + return regExps.some((regExp) => regExp.test(filePath)); +} + +function isValidDir(filePath: string, config: Config): boolean { + if (isExcludeDir(filePath, config)) { + return false; + } + return true; +} + +function isValidFile(fileName: string, config: Config): boolean { + if (isIncludeFile(fileName, config) && !isExcludeFile(fileName, config)) { + return true; + } + + return false; +} + +const buildExportStatement = (filePath: string, config: Config) => { + // 文件夹(不是文件)与目标文件的相对路径 + let exportFilePath = path.relative(config.outputDir, filePath); + + // 去除扩展名,并且转化成正斜杠 + const exportFilePathWithoutExt = path + .join( + path.dirname(exportFilePath), + path.basename(exportFilePath, path.extname(exportFilePath)), + ) + .replace(/\\/g, "/"); + + // 加上 ./ 前缀 + return `${config.importPrefix} './${exportFilePathWithoutExt}';`; +}; + +function isOutputEntry(filePath: string, config: Config) { + const outputFilePath = path.resolve(config.outputDir, config.outputFile); + const targetFilePath = path.resolve(filePath); + + return outputFilePath === targetFilePath; +} + +function generateExports(dirPath: string, config: Config): string[] { + const fileNames = fs.readdirSync(dirPath); + const exports: string[] = []; + + // ========================= + // 逻辑分支:Barrel First Mode + // ========================= + if (config.barrelFirstMode) { + // 查找当前目录有没有 index.ts + const entryFileName = fileNames.find((fileName) => { + const filePath = path.join(dirPath, fileName); + return fs.statSync(filePath).isFile() && isEntryFile(fileName, config); + }); + // 如果有 + if (entryFileName) { + const entryFilePath = path.join(dirPath, entryFileName); + + // 如果是 outputFile 自身,则跳过 + if (isOutputEntry(entryFilePath, config)) { + console.log(`⏭️ 跳过自身入口文件: ${entryFilePath}`); + } else { + exports.push(buildExportStatement(entryFilePath, config)); + } + } + } + + // ========================= + // 逻辑分支:index.ts 不存在,则继续正常遍历与递归 + // ========================= + fileNames.forEach((fileName) => { + const filePath = path.join(dirPath, fileName); + const stat = fs.statSync(filePath); + + // 情况1:是文件,且通过了校验 + if ( + stat.isFile() && + isValidFile(fileName, config) && + !isEntryFile(fileName, config) + ) { + exports.push(buildExportStatement(filePath, config)); + } + // 情况2:是文件夹,且通过了校验,递归扫描子文件夹 + else if (stat.isDirectory() && isValidDir(filePath, config)) { + const subExports = generateExports(filePath, config); + exports.push(...subExports); + } + }); + + return exports; +} + +async function genIndexFile(config: Config) { + const allExports: string[] = []; + + // 遍历所有需要扫描的根目录 + config.scanDirs.forEach((scanDir) => { + // 只有当目录真实存在时才进行扫描 + if (fs.existsSync(scanDir)) { + const exports = generateExports(scanDir, config); + allExports.push(...exports); + } else { + console.warn(`⚠️ 警告:扫描目录不存在,已跳过 -> ${scanDir}`); + } + }); + + // 拼接最终的文件内容:前言 + 导出语句(使用 Set 自动去重) + const fileContent = [ + ...(config.preamble ?? []), + ...Array.from(new Set(allExports)), + ].join("\n"); + + // 写入之前,确保输出目录存在,如果不存在就递归创建 + if (!fs.existsSync(config.outputDir)) { + fs.mkdirSync(config.outputDir, { recursive: true }); + } + + // 将内容写入到最终的 index.ts 文件中 + const outputFilePath = path.join(config.outputDir, config.outputFile); + fs.writeFileSync(outputFilePath, fileContent, "utf-8"); + + console.log(`✨ 成功生成入口文件: ${outputFilePath}`); +} + +// ================= 脚本执行入口 ================= +try { + console.log("🚀 开始扫描并生成入口文件..."); + await genIndexFile(cssConfig); + await genIndexFile(tsConfig); + console.log("✅ 脚本执行完毕!"); +} catch (error) { + console.error("❌ 脚本执行失败:", error); + process.exit(1); // 如果报错,让进程以非 0 状态码退出 +} diff --git a/packages/ui-react/src/styles/base/root.css b/packages/css/src/base/root.css similarity index 91% rename from packages/ui-react/src/styles/base/root.css rename to packages/css/src/base/root.css index ee4215a..ef9772f 100644 --- a/packages/ui-react/src/styles/base/root.css +++ b/packages/css/src/base/root.css @@ -330,28 +330,46 @@ --disabled-bg: var(--color-gray-100); --disabled-border-color: var(--color-gray-300); - --spacing: 2px; + --font-size-xs: 12px; + --font-size-sm: 12px; + --font-size-md: 14px; + --font-size-lg: 14px; + --font-size-xl: 16px; + --font-size-2xl: 24px; + --font-size-3xl: 30px; - --font-size-xs: 0.75rem; - --font-size-sm: 0.875rem; - --font-size-md: 1rem; - --font-size-lg: 1.125rem; - --font-size-xl: 1.5rem; - --font-size-2xl: 1.875rem; + --line-height: 1.4; - --line-height-xs: 1.33; - --line-height-sm: 1.42; - --line-height-md: 1.5; - --line-height-lg: 1.55; - --line-height-xl: 1.33; - --line-height-2xl: 1.2; + /* x button in tag */ + --height-item-xs: 20px; + /* text line */ + --height-item-sm: 24px; + /* normal desktop button */ + --height-item-md: 28px; + /* tab */ + --height-item-lg: 34px; + /* mobile button */ + --height-item-xl: 44px; + /* navigation bar */ + --height-item-2xl: 56px; + /* header bar */ + --height-item-3xl: 64px; - --height-item-xs: 1.5rem; - --height-item-sm: 1.75rem; - --height-item-md: 2.125rem; - --height-item-lg: 2.75rem; - --height-item-xl: 4rem; - --height-item-2xl: 4rem; + --radius-xs: 2px; + --radius-sm: 2px; + --radius-md: 4px; + --radius-lg: 6px; + --radius-xl: 8px; + --radius-2xl: 12px; + --radius-3xl: 16px; + + --padding-xs: 6px; + --padding-sm: 8px; + --padding-md: 10px; + --padding-lg: 12px; + --padding-xl: 16px; + --padding-2xl: 2px; + --padding-3xl: 2px; --animate-spin: spin 1s linear infinite; --animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; @@ -362,12 +380,12 @@ --animate-fade-in-up: fade-in-up 0.5s ease-out both; --animate-fade-out-up: fade-out-up 0.5s ease-in both; - --radius-xs: 0.125rem; - --radius-sm: 0.25rem; - --radius-md: 0.375rem; - --radius-lg: 0.5rem; - --radius-xl: 0.75rem; - --radius-2xl: 1rem; + --font-weight-light: 300; + --font-weight-normal: 400; + --font-weight-extranormal: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + --font-weight-extrabold: 800; --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", @@ -377,26 +395,31 @@ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - --margin-xs: calc(var(--spacing) * 2); - --margin-sm: calc(var(--spacing) * 4); + --margin-xs: 4px; + --margin-sm: 8px; --margin-md: calc(var(--spacing) * 2); --margin-lg: calc(var(--spacing) * 2); --margin-xl: calc(var(--spacing) * 2); --margin-2xl: calc(var(--spacing) * 2); + --margin-3xl: calc(var(--spacing) * 2); - --padding-long-xs: calc(var(--spacing) * 3); - --padding-long-sm: calc(var(--spacing) * 4); - --padding-long-md: calc(var(--spacing) * 5); - --padding-long-lg: calc(var(--spacing) * 8); - --padding-long-xl: calc(var(--spacing) * 2); - --padding-long-2xl: calc(var(--spacing) * 2); + --padding-long-xs: 12px; + --padding-long-sm: 14px; + --padding-long-md: 18px; + --padding-long-lg: 26px; + --padding-long-xl: 2px; + --padding-long-2xl: 2px; + --padding-long-3xl: 2px; - --padding-xs: calc(var(--spacing) * 2); - --padding-sm: calc(var(--spacing) * 4); - --padding-md: calc(var(--spacing) * 2); - --padding-lg: calc(var(--spacing) * 2); - --padding-xl: calc(var(--spacing) * 2); - --padding-2xl: calc(var(--spacing) * 2); + --height-addon-xs: 16px; + --height-addon-sm: 17px; + --height-addon-md: 18px; + --height-addon-lg: 20px; + + --px-addon-xs: 6px; + --px-addon-sm: 6px; + --px-addon-md: 10px; + --px-addon-lg: 12px; --drop-shadow-md: drop-shadow(0 0 4px rgba(0, 0, 0, 0.12)) drop-shadow(0 8px 16px rgba(0, 0, 0, 0.14)); diff --git a/packages/css/src/index.css b/packages/css/src/index.css new file mode 100644 index 0000000..5e729fd --- /dev/null +++ b/packages/css/src/index.css @@ -0,0 +1,52 @@ +@import './base/root'; +@import './utility-size-insensitive/align-content'; +@import './utility-size-insensitive/align-items'; +@import './utility-size-insensitive/align-self'; +@import './utility-size-insensitive/animation'; +@import './utility-size-insensitive/background'; +@import './utility-size-insensitive/box-decoration'; +@import './utility-size-insensitive/box-inside'; +@import './utility-size-insensitive/box-sizing'; +@import './utility-size-insensitive/brand'; +@import './utility-size-insensitive/break-after'; +@import './utility-size-insensitive/break-before'; +@import './utility-size-insensitive/color'; +@import './utility-size-insensitive/cursor'; +@import './utility-size-insensitive/display'; +@import './utility-size-insensitive/drop-shadow'; +@import './utility-size-insensitive/flex-direction'; +@import './utility-size-insensitive/flex-wrap'; +@import './utility-size-insensitive/font-family'; +@import './utility-size-insensitive/justify-content'; +@import './utility-size-insensitive/justify-items'; +@import './utility-size-insensitive/justify-self'; +@import './utility-size-insensitive/overflow'; +@import './utility-size-insensitive/overscroll-behavior'; +@import './utility-size-insensitive/position'; +@import './utility-size-insensitive/screen-reader'; +@import './utility-size-insensitive/theme'; +@import './utility-size-insensitive/user-select'; +@import './utility-size-insensitive/variant-can-hover'; +@import './utility-size-insensitive/variant-disabled'; +@import './utility-size-insensitive/variant-non-clickable'; +@import './utility-size-insensitive/variant'; +@import './utility-size-insensitive/visibility'; +@import './utility-size-insensitive/z-index'; +@import './utility-size-sensitive/border-radius'; +@import './utility-size-sensitive/font-size-addon'; +@import './utility-size-sensitive/font-size'; +@import './utility-size-sensitive/font-weight'; +@import './utility-size-sensitive/gap'; +@import './utility-size-sensitive/height-addon'; +@import './utility-size-sensitive/height-dot'; +@import './utility-size-sensitive/height-inline'; +@import './utility-size-sensitive/height-item'; +@import './utility-size-sensitive/margin'; +@import './utility-size-sensitive/min-width'; +@import './utility-size-sensitive/padding-addon'; +@import './utility-size-sensitive/padding-long'; +@import './utility-size-sensitive/padding'; +@import './utility-size-sensitive/width-addon'; +@import './utility-size-sensitive/width-dot'; +@import './utility-size-sensitive/width-inline'; +@import './utility-size-sensitive/width-item'; \ No newline at end of file diff --git a/packages/css/src/index.ts b/packages/css/src/index.ts new file mode 100644 index 0000000..49127c8 --- /dev/null +++ b/packages/css/src/index.ts @@ -0,0 +1,10 @@ +import './index.css'; +export * from './recipes/badgeSizeRecipe'; +export * from './recipes/brandRecipe'; +export * from './recipes/dotSizeRecipe'; +export * from './recipes/inlineSizeRecipe'; +export * from './recipes/itemSizeRecipe'; +export * from './recipes/itemVariantRecipe'; +export * from './recipes/tabVariantRecipe'; +export * from './utils/cpm'; +export * from './utils/cvr'; \ No newline at end of file diff --git a/packages/css/src/recipes/badgeSizeRecipe.ts b/packages/css/src/recipes/badgeSizeRecipe.ts new file mode 100644 index 0000000..da19452 --- /dev/null +++ b/packages/css/src/recipes/badgeSizeRecipe.ts @@ -0,0 +1,23 @@ +import { cvr } from "../utils/cvr"; + +export const badgeSizeRecipe = cvr({ + base: "display--flex flex--nowrap justify--center items--center select--none bg--red color--white", + variants: { + size: { + xs: "text--addon-xs h--addon-xs w--addon-xs px--addon-xs", + sm: "text--addon-sm h--addon-sm w--addon-sm px--addon-sm", + md: "text--addon-md h--addon-md w--addon-md px--addon-md", + lg: "text--addon-lg h--addon-lg w--addon-lg px--addon-lg", + }, + isCircle: { + true: "", + false: "", + }, + }, + compoundVariants: [ + { + isCircle: true, + class: "px--none", + }, + ], +}); diff --git a/packages/ui-react/src/recipes/brandRecipe.ts b/packages/css/src/recipes/brandRecipe.ts similarity index 84% rename from packages/ui-react/src/recipes/brandRecipe.ts rename to packages/css/src/recipes/brandRecipe.ts index 2595b99..51040da 100644 --- a/packages/ui-react/src/recipes/brandRecipe.ts +++ b/packages/css/src/recipes/brandRecipe.ts @@ -1,4 +1,4 @@ -import { cvr } from "../styles/utils/cvr"; +import { cvr } from "../utils/cvr"; export const brandRecipe = cvr({ variants: { diff --git a/packages/css/src/recipes/dotSizeRecipe.ts b/packages/css/src/recipes/dotSizeRecipe.ts new file mode 100644 index 0000000..89761d5 --- /dev/null +++ b/packages/css/src/recipes/dotSizeRecipe.ts @@ -0,0 +1,13 @@ +import { cvr } from "../utils/cvr"; + +export const dotSizeRecipe = cvr({ + base: "display--flex flex--nowrap justify--center items--center select--none bg--red color--white", + variants: { + size: { + xs: "h--dot-xs w--dot-xs", + sm: "h--dot-sm w--dot-sm", + md: "h--dot-md w--dot-md", + lg: "h--dot-lg w--dot-lg", + }, + }, +}); diff --git a/packages/css/src/recipes/inlineSizeRecipe.ts b/packages/css/src/recipes/inlineSizeRecipe.ts new file mode 100644 index 0000000..49603e6 --- /dev/null +++ b/packages/css/src/recipes/inlineSizeRecipe.ts @@ -0,0 +1,20 @@ +import { cvr } from "../utils/cvr"; + +export const inlineSizeRecipe = cvr({ + base: "display--flex flex--nowrap justify--center items--center", + variants: { + size: { + xs: "text--xs font-weight--xs h--inline-xs gap--xs", + sm: "text--sm font-weight--sm h--inline-sm gap--sm", + md: "text--md font-weight--md h--inline-md gap--md", + lg: "text--lg font-weight--lg h--inline-lg gap--lg", + xl: "text--xl font-weight--xl h--inline-xl gap--xl", + "2xl": "text--2xl font-weight--2xl h--inline-2xl gap--2xl", + "3xl": "text--3xl font-weight--3xl h--inline-3xl gap--3xl", + }, + shape: { + square: "rounded--none", + circle: "rounded--full", + }, + }, +}); diff --git a/packages/ui-react/src/recipes/itemSizeRecipe.ts b/packages/css/src/recipes/itemSizeRecipe.ts similarity index 51% rename from packages/ui-react/src/recipes/itemSizeRecipe.ts rename to packages/css/src/recipes/itemSizeRecipe.ts index 9b338c0..5a5d489 100644 --- a/packages/ui-react/src/recipes/itemSizeRecipe.ts +++ b/packages/css/src/recipes/itemSizeRecipe.ts @@ -1,15 +1,16 @@ -import { cvr } from "../styles/utils/cvr"; +import { cvr } from "../utils/cvr"; export const itemSizeRecipe = cvr({ base: "select--none display--flex flex--nowrap justify--center items--center", variants: { size: { - xs: "text--xs h--item-xs gap--xs px--xs", - sm: "text--sm h--item-sm gap--sm px--sm", - md: "text--md h--item-md gap--md px--md", - lg: "text--lg h--item-lg gap--lg px--lg", - xl: "text--xl h--item-xl gap--xl px--xl", - "2xl": "text--2xl h--item-2xl gap--2xl px--2xl", + xs: "text--xs font-weight--xs h--item-xs gap--xs px--xs", + sm: "text--sm font-weight--sm h--item-sm gap--sm px--sm", + md: "text--md font-weight--md h--item-md gap--md px--md", + lg: "text--lg font-weight--lg h--item-lg gap--lg px--lg", + xl: "text--xl font-weight--xl h--item-xl gap--xl px--xl", + "2xl": "text--2xl font-weight--2xl h--item-2xl gap--2xl px--2xl", + "3xl": "text--3xl font-weight--3xl h--item-3xl gap--3xl px--3xl", }, shape: { square: "rounded--none", @@ -20,8 +21,19 @@ export const itemSizeRecipe = cvr({ true: "px--none", false: "", }, + longPadding: { + true: "", + false: "", + }, }, compoundVariants: [ + { size: "xs", longPadding: true, class: "px--long-xs" }, + { size: "sm", longPadding: true, class: "px--long-sm" }, + { size: "md", longPadding: true, class: "px--long-md" }, + { size: "lg", longPadding: true, class: "px--long-lg" }, + { size: "xl", longPadding: true, class: "px--long-xl" }, + { size: "2xl", longPadding: true, class: "px--long-2xl" }, + { size: "3xl", longPadding: true, class: "px--long-3xl" }, // ================================================== { shape: "rounded", size: "xs", class: "rounded--xs" }, { shape: "rounded", size: "sm", class: "rounded--sm" }, @@ -29,6 +41,7 @@ export const itemSizeRecipe = cvr({ { shape: "rounded", size: "lg", class: "rounded--lg" }, { shape: "rounded", size: "xl", class: "rounded--xl" }, { shape: "rounded", size: "2xl", class: "rounded--2xl" }, + { shape: "rounded", size: "3xl", class: "rounded--3xl" }, // ================================================== { iconOnly: true, size: "xs", class: "w--item-xs" }, { iconOnly: true, size: "sm", class: "w--item-sm" }, @@ -36,5 +49,6 @@ export const itemSizeRecipe = cvr({ { iconOnly: true, size: "lg", class: "w--item-lg" }, { iconOnly: true, size: "xl", class: "w--item-xl" }, { iconOnly: true, size: "2xl", class: "w--item-2xl" }, + { iconOnly: true, size: "3xl", class: "w--item-3xl" }, ], }); diff --git a/packages/ui-react/src/recipes/variantRecipe.ts b/packages/css/src/recipes/itemVariantRecipe.ts similarity index 73% rename from packages/ui-react/src/recipes/variantRecipe.ts rename to packages/css/src/recipes/itemVariantRecipe.ts index 52c3ee5..0e2e83a 100644 --- a/packages/ui-react/src/recipes/variantRecipe.ts +++ b/packages/css/src/recipes/itemVariantRecipe.ts @@ -1,6 +1,6 @@ -import { cvr } from "../styles/utils/cvr"; +import { cvr } from "../utils/cvr"; -export const variantRecipe = cvr({ +export const itemVariantRecipe = cvr({ variants: { variant: { filled: "", @@ -12,6 +12,10 @@ export const variantRecipe = cvr({ true: "", false: "", }, + clickable: { + true: "", + false: "", + }, }, compoundVariants: [ { @@ -54,5 +58,15 @@ export const variantRecipe = cvr({ variant: "ghost", class: "variant--ghost-disabled", }, + { + variant: "filled", + clickable: false, + class: "variant--filled-non-clickable", + }, + { + variant: "outline", + clickable: false, + class: "variant--outline-non-clickable", + }, ], }); diff --git a/packages/css/src/recipes/tabVariantRecipe.ts b/packages/css/src/recipes/tabVariantRecipe.ts new file mode 100644 index 0000000..3ef85f6 --- /dev/null +++ b/packages/css/src/recipes/tabVariantRecipe.ts @@ -0,0 +1,14 @@ +import { cvr } from "../utils/cvr"; + +export const tabVariantRecipe = cvr({ + variants: { + variant: { + outline: "", + ghost: "", + }, + isAcitve: { + true: "", + false: "", + }, + }, +}); diff --git a/packages/ui-react/src/styles/utility/size-insensitive/align-content.css b/packages/css/src/utility-size-insensitive/align-content.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/align-content.css rename to packages/css/src/utility-size-insensitive/align-content.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/align-items.css b/packages/css/src/utility-size-insensitive/align-items.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/align-items.css rename to packages/css/src/utility-size-insensitive/align-items.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/align-self.css b/packages/css/src/utility-size-insensitive/align-self.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/align-self.css rename to packages/css/src/utility-size-insensitive/align-self.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/animation.css b/packages/css/src/utility-size-insensitive/animation.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/animation.css rename to packages/css/src/utility-size-insensitive/animation.css diff --git a/packages/css/src/utility-size-insensitive/background.css b/packages/css/src/utility-size-insensitive/background.css new file mode 100644 index 0000000..9a25943 --- /dev/null +++ b/packages/css/src/utility-size-insensitive/background.css @@ -0,0 +1,5 @@ +@layer utility { + .bg--red { + background-color: red; + } +} diff --git a/packages/ui-react/src/styles/utility/size-insensitive/box-decoration.css b/packages/css/src/utility-size-insensitive/box-decoration.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/box-decoration.css rename to packages/css/src/utility-size-insensitive/box-decoration.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/box-inside.css b/packages/css/src/utility-size-insensitive/box-inside.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/box-inside.css rename to packages/css/src/utility-size-insensitive/box-inside.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/box-sizing.css b/packages/css/src/utility-size-insensitive/box-sizing.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/box-sizing.css rename to packages/css/src/utility-size-insensitive/box-sizing.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/brand.css b/packages/css/src/utility-size-insensitive/brand.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/brand.css rename to packages/css/src/utility-size-insensitive/brand.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/break-after.css b/packages/css/src/utility-size-insensitive/break-after.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/break-after.css rename to packages/css/src/utility-size-insensitive/break-after.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/break-before.css b/packages/css/src/utility-size-insensitive/break-before.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/break-before.css rename to packages/css/src/utility-size-insensitive/break-before.css diff --git a/packages/css/src/utility-size-insensitive/color.css b/packages/css/src/utility-size-insensitive/color.css new file mode 100644 index 0000000..becc3ed --- /dev/null +++ b/packages/css/src/utility-size-insensitive/color.css @@ -0,0 +1,5 @@ +@layer utility { + .color--white { + color: white; + } +} diff --git a/packages/ui-react/src/styles/utility/size-insensitive/cursor.css b/packages/css/src/utility-size-insensitive/cursor.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/cursor.css rename to packages/css/src/utility-size-insensitive/cursor.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/display.css b/packages/css/src/utility-size-insensitive/display.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/display.css rename to packages/css/src/utility-size-insensitive/display.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/drop-shadow.css b/packages/css/src/utility-size-insensitive/drop-shadow.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/drop-shadow.css rename to packages/css/src/utility-size-insensitive/drop-shadow.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/flex-direction.css b/packages/css/src/utility-size-insensitive/flex-direction.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/flex-direction.css rename to packages/css/src/utility-size-insensitive/flex-direction.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/flex-wrap.css b/packages/css/src/utility-size-insensitive/flex-wrap.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/flex-wrap.css rename to packages/css/src/utility-size-insensitive/flex-wrap.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/font-family.css b/packages/css/src/utility-size-insensitive/font-family.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/font-family.css rename to packages/css/src/utility-size-insensitive/font-family.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/justify-content.css b/packages/css/src/utility-size-insensitive/justify-content.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/justify-content.css rename to packages/css/src/utility-size-insensitive/justify-content.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/justify-items.css b/packages/css/src/utility-size-insensitive/justify-items.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/justify-items.css rename to packages/css/src/utility-size-insensitive/justify-items.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/justify-self.css b/packages/css/src/utility-size-insensitive/justify-self.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/justify-self.css rename to packages/css/src/utility-size-insensitive/justify-self.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/overflow.css b/packages/css/src/utility-size-insensitive/overflow.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/overflow.css rename to packages/css/src/utility-size-insensitive/overflow.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/overscroll-behavior.css b/packages/css/src/utility-size-insensitive/overscroll-behavior.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/overscroll-behavior.css rename to packages/css/src/utility-size-insensitive/overscroll-behavior.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/position.css b/packages/css/src/utility-size-insensitive/position.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/position.css rename to packages/css/src/utility-size-insensitive/position.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/screen-reader.css b/packages/css/src/utility-size-insensitive/screen-reader.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/screen-reader.css rename to packages/css/src/utility-size-insensitive/screen-reader.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/theme.css b/packages/css/src/utility-size-insensitive/theme.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/theme.css rename to packages/css/src/utility-size-insensitive/theme.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/user-select.css b/packages/css/src/utility-size-insensitive/user-select.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/user-select.css rename to packages/css/src/utility-size-insensitive/user-select.css diff --git a/packages/css/src/utility-size-insensitive/variant-can-hover.css b/packages/css/src/utility-size-insensitive/variant-can-hover.css new file mode 100644 index 0000000..22e3324 --- /dev/null +++ b/packages/css/src/utility-size-insensitive/variant-can-hover.css @@ -0,0 +1,51 @@ +@layer utility { + .variant--outline-can-hover { + --outline-fg: var(--brand-bg); + --outline-fg-hover: var(--brand-bg); + --outline-fg-active: var(--brand-bg); + --outline-bg: var(--color-transparent); + --outline-bg-hover: var(--brand-bg-low); + --outline-bg-active: var(--brand-bg-low-hover); + --outline-border-color: var(--brand-bg); + + color: var(--outline-fg); + background-color: var(--outline-bg); + border: solid 1px; + border-color: var(--outline-border-color); + + &:hover { + background-color: var(--outline-bg-hover); + color: var(--outline-fg-hover); + } + } + .variant--outline-active { + &:active { + background-color: var(--outline-bg-active); + color: var(--outline-fg-active); + } + } + .variant--ghost-can-hover { + --ghost-fg: var(--brand-bg); + --ghost-fg-hover: var(--brand-bg); + --ghost-fg-active: var(--brand-bg); + --ghost-bg: var(--color-transparent); + --ghost-bg-hover: var(--brand-bg-low); + --ghost-bg-active: var(--brand-bg-low-hover); + --ghost-border-color: var(--color-transparent); + + color: var(--ghost-fg); + background-color: var(--ghost-bg); + border-color: var(--ghost-border-color); + + &:hover { + background-color: var(--ghost-bg-hover); + color: var(--ghost-fg-hover); + } + } + .variant--ghost-active { + &:active { + background-color: var(--ghost-bg-active); + color: var(--ghost-fg-active); + } + } +} diff --git a/packages/css/src/utility-size-insensitive/variant-disabled.css b/packages/css/src/utility-size-insensitive/variant-disabled.css new file mode 100644 index 0000000..47c3616 --- /dev/null +++ b/packages/css/src/utility-size-insensitive/variant-disabled.css @@ -0,0 +1,89 @@ +@layer utility { + .variant--filled-disabled { + color: var(--disabled-fg); + background-color: var(--disabled-bg); + border-color: var(--disabled-border-color); + filter: grayscale(100%); + + &:hover { + color: var(--disabled-fg); + background-color: var(--disabled-bg); + border-color: var(--disabled-border-color); + filter: grayscale(100%); + } + + &:active { + color: var(--disabled-fg); + background-color: var(--disabled-bg); + border-color: var(--disabled-border-color); + filter: grayscale(100%); + } + + &:focus-visible { + color: var(--disabled-fg); + background-color: var(--disabled-bg); + border-color: var(--disabled-border-color); + filter: grayscale(100%); + } + } + + .variant--outline-disabled { + color: var(--disabled-fg); + background-color: var(--disabled-bg); + border: solid 1px; + border-color: var(--disabled-border-color); + filter: grayscale(100%); + + &:hover { + color: var(--disabled-fg); + background-color: var(--disabled-bg); + border: solid 1px; + border-color: var(--disabled-border-color); + filter: grayscale(100%); + } + + &:active { + color: var(--disabled-fg); + background-color: var(--disabled-bg); + border: solid 1px; + border-color: var(--disabled-border-color); + filter: grayscale(100%); + } + + &:focus-visible { + color: var(--disabled-fg); + background-color: var(--disabled-bg); + border: solid 1px; + border-color: var(--disabled-border-color); + filter: grayscale(100%); + } + } + + .variant--ghost-disabled { + color: var(--ghost-fg); + background-color: var(--ghost-bg); + border-color: var(--ghost-border-color); + filter: grayscale(50%); + + &:hover { + color: var(--ghost-fg); + background-color: var(--ghost-bg); + border-color: var(--ghost-border-color); + filter: grayscale(50%); + } + + &:active { + color: var(--ghost-fg); + background-color: var(--ghost-bg); + border-color: var(--ghost-border-color); + filter: grayscale(50%); + } + + &:focus-visible { + color: var(--ghost-fg); + background-color: var(--ghost-bg); + border-color: var(--ghost-border-color); + filter: grayscale(50%); + } + } +} diff --git a/packages/css/src/utility-size-insensitive/variant-non-clickable.css b/packages/css/src/utility-size-insensitive/variant-non-clickable.css new file mode 100644 index 0000000..75a0540 --- /dev/null +++ b/packages/css/src/utility-size-insensitive/variant-non-clickable.css @@ -0,0 +1,55 @@ +@layer utility { + .variant--filled-non-clickable { + --filled-fg: var(--color-white); + --filled-fg-hover: var(--color-white); + --filled-fg-active: var(--color-white); + --filled-bg: var(--brand-bg); + --filled-bg-hover: var(--brand-bg-hover); + --filled-bg-active: var(--brand-bg-active); + --filled-border-color: var(--color-transparent); + + color: var(--filled-fg); + background-color: var(--filled-bg); + border-color: var(--filled-border-color); + } + .variant--outline-non-clickable { + --outline-fg: var(--brand-bg); + --outline-fg-hover: var(--brand-bg); + --outline-fg-active: var(--brand-bg); + --outline-bg: var(--color-transparent); + --outline-bg-hover: var(--brand-bg-low); + --outline-bg-active: var(--brand-bg-low-hover); + --outline-border-color: var(--brand-bg); + + color: var(--outline-fg); + background-color: var(--outline-bg); + border: solid 1px; + border-color: var(--outline-border-color); + } + .variant--subtle-non-clickable { + --subtle-fg: var(--brand-bg); + --subtle-fg-hover: var(--brand-bg); + --subtle-fg-active: var(--brand-bg); + --subtle-bg: var(--brand-bg-low); + --subtle-bg-hover: var(--brand-bg-low-hover); + --subtle-bg-active: var(--brand-bg-low-active); + --subtle-border-color: var(--color-transparent); + + color: var(--subtle-fg); + background-color: var(--subtle-bg); + border-color: var(--subtle-border-color); + } + .variant--ghost-non-clickable { + --ghost-fg: var(--brand-bg); + --ghost-fg-hover: var(--brand-bg); + --ghost-fg-active: var(--brand-bg); + --ghost-bg: var(--color-transparent); + --ghost-bg-hover: var(--brand-bg-low); + --ghost-bg-active: var(--brand-bg-low-hover); + --ghost-border-color: var(--color-transparent); + + color: var(--ghost-fg); + background-color: var(--ghost-bg); + border-color: var(--ghost-border-color); + } +} diff --git a/packages/css/src/utility-size-insensitive/variant.css b/packages/css/src/utility-size-insensitive/variant.css new file mode 100644 index 0000000..9b521c9 --- /dev/null +++ b/packages/css/src/utility-size-insensitive/variant.css @@ -0,0 +1,98 @@ +@layer utility { + .variant--filled { + --filled-fg: var(--color-white); + --filled-fg-hover: var(--color-white); + --filled-fg-active: var(--color-white); + --filled-bg: var(--brand-bg); + --filled-bg-hover: var(--brand-bg-hover); + --filled-bg-active: var(--brand-bg-active); + --filled-border-color: var(--color-transparent); + + color: var(--filled-fg); + background-color: var(--filled-bg); + border-color: var(--filled-border-color); + + &:hover { + background-color: var(--filled-bg-hover); + color: var(--filled-fg-hover); + } + + &:active { + background-color: var(--filled-bg-active); + color: var(--filled-fg-active); + } + } + + .variant--outline { + --outline-fg: var(--brand-bg); + --outline-fg-hover: var(--brand-bg); + --outline-fg-active: var(--brand-bg); + --outline-bg: var(--color-transparent); + --outline-bg-hover: var(--brand-bg-low); + --outline-bg-active: var(--brand-bg-low-hover); + --outline-border-color: var(--brand-bg); + + color: var(--outline-fg); + background-color: var(--outline-bg); + border: solid 1px; + border-color: var(--outline-border-color); + + &:hover { + background-color: var(--outline-bg-hover); + color: var(--outline-fg-hover); + } + + &:active { + background-color: var(--outline-bg-active); + color: var(--outline-fg-active); + } + } + + .variant--subtle { + --subtle-fg: var(--brand-bg); + --subtle-fg-hover: var(--brand-bg); + --subtle-fg-active: var(--brand-bg); + --subtle-bg: var(--brand-bg-low); + --subtle-bg-hover: var(--brand-bg-low-hover); + --subtle-bg-active: var(--brand-bg-low-active); + --subtle-border-color: var(--color-transparent); + + color: var(--subtle-fg); + background-color: var(--subtle-bg); + border-color: var(--subtle-border-color); + + &:hover { + background-color: var(--subtle-bg-hover); + color: var(--subtle-fg-hover); + } + + &:active { + background-color: var(--subtle-bg-active); + color: var(--subtle-fg-active); + } + } + + .variant--ghost { + --ghost-fg: var(--brand-bg); + --ghost-fg-hover: var(--brand-bg); + --ghost-fg-active: var(--brand-bg); + --ghost-bg: var(--color-transparent); + --ghost-bg-hover: var(--brand-bg-low); + --ghost-bg-active: var(--brand-bg-low-hover); + --ghost-border-color: var(--color-transparent); + + color: var(--ghost-fg); + background-color: var(--ghost-bg); + border-color: var(--ghost-border-color); + + &:hover { + background-color: var(--ghost-bg-hover); + color: var(--ghost-fg-hover); + } + + &:active { + background-color: var(--ghost-bg-active); + color: var(--ghost-fg-active); + } + } +} diff --git a/packages/ui-react/src/styles/utility/size-insensitive/visibility.css b/packages/css/src/utility-size-insensitive/visibility.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/visibility.css rename to packages/css/src/utility-size-insensitive/visibility.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/z-index.css b/packages/css/src/utility-size-insensitive/z-index.css similarity index 100% rename from packages/ui-react/src/styles/utility/size-insensitive/z-index.css rename to packages/css/src/utility-size-insensitive/z-index.css diff --git a/packages/ui-react/src/styles/utility/size-sensitive/border-radius.css b/packages/css/src/utility-size-sensitive/border-radius.css similarity index 88% rename from packages/ui-react/src/styles/utility/size-sensitive/border-radius.css rename to packages/css/src/utility-size-sensitive/border-radius.css index 9e90d1c..ba7d8c9 100644 --- a/packages/ui-react/src/styles/utility/size-sensitive/border-radius.css +++ b/packages/css/src/utility-size-sensitive/border-radius.css @@ -23,4 +23,7 @@ .rounded--2xl { border-radius: var(--radius-2xl); } + .rounded--3xl { + border-radius: var(--radius-3xl); + } } diff --git a/packages/css/src/utility-size-sensitive/font-size-addon.css b/packages/css/src/utility-size-sensitive/font-size-addon.css new file mode 100644 index 0000000..eefb8d8 --- /dev/null +++ b/packages/css/src/utility-size-sensitive/font-size-addon.css @@ -0,0 +1,22 @@ +@layer utility { + .text--addon-xs { + font-size: 12px; + line-height: var(--line-height); + font-weight: 400; + } + .text--addon-sm { + font-size: 13px; + line-height: var(--line-height); + font-weight: 400; + } + .text--addon-md { + font-size: 14px; + line-height: var(--line-height); + font-weight: 500; + } + .text--addon-lg { + font-size: 16px; + line-height: var(--line-height); + font-weight: 500; + } +} diff --git a/packages/css/src/utility-size-sensitive/font-size.css b/packages/css/src/utility-size-sensitive/font-size.css new file mode 100644 index 0000000..ca903f4 --- /dev/null +++ b/packages/css/src/utility-size-sensitive/font-size.css @@ -0,0 +1,30 @@ +@layer utility { + .text--xs { + font-size: var(--font-size-xs); + line-height: var(--line-height); + } + .text--sm { + font-size: var(--font-size-sm); + line-height: var(--line-height); + } + .text--md { + font-size: var(--font-size-md); + line-height: var(--line-height); + } + .text--lg { + font-size: var(--font-size-lg); + line-height: var(--line-height); + } + .text--xl { + font-size: var(--font-size-2xl); + line-height: var(--line-height); + } + .text--2xl { + font-size: var(--font-size-2xl); + line-height: var(--line-height); + } + .text--3xl { + font-size: var(--font-size-3xl); + line-height: var(--line-height); + } +} diff --git a/packages/css/src/utility-size-sensitive/font-weight.css b/packages/css/src/utility-size-sensitive/font-weight.css new file mode 100644 index 0000000..bb14bc1 --- /dev/null +++ b/packages/css/src/utility-size-sensitive/font-weight.css @@ -0,0 +1,44 @@ +@layer utility { + .font-weight--light { + font-weight: var(--font-weight-light); + } + .font-weight--normal { + font-weight: var(--font-weight-normal); + } + .font-weight--extranormal { + font-weight: var(--font-weight-extranormal); + } + .font-weight--semibold { + font-weight: var(--font-weight-semibold); + } + .font-weight--bold { + font-weight: var(--font-weight-bold); + } + .font-weight--extrabold { + font-weight: var(--font-weight-extrabold); + } + + /* ================== */ + + .font-weight--xs { + font-weight: var(--font-weight-normal); + } + .font-weight--sm { + font-weight: var(--font-weight-normal); + } + .font-weight--md { + font-weight: var(--font-weight-extranormal); + } + .font-weight--lg { + font-weight: var(--font-weight-semibold); + } + .font-weight--xl { + font-weight: var(--font-weight-semibold); + } + .font-weight--2xl { + font-weight: var(--font-weight-semibold); + } + .font-weight--3xl { + font-weight: var(--font-weight-bold); + } +} diff --git a/packages/css/src/utility-size-sensitive/gap.css b/packages/css/src/utility-size-sensitive/gap.css new file mode 100644 index 0000000..e63f32d --- /dev/null +++ b/packages/css/src/utility-size-sensitive/gap.css @@ -0,0 +1,23 @@ +@layer utility { + .gap--xs { + gap: 2px; + } + .gap--sm { + gap: 4px; + } + .gap--md { + gap: 6px; + } + .gap--lg { + gap: 8px; + } + .gap--xl { + gap: 10px; + } + .gap--2xl { + gap: 12px; + } + .gap--3xl { + gap: 14px; + } +} diff --git a/packages/css/src/utility-size-sensitive/height-addon.css b/packages/css/src/utility-size-sensitive/height-addon.css new file mode 100644 index 0000000..c0a08f1 --- /dev/null +++ b/packages/css/src/utility-size-sensitive/height-addon.css @@ -0,0 +1,14 @@ +@layer utility { + .h--addon-xs { + height: var(--height-addon-xs); + } + .h--addon-sm { + height: var(--height-addon-sm); + } + .h--addon-md { + height: var(--height-addon-md); + } + .h--addon-lg { + height: var(--height-addon-lg); + } +} diff --git a/packages/css/src/utility-size-sensitive/height-dot.css b/packages/css/src/utility-size-sensitive/height-dot.css new file mode 100644 index 0000000..3817d02 --- /dev/null +++ b/packages/css/src/utility-size-sensitive/height-dot.css @@ -0,0 +1,14 @@ +@layer utility { + .h--dot-xs { + height: calc(var(--font-size-xs) / 2); + } + .h--dot-sm { + height: calc(var(--font-size-sm) / 2); + } + .h--dot-md { + height: calc(var(--font-size-md) / 2); + } + .h--dot-lg { + height: calc(var(--font-size-lg) / 2); + } +} diff --git a/packages/css/src/utility-size-sensitive/height-inline.css b/packages/css/src/utility-size-sensitive/height-inline.css new file mode 100644 index 0000000..aa64e65 --- /dev/null +++ b/packages/css/src/utility-size-sensitive/height-inline.css @@ -0,0 +1,25 @@ +@layer utility { + .h--inline-xs { + height: calc(var(--font-size-xs) * var(--line-height)); + } + + .h--inline-sm { + height: calc(var(--font-size-sm) * var(--line-height)); + } + + .h--inline-md { + height: calc(var(--font-size-md) * var(--line-height)); + } + + .h--inline-lg { + height: calc(var(--font-size-lg) * var(--line-height)); + } + + .h--inline-xl { + height: calc(var(--font-size-xl) * var(--line-height)); + } + + .h--inline-2xl { + height: calc(var(--font-size-2xl) * var(--line-height)); + } +} diff --git a/packages/css/src/utility-size-sensitive/height-item.css b/packages/css/src/utility-size-sensitive/height-item.css new file mode 100644 index 0000000..d607285 --- /dev/null +++ b/packages/css/src/utility-size-sensitive/height-item.css @@ -0,0 +1,23 @@ +@layer utility { + .h--item-xs { + height: var(--height-item-xs); + } + .h--item-sm { + height: var(--height-item-sm); + } + .h--item-md { + height: var(--height-item-md); + } + .h--item-lg { + height: var(--height-item-lg); + } + .h--item-xl { + height: var(--height-item-xl); + } + .h--item-2xl { + height: var(--height-item-2xl); + } + .h--item-3xl { + height: var(--height-item-3xl); + } +} diff --git a/packages/ui-react/src/styles/utility/size-sensitive/margin.css b/packages/css/src/utility-size-sensitive/margin.css similarity index 87% rename from packages/ui-react/src/styles/utility/size-sensitive/margin.css rename to packages/css/src/utility-size-sensitive/margin.css index cc5cc7a..c56bb2a 100644 --- a/packages/ui-react/src/styles/utility/size-sensitive/margin.css +++ b/packages/css/src/utility-size-sensitive/margin.css @@ -22,11 +22,12 @@ .my--xl { margin-block: var(--margin-xl); } - .my--2xl { margin-block: var(--margin-2xl); } - + .my--3xl { + margin-block: var(--margin-3xl); + } /* ======================== */ .mx--none { @@ -56,4 +57,7 @@ .mx--2xl { margin-inline: var(--margin-2xl); } -} \ No newline at end of file + .mx--3xl { + margin-inline: var(--margin-3xl); + } +} diff --git a/packages/css/src/utility-size-sensitive/min-width.css b/packages/css/src/utility-size-sensitive/min-width.css new file mode 100644 index 0000000..b129dce --- /dev/null +++ b/packages/css/src/utility-size-sensitive/min-width.css @@ -0,0 +1,26 @@ +@layer utility { + .min-w--addon-xs { + min-width: calc( + calc(var(--font-size-addon-xs) * var(--line-height)) - + calc(2 * var(--padding-addon-xs)) + ); + } + .min-w--addon-sm { + min-width: calc( + calc(var(--font-size-addon-sm) * var(--line-height)) - + calc(2 * var(--padding-addon-sm)) + ); + } + .min-w--addon-md { + min-width: calc( + calc(var(--font-size-addon-md) * var(--line-height)) - + calc(2 * var(--padding-addon-md)) + ); + } + .min-w--addon-lg { + min-width: calc( + calc(var(--font-size-addon-lg) * var(--line-height)) - + calc(2 * var(--padding-addon-lg)) + ); + } +} diff --git a/packages/css/src/utility-size-sensitive/padding-addon.css b/packages/css/src/utility-size-sensitive/padding-addon.css new file mode 100644 index 0000000..152aa7a --- /dev/null +++ b/packages/css/src/utility-size-sensitive/padding-addon.css @@ -0,0 +1,14 @@ +@layer utility { + .px--addon-xs { + padding-inline: var(--px-addon-xs); + } + .px--addon-sm { + padding-inline: var(--px-addon-sm); + } + .px--addon-md { + padding-inline: var(--px-addon-md); + } + .px--addon-lg { + padding-inline: var(--px-addon-lg); + } +} diff --git a/packages/css/src/utility-size-sensitive/padding-long.css b/packages/css/src/utility-size-sensitive/padding-long.css new file mode 100644 index 0000000..e43939d --- /dev/null +++ b/packages/css/src/utility-size-sensitive/padding-long.css @@ -0,0 +1,20 @@ +@layer utility { + .px--long-xs { + padding-inline: var(--padding-long-xs); + } + .px--long-sm { + padding-inline: var(--padding-long-sm); + } + .px--long-md { + padding-inline: var(--padding-long-md); + } + .px--long-lg { + padding-inline: var(--padding-long-lg); + } + .px--long-xl { + padding-inline: var(--padding-long-xl); + } + .px--long-2xl { + padding-inline: var(--padding-long-2xl); + } +} diff --git a/packages/ui-react/src/styles/utility/size-sensitive/padding.css b/packages/css/src/utility-size-sensitive/padding.css similarity index 55% rename from packages/ui-react/src/styles/utility/size-sensitive/padding.css rename to packages/css/src/utility-size-sensitive/padding.css index 43d80a3..47e6579 100644 --- a/packages/ui-react/src/styles/utility/size-sensitive/padding.css +++ b/packages/css/src/utility-size-sensitive/padding.css @@ -2,90 +2,51 @@ .px--none { padding-inline: 0px; } - .px--xs { - /* 4px, 24px - 16px = 8px */ padding-inline: var(--padding-xs); } - .px--sm { - /* 4px, 28px - 20px = 8px */ padding-inline: var(--padding-sm); } - .px--md { - /* 10px */ padding-inline: var(--padding-md); } - .px--lg { - /* 16px */ padding-inline: var(--padding-lg); } - .px--xl { padding-inline: var(--padding-xl); } - .px--2xl { padding-inline: var(--padding-2xl); } + .px--3xl { + padding-inline: var(--padding-3xl); + } + /* =================================================== */ - /* ------------------------ */ .py--none { padding-block: 0px; } - .py--xs { padding-block: var(--padding-xs); } - .py--sm { padding-block: var(--padding-sm); } - .py--md { padding-block: var(--padding-md); } - .py--lg { padding-block: var(--padding-lg); } - .py--xl { padding-block: var(--padding-xl); } - .py--2xl { padding-block: var(--padding-2xl); } - - /* ========================== */ - .px--long-xs { - /* 6px */ - padding-inline: var(--padding-long-xs); + .py--3xl { + padding-block: var(--padding-3xl); } - - .px--long-sm { - /* 8px */ - padding-inline: var(--padding-long-sm); - } - - .px--long-md { - /* 10px */ - padding-inline: var(--padding-long-md); - } - - .px--long-lg { - /* 16px */ - padding-inline: var(--padding-long-lg); - } - - .px--long-xl { - padding-inline: var(--padding-long-xl); - } - - .px--long-2xl { - padding-inline: var(--padding-long-2xl); - } -} \ No newline at end of file +} diff --git a/packages/css/src/utility-size-sensitive/width-addon.css b/packages/css/src/utility-size-sensitive/width-addon.css new file mode 100644 index 0000000..797ef31 --- /dev/null +++ b/packages/css/src/utility-size-sensitive/width-addon.css @@ -0,0 +1,14 @@ +@layer utility { + .w--addon-xs { + width: var(--height-addon-xs); + } + .w--addon-sm { + width: var(--height-addon-sm); + } + .w--addon-md { + width: var(--height-addon-md); + } + .w--addon-lg { + width: var(--height-addon-lg); + } +} diff --git a/packages/css/src/utility-size-sensitive/width-dot.css b/packages/css/src/utility-size-sensitive/width-dot.css new file mode 100644 index 0000000..11a6c2c --- /dev/null +++ b/packages/css/src/utility-size-sensitive/width-dot.css @@ -0,0 +1,14 @@ +@layer utility { + .w--dot-xs { + width: calc(var(--font-size-xs) / 2); + } + .w--dot-sm { + width: calc(var(--font-size-sm) / 2); + } + .w--dot-md { + width: calc(var(--font-size-md) / 2); + } + .w--dot-lg { + width: calc(var(--font-size-lg) / 2); + } +} diff --git a/packages/css/src/utility-size-sensitive/width-inline.css b/packages/css/src/utility-size-sensitive/width-inline.css new file mode 100644 index 0000000..406db54 --- /dev/null +++ b/packages/css/src/utility-size-sensitive/width-inline.css @@ -0,0 +1,25 @@ +@layer utility { + .w--inline-xs { + width: calc(var(--font-size-xs) * var(--line-height-xs)); + } + + .w--inline-sm { + width: calc(var(--font-size-sm) * var(--line-height-sm)); + } + + .w--inline-md { + width: calc(var(--font-size-md) * var(--line-height-md)); + } + + .w--inline-lg { + width: calc(var(--font-size-lg) * var(--line-height-lg)); + } + + .w--inline-xl { + width: calc(var(--font-size-xl) * var(--line-height-xl)); + } + + .w--inline-xl { + width: calc(var(--font-size-2xl) * var(--line-height-2xl)); + } +} diff --git a/packages/ui-react/src/styles/utility/size-sensitive/width.css b/packages/css/src/utility-size-sensitive/width-item.css similarity index 50% rename from packages/ui-react/src/styles/utility/size-sensitive/width.css rename to packages/css/src/utility-size-sensitive/width-item.css index fff1416..d5b9382 100644 --- a/packages/ui-react/src/styles/utility/size-sensitive/width.css +++ b/packages/css/src/utility-size-sensitive/width-item.css @@ -28,29 +28,4 @@ /* 64px navigation bar */ width: var(--height-item-2xl); } - - /* ---------------------------------------------------- */ - .w--inline-xs { - width: calc(var(--font-size-xs) * var(--line-height-xs)); - } - - .w--inline-sm { - width: calc(var(--font-size-sm) * var(--line-height-sm)); - } - - .w--inline-md { - width: calc(var(--font-size-md) * var(--line-height-md)); - } - - .w--inline-lg { - width: calc(var(--font-size-lg) * var(--line-height-lg)); - } - - .w--inline-xl { - width: calc(var(--font-size-xl) * var(--line-height-xl)); - } - - .w--inline-xl { - width: calc(var(--font-size-2xl) * var(--line-height-2xl)); - } } diff --git a/packages/ui-react/src/styles/utils/cpm.ts b/packages/css/src/utils/cpm.ts similarity index 100% rename from packages/ui-react/src/styles/utils/cpm.ts rename to packages/css/src/utils/cpm.ts diff --git a/packages/ui-react/src/styles/utils/cvr.ts b/packages/css/src/utils/cvr.ts similarity index 100% rename from packages/ui-react/src/styles/utils/cvr.ts rename to packages/css/src/utils/cvr.ts diff --git a/packages/css/tsconfig.build.json b/packages/css/tsconfig.build.json new file mode 100644 index 0000000..a5bcc27 --- /dev/null +++ b/packages/css/tsconfig.build.json @@ -0,0 +1,41 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": false, + "emitDeclarationOnly": true, + "declaration": true, + "rootDir": "./src", + "outDir": "./dist", + "declarationDir": "./dist" + }, + "include": ["src"], + "exclude": [ + "node_modules", + "dist", + ".turbo/**/*", + ".cache/**/*", + ".vite/**/*", + "vite.config.ts", + "*.config.ts", + "*.config.js", + "tsconfig.*.json", + "__tests__/**/*", + "test/**/*", + "tests/**/*", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx", + ".storybook/**/*", + "stories/**/*", + "example/**/*", + "examples/**/*", + "scripts/**/*", + ".env", + ".env.*", + "public/**/*", + "docs/**/*", + "README.md", + "LICENSE" + ] +} diff --git a/packages/css/tsconfig.json b/packages/css/tsconfig.json new file mode 100644 index 0000000..7b84f30 --- /dev/null +++ b/packages/css/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2025", + "lib": [ + "ES2025", + "DOM", + "DOM.Iterable" + ], + "module": "ESNext", + "types": [ + "node", + "vite/client" + ], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + }, + "include": [ + "src", + "scripts", + "vite.config.ts", + ] +} \ No newline at end of file diff --git a/packages/css/vite.config.ts b/packages/css/vite.config.ts new file mode 100644 index 0000000..5e58d54 --- /dev/null +++ b/packages/css/vite.config.ts @@ -0,0 +1,38 @@ +import path from "path"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [], + + build: { + cssMinify: false, + + lib: { + entry: path.resolve(import.meta.dirname, "src/index.ts"), + formats: ["es", "cjs"], + fileName: (format) => `index.${format}.js`, + }, + + rolldownOptions: { + external: ["react", "react-dom", "react/jsx-runtime"], + output: { + // 强制将生成的 CSS 命名为 index.css + assetFileNames: (assetInfo) => { + if (assetInfo.name && assetInfo.name.endsWith(".css")) { + return "index.css"; + } + return "[name].[hash][extname]"; + }, + globals: { + react: "React", + "react-dom": "ReactDOM", + }, + }, + }, + + emptyOutDir: true, + sourcemap: true, + cssCodeSplit: false, + outDir: "dist", + }, +}); diff --git a/packages/ui-react/package.json b/packages/ui-react/package.json index 13b0e2f..dcad19e 100644 --- a/packages/ui-react/package.json +++ b/packages/ui-react/package.json @@ -26,7 +26,9 @@ "gen-dts": "tsc -p tsconfig.build.json", "build": "pnpm gen-index && vite build && pnpm gen-dts" }, - "dependencies": {}, + "dependencies": { + "@dg/css": "workspace:*" + }, "devDependencies": { "@types/node": "^25.6.0", "@types/react": "^19.2.14", diff --git a/packages/ui-react/src/assets/svg/CloseSvg.tsx b/packages/ui-react/src/assets/svg/CloseSvg.tsx new file mode 100644 index 0000000..8686948 --- /dev/null +++ b/packages/ui-react/src/assets/svg/CloseSvg.tsx @@ -0,0 +1,12 @@ +export const CloseSvg = (props: React.SVGProps) => ( + + + +); diff --git a/packages/ui-react/src/componnets/Badge/Badge.tsx b/packages/ui-react/src/componnets/Badge/Badge.tsx new file mode 100644 index 0000000..0e317f6 --- /dev/null +++ b/packages/ui-react/src/componnets/Badge/Badge.tsx @@ -0,0 +1,61 @@ +import { + forwardRef, + type ComponentPropsWithoutRef, + type CSSProperties, +} from "react"; +import { cpm } from "../../styles/utils/cpm"; +import { dotSizeRecipe } from "../../recipes/dotSizeRecipe"; +import { addonSizeRecipe } from "../../recipes/addonSizeRecipe"; + +export type BadgeProps = ComponentPropsWithoutRef<"div"> & { + size?: "xs" | "sm" | "md" | "lg"; +} & { + forceDot?: boolean; + indicatorContent?: string; +}; + +export const Badge = forwardRef((props, ref) => { + const { + indicatorContent = "", + forceDot = false, + size = "md", + children, + className = "", + ...rest + } = props; + + const wrapperStyle: CSSProperties = { + position: "relative", + height: "fit", + width: "fit", + }; + + const indicatorStyle: CSSProperties = { + position: "absolute", + top: 0, + right: 0, + transform: "translate(50%,-50%)", + borderRadius: "9999px", + }; + const isNotHaveContent = + indicatorContent == "" || indicatorContent == undefined; + const isDot = isNotHaveContent || forceDot == true; + const isCircle = indicatorContent.length == 1; + + let indicatorClass; + + if (isDot) { + indicatorClass = cpm(dotSizeRecipe({ size }), className); + } else { + indicatorClass = cpm(addonSizeRecipe({ size, isCircle }), className); + } + + return ( +
+ {children} +
+ {indicatorContent} +
+
+ ); +}); diff --git a/packages/ui-react/src/componnets/Button/Button.tsx b/packages/ui-react/src/componnets/Button/Button.tsx index ab065cc..cbe080a 100644 --- a/packages/ui-react/src/componnets/Button/Button.tsx +++ b/packages/ui-react/src/componnets/Button/Button.tsx @@ -6,11 +6,6 @@ import { import { Icon } from "../Icon/Icon"; import { SpinnerSvg } from "../../assets/svg/SpinnerSvg"; -import { cpm } from "../../styles/utils/cpm"; -import { itemSizeRecipe } from "../../recipes/itemSizeRecipe"; -import { variantRecipe } from "../../recipes/variantRecipe"; -import { brandRecipe } from "../../recipes/brandRecipe"; -import { inlineSizeRecipe } from "../../recipes/inlineSizeRecipe"; export type ButtonSize = "xs" | "sm" | "md" | "lg"; @@ -50,7 +45,7 @@ export const Button = forwardRef( } = props; const mergedClass = cpm( - itemSizeRecipe({ size, shape, iconOnly }), + itemSizeRecipe({ size, shape, iconOnly, longPadding: false }), variantRecipe({ variant, disabled }), brandRecipe({ brand }), className, diff --git a/packages/ui-react/src/componnets/Icon/Icon.tsx b/packages/ui-react/src/componnets/Icon/Icon.tsx index 48e392d..4f9c7f0 100644 --- a/packages/ui-react/src/componnets/Icon/Icon.tsx +++ b/packages/ui-react/src/componnets/Icon/Icon.tsx @@ -1,20 +1,26 @@ -import { forwardRef, type ComponentPropsWithoutRef } from "react"; -import { Slot } from "../../utils/Slot"; +import { forwardRef } from "react"; import { inlineSizeRecipe } from "../../recipes/inlineSizeRecipe"; import { cpm } from "../../styles/utils/cpm"; +import type { CommonProps } from "../../utils/CommonProps"; +import { Slot } from "../../utils/Slot"; +import { variantRecipe } from "../../recipes/variantRecipe"; -export type IconProps = { - size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl"; -} & ComponentPropsWithoutRef<"svg">; +export type IconProps = CommonProps & { + size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl"; + shape?: "square" | "circle"; +} & { + onClick?: () => void; +}; -export const Icon = forwardRef((props, ref) => { - const { size = "md", className = "", children, ...rest } = props; - const mergedClass = cpm(inlineSizeRecipe({ size }), className); +export const Icon = forwardRef((props, ref) => { + const { size = "md", className = "", children, shape, ...rest } = props; + + const mergedClass = cpm(inlineSizeRecipe({ size, shape }), className); return ( - - {children} - + + {children} + ); }); diff --git a/packages/ui-react/src/componnets/Tag/Tag.tsx b/packages/ui-react/src/componnets/Tag/Tag.tsx new file mode 100644 index 0000000..d08a0e3 --- /dev/null +++ b/packages/ui-react/src/componnets/Tag/Tag.tsx @@ -0,0 +1,62 @@ +import { cpm } from "../../styles/utils/cpm"; +import { brandRecipe } from "../../recipes/brandRecipe"; +import { variantRecipe } from "../../recipes/variantRecipe"; +import { downSizeXsTo3xl } from "../../utils/downSizeSmTo2xl"; +import { itemSizeRecipe } from "../../recipes/itemSizeRecipe"; +import { Icon } from "../Icon/Icon"; +import { CloseSvg } from "../../assets/svg/CloseSvg"; +import type { CommonProps } from "../../utils/CommonProps"; + +export type TagProps = CommonProps & { + size?: "sm" | "md" | "lg"; + variant?: "filled" | "outline"; + brand?: "success" | "danger" | "info" | "warning" | "emphasize"; +} & { + checkable?: boolean; + checked?: boolean; + onCheck?: (checked: boolean) => void; +} & { + closable?: boolean; + onClose?: () => void; +}; + +export const Tag = (props: TagProps) => { + const { + className = "", + children, + size: defaultSize = "md", + brand = "info", + disabled = false, + onClose, + ...rest + } = props; + + const size = downSizeXsTo3xl(defaultSize, 1); + + const mergedClass = cpm( + itemSizeRecipe({ size }), + variantRecipe({ variant: "subtle", disabled, clickable: false }), + brandRecipe({ brand }), + "rounded--full", + className, + ); + + const closeIconClase = cpm( + variantRecipe({ variant: "ghost", disabled }), + brandRecipe({ brand: "emphasize" }), + ); + + return ( +
+ {children} + + + +
+ ); +}; diff --git a/packages/ui-react/src/index.css b/packages/ui-react/src/index.css index ad71dd2..185a30d 100644 --- a/packages/ui-react/src/index.css +++ b/packages/ui-react/src/index.css @@ -3,12 +3,14 @@ @import './styles/utility/size-insensitive/align-items'; @import './styles/utility/size-insensitive/align-self'; @import './styles/utility/size-insensitive/animation'; +@import './styles/utility/size-insensitive/background'; @import './styles/utility/size-insensitive/box-decoration'; @import './styles/utility/size-insensitive/box-inside'; @import './styles/utility/size-insensitive/box-sizing'; @import './styles/utility/size-insensitive/brand'; @import './styles/utility/size-insensitive/break-after'; @import './styles/utility/size-insensitive/break-before'; +@import './styles/utility/size-insensitive/color'; @import './styles/utility/size-insensitive/cursor'; @import './styles/utility/size-insensitive/display'; @import './styles/utility/size-insensitive/drop-shadow'; @@ -33,5 +35,6 @@ @import './styles/utility/size-sensitive/gap'; @import './styles/utility/size-sensitive/height'; @import './styles/utility/size-sensitive/margin'; +@import './styles/utility/size-sensitive/min-width'; @import './styles/utility/size-sensitive/padding'; @import './styles/utility/size-sensitive/width'; \ No newline at end of file diff --git a/packages/ui-react/src/index.ts b/packages/ui-react/src/index.ts index 0e763a6..cbcfc65 100644 --- a/packages/ui-react/src/index.ts +++ b/packages/ui-react/src/index.ts @@ -2,6 +2,7 @@ import './index.css'; export * from './assets/svg/BoldSvg'; export * from './assets/svg/CheckIndicatorSvg'; export * from './assets/svg/ChevronRightSvg'; +export * from './assets/svg/CloseSvg'; export * from './assets/svg/CutSvg'; export * from './assets/svg/DownloadSvg'; export * from './assets/svg/FileSvg'; @@ -18,15 +19,20 @@ export * from './assets/svg/UserSvg'; export * from './assets/svg/VolumeHighSvg'; export * from './assets/svg/VolumeLowSvg'; export * from './assets/svg/VolumeMuteSvg'; +export * from './componnets/Badge/Badge'; export * from './componnets/Button/Button'; export * from './componnets/Icon/Icon'; +export * from './componnets/Tag/Tag'; +export * from './recipes/addonSizeRecipe'; export * from './recipes/brandRecipe'; +export * from './recipes/dotSizeRecipe'; export * from './recipes/inlineSizeRecipe'; export * from './recipes/itemSizeRecipe'; export * from './recipes/variantRecipe'; export * from './styles/utils/cpm'; export * from './styles/utils/cvr'; export * from './utils/camelToKebab'; +export * from './utils/CommonProps'; +export * from './utils/downSizeSmTo2xl'; export * from './utils/mergeProps'; -export * from './utils/Slot'; -export * from './utils/useSlotsRegistry'; \ No newline at end of file +export * from './utils/Slot'; \ No newline at end of file diff --git a/packages/ui-react/src/recipes/inlineSizeRecipe.ts b/packages/ui-react/src/recipes/inlineSizeRecipe.ts deleted file mode 100644 index 2b06111..0000000 --- a/packages/ui-react/src/recipes/inlineSizeRecipe.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { cvr } from "../styles/utils/cvr"; - -export const inlineSizeRecipe = cvr({ - base: "display--flex flex--nowrap justify--center items--center", - variants: { - size: { - xs: "text--xs h--inline-xs gap--xs", - sm: "text--sm h--inline-sm gap--sm", - md: "text--md h--inline-md gap--md", - lg: "text--lg h--inline-lg gap--lg", - xl: "text--xl h--inline-xl gap--xl", - "2xl": "text--2xl h--inline-2xl gap--2xl", - }, - }, -}); diff --git a/packages/ui-react/src/styles/utility/size-insensitive/variant.css b/packages/ui-react/src/styles/utility/size-insensitive/variant.css deleted file mode 100644 index 55705d9..0000000 --- a/packages/ui-react/src/styles/utility/size-insensitive/variant.css +++ /dev/null @@ -1,206 +0,0 @@ -@layer utility { - .variant--filled { - --filled-fg: var(--color-white); - --filled-fg-hover: var(--color-white); - --filled-fg-active: var(--color-white); - --filled-bg: var(--brand-bg); - --filled-bg-hover: var(--brand-bg-hover); - --filled-bg-active: var(--brand-bg-active); - --filled-border-color: var(--color-transparent); - - color: var(--filled-fg); - background-color: var(--filled-bg); - border-color: var(--filled-border-color); - - &:hover { - background-color: var(--filled-bg-hover); - color: var(--filled-fg-hover); - } - - &:active { - background-color: var(--filled-bg-active); - color: var(--filled-fg-active); - } - - &:focus-visible { - background-color: var(--filled-bg-hover); - color: var(--filled-fg-hover); - } - } - - .variant--outline { - --outline-fg: var(--brand-bg); - --outline-fg-hover: var(--brand-bg); - --outline-fg-active: var(--brand-bg); - --outline-bg: var(--color-transparent); - --outline-bg-hover: var(--brand-bg-low); - --outline-bg-active: var(--brand-bg-low-hover); - --outline-border-color: var(--brand-bg); - - color: var(--outline-fg); - background-color: var(--outline-bg); - border: solid 1px; - border-color: var(--outline-border-color); - - &:hover { - background-color: var(--outline-bg-hover); - color: var(--outline-fg-hover); - } - - &:active { - background-color: var(--outline-bg-active); - color: var(--outline-fg-active); - } - - &:focus-visible { - background-color: var(--outline-bg-hover); - color: var(--outline-fg-hover); - } - } - - .variant--subtle { - --subtle-fg: var(--brand-bg); - --subtle-fg-hover: var(--brand-bg); - --subtle-fg-active: var(--brand-bg); - --subtle-bg: var(--brand-bg-low); - --subtle-bg-hover: var(--brand-bg-low-hover); - --subtle-bg-active: var(--brand-bg-low-active); - --subtle-border-color: var(--color-transparent); - - color: var(--subtle-fg); - background-color: var(--subtle-bg); - border-color: var(--subtle-border-color); - - &:hover { - background-color: var(--subtle-bg-hover); - color: var(--subtle-fg-hover); - } - - &:active { - background-color: var(--subtle-bg-active); - color: var(--subtle-fg-active); - } - - &:focus-visible { - background-color: var(--subtle-bg-hover); - color: var(--subtle-fg-hover); - } - } - - .variant--ghost { - --ghost-fg: var(--brand-bg); - --ghost-fg-hover: var(--brand-bg); - --ghost-fg-active: var(--brand-bg); - --ghost-bg: var(--color-transparent); - --ghost-bg-hover: var(--brand-bg-low); - --ghost-bg-active: var(--brand-bg-low-hover); - --ghost-border-color: var(--color-transparent); - - color: var(--ghost-fg); - background-color: var(--ghost-bg); - border-color: var(--ghost-border-color); - - &:hover { - background-color: var(--ghost-bg-hover); - color: var(--ghost-fg-hover); - } - - &:active { - background-color: var(--ghost-bg-active); - color: var(--ghost-fg-active); - } - - &:focus-visible { - background-color: var(--ghost-bg-hover); - color: var(--ghost-fg-hover); - } - } - - .variant--filled-disabled { - color: var(--disabled-fg); - background-color: var(--disabled-bg); - border-color: var(--disabled-border-color); - filter: grayscale(100%); - - &:hover { - color: var(--disabled-fg); - background-color: var(--disabled-bg); - border-color: var(--disabled-border-color); - filter: grayscale(100%); - } - - &:active { - color: var(--disabled-fg); - background-color: var(--disabled-bg); - border-color: var(--disabled-border-color); - filter: grayscale(100%); - } - - &:focus-visible { - color: var(--disabled-fg); - background-color: var(--disabled-bg); - border-color: var(--disabled-border-color); - filter: grayscale(100%); - } - } - - .variant--outline-disabled { - color: var(--disabled-fg); - background-color: var(--disabled-bg); - border: solid 1px; - border-color: var(--disabled-border-color); - filter: grayscale(100%); - - &:hover { - color: var(--disabled-fg); - background-color: var(--disabled-bg); - border: solid 1px; - border-color: var(--disabled-border-color); - filter: grayscale(100%); - } - - &:active { - color: var(--disabled-fg); - background-color: var(--disabled-bg); - border: solid 1px; - border-color: var(--disabled-border-color); - filter: grayscale(100%); - } - - &:focus-visible { - color: var(--disabled-fg); - background-color: var(--disabled-bg); - border: solid 1px; - border-color: var(--disabled-border-color); - filter: grayscale(100%); - } - } - - .variant--ghost-disabled { - color: var(--ghost-fg); - background-color: var(--ghost-bg); - border-color: var(--ghost-border-color); - filter: grayscale(50%); - - &:hover { - color: var(--ghost-fg); - background-color: var(--ghost-bg); - border-color: var(--ghost-border-color); - filter: grayscale(50%); - } - - &:active { - color: var(--ghost-fg); - background-color: var(--ghost-bg); - border-color: var(--ghost-border-color); - filter: grayscale(50%); - } - - &:focus-visible { - color: var(--ghost-fg); - background-color: var(--ghost-bg); - border-color: var(--ghost-border-color); - filter: grayscale(50%); - } - } -} diff --git a/packages/ui-react/src/styles/utility/size-sensitive/font-size.css b/packages/ui-react/src/styles/utility/size-sensitive/font-size.css deleted file mode 100644 index 3ca5c39..0000000 --- a/packages/ui-react/src/styles/utility/size-sensitive/font-size.css +++ /dev/null @@ -1,38 +0,0 @@ -@layer utility { - .text--xs { - /* 12px 支持rem字体放大 */ - font-size: var(--font-size-xs); - /* 不能超过 16px */ - line-height: var(--line-height-xs); - } - .text--sm { - /* 14px 支持rem字体放大 */ - font-size: var(--font-size-sm); - /* 不能超过 20px */ - line-height: var(--line-height-sm); - } - .text--md { - /* 16px 支持rem字体放大 */ - font-size: var(--font-size-md); - /* 不能超过 24px */ - line-height: var(--line-height-md); - } - .text--lg { - /* 18px 支持rem字体放大 */ - font-size: var(--font-size-lg); - /* 不能超过 28px */ - line-height: var(--line-height-lg); - } - .text--xl { - /* 24px 支持rem字体放大 */ - font-size: var(--font-size-2xl); - /* 不能超过 32px */ - line-height: var(--line-height-2xl); - } - .text--2xl { - /* 30px 支持rem字体放大 */ - font-size: var(--font-size-2xl); - /* 不能超过 36px */ - line-height: var(--line-height-2xl); - } -} diff --git a/packages/ui-react/src/styles/utility/size-sensitive/font-weight.css b/packages/ui-react/src/styles/utility/size-sensitive/font-weight.css deleted file mode 100644 index 17b4754..0000000 --- a/packages/ui-react/src/styles/utility/size-sensitive/font-weight.css +++ /dev/null @@ -1,20 +0,0 @@ -@layer utility { - .font-weight--light { - font-weight: 300; - } - .font-weight--normal { - font-weight: 400; - } - .font-weight--extranormal { - font-weight: 500; - } - .font-weight--semibold { - font-weight: 600; - } - .font-weight--bold { - font-weight: 700; - } - .font-weight--extrabold { - font-weight: 700; - } -} diff --git a/packages/ui-react/src/styles/utility/size-sensitive/gap.css b/packages/ui-react/src/styles/utility/size-sensitive/gap.css deleted file mode 100644 index 967acf9..0000000 --- a/packages/ui-react/src/styles/utility/size-sensitive/gap.css +++ /dev/null @@ -1,23 +0,0 @@ -@layer utility { - .gap--xs { - /* 2px */ - gap: calc(var(--spacing)); - } - .gap--sm { - /* 4px */ - gap: calc(var(--spacing) * 2); - } - .gap--md { - /* 6px */ - gap: calc(var(--spacing) * 3); - } - .gap--lg { - gap: calc(var(--spacing) * 4); - } - .gap--xl { - gap: calc(var(--spacing) * 5); - } - .gap--2xl { - gap: calc(var(--spacing) * 6); - } -} diff --git a/packages/ui-react/src/styles/utility/size-sensitive/height.css b/packages/ui-react/src/styles/utility/size-sensitive/height.css deleted file mode 100644 index e51ee28..0000000 --- a/packages/ui-react/src/styles/utility/size-sensitive/height.css +++ /dev/null @@ -1,58 +0,0 @@ -@layer utility { - .h--item-xs { - /* 24px minimum touch size for text line */ - height: var(--height-item-xs); - } - - .h--item-sm { - /* 28px save space for most used size */ - height: var(--height-item-sm); - } - - .h--item-md { - /* 34px most used size */ - height: var(--height-item-md); - } - - .h--item-lg { - /* 44px maximum touch size without waste */ - height: var(--height-item-lg); - } - - .h--item-xl { - /* 56px section-header bar */ - height: var(--height-item-xl); - } - - .h--item-2xl { - /* 64px navigation bar */ - height: var(--height-item-2xl); - } - - /* -------------- */ - .h--inline-xs { - /* 16px */ - height: calc(var(--font-size-xs) * var(--line-height-xs)); - } - - .h--inline-sm { - /* 20px */ - height: calc(var(--font-size-sm) * var(--line-height-sm)); - } - - .h--inline-md { - height: calc(var(--font-size-md) * var(--line-height-md)); - } - - .h--inline-lg { - height: calc(var(--font-size-lg) * var(--line-height-lg)); - } - - .h--inline-xl { - height: calc(var(--font-size-xl) * var(--line-height-xl)); - } - - .h--inline-2xl { - height: calc(var(--font-size-2xl) * var(--line-height-2xl)); - } -} \ No newline at end of file diff --git a/packages/ui-react/src/utils/CommonProps.ts b/packages/ui-react/src/utils/CommonProps.ts new file mode 100644 index 0000000..8f65800 --- /dev/null +++ b/packages/ui-react/src/utils/CommonProps.ts @@ -0,0 +1,8 @@ +import type { CSSProperties, ReactNode } from "react"; + +export type CommonProps = { + className?: string; + style?: CSSProperties; + children?: ReactNode; + disabled?: boolean; +}; diff --git a/packages/ui-react/src/utils/downSizeSmTo2xl.ts b/packages/ui-react/src/utils/downSizeSmTo2xl.ts new file mode 100644 index 0000000..4b08ef2 --- /dev/null +++ b/packages/ui-react/src/utils/downSizeSmTo2xl.ts @@ -0,0 +1,11 @@ +type xsTo3xl = "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl"; + +export function downSizeXsTo3xl( + size: "sm" | "md" | "lg" | "xl" | "2xl", + downLevel: 1 | 2, +): xsTo3xl { + const sizeList = ["xs", "sm", "md", "lg", "xl", "2xl", "3xl"]; + const index = sizeList.indexOf(size); + const returnIndex = index - downLevel; + return sizeList[returnIndex] as xsTo3xl; +} diff --git a/packages/ui-react/src/utils/useSlotsRegistry.ts b/packages/ui-react/src/utils/useSlotsRegistry.ts deleted file mode 100644 index 1314483..0000000 --- a/packages/ui-react/src/utils/useSlotsRegistry.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { useRef, useState } from "react"; - -export type UseSlotsRegistryReturn = { - slots: Partial>; - canRender: boolean; - generateId: (prefix: string) => string; - registerSlot: ( - id: string, - slotName: Names[number], - content: React.ReactNode, - ) => void; - markReady: (id: string) => void; -}; - -type SlotRecord = { - [K in Names[number]]: React.ReactNode[]; -}; - -export function useSlotsRegistry< - const Names extends readonly string[], ->(): UseSlotsRegistryReturn { - type SlotName = Names[number]; - - const [slots, setSlots] = useState>>({}); - const readySet = useRef(new Set()); - const totalSet = useRef(new Set()); - const [canRender, setCanRender] = useState(false); - const [ids, setIds] = useState([]); - - const generateId = (prefix: string): string => { - while (true) { - const rand = Math.random().toString(36).slice(2, 8); - const id = `${prefix}-${rand}`; - if (!ids.includes(id)) { - setIds((prev) => [...prev, id]); - return id; - } - } - }; - - const registerSlot = ( - id: string, - slotName: SlotName, - content: React.ReactNode, - ) => { - totalSet.current.add(id); - - setSlots((prev) => ({ - ...prev, - [slotName]: [...(prev[slotName] ?? []), content], - })); - }; - - const markReady = (id: string) => { - readySet.current.add(id); - - if (readySet.current.size === totalSet.current.size) { - setCanRender(true); - } - }; - - return { - slots, - canRender, - generateId, - registerSlot, - markReady, - }; -} diff --git a/playground/ui-gallery/src/App.tsx b/playground/ui-gallery/src/App.tsx index 8b939ca..edc4e6b 100644 --- a/playground/ui-gallery/src/App.tsx +++ b/playground/ui-gallery/src/App.tsx @@ -1,10 +1,14 @@ +import { BadgeGallery } from "./gallery/BadgeGallery"; import { ButtonGallery } from "./gallery/ButtonGallery"; import "@dg/ui-react/index.css"; +import { TagGallery } from "./gallery/TagGallery"; function App() { return (
+ +
); } diff --git a/playground/ui-gallery/src/common/OW.tsx b/playground/ui-gallery/src/common/OW.tsx index 1cc77b5..9ebd1b9 100644 --- a/playground/ui-gallery/src/common/OW.tsx +++ b/playground/ui-gallery/src/common/OW.tsx @@ -4,6 +4,7 @@ export const OW = ({ children }: { children: ReactNode }) => { return (
{ + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/playground/ui-gallery/src/gallery/ButtonGallery.tsx b/playground/ui-gallery/src/gallery/ButtonGallery.tsx index 947936f..79672f7 100644 --- a/playground/ui-gallery/src/gallery/ButtonGallery.tsx +++ b/playground/ui-gallery/src/gallery/ButtonGallery.tsx @@ -6,7 +6,10 @@ export const ButtonGallery = () => { return ( - + + @@ -18,7 +21,10 @@ export const ButtonGallery = () => { - + + @@ -29,6 +35,36 @@ export const ButtonGallery = () => { Small + + + + + + + + + + + + + + ); }; diff --git a/playground/ui-gallery/src/gallery/TagGallery.tsx b/playground/ui-gallery/src/gallery/TagGallery.tsx new file mode 100644 index 0000000..b6fcb96 --- /dev/null +++ b/playground/ui-gallery/src/gallery/TagGallery.tsx @@ -0,0 +1,18 @@ +import { Tag } from "@dg/ui-react"; +import { IW } from "../common/IW"; +import { OW } from "../common/OW"; + +export const TagGallery = () => { + return ( + + + 写实 + 简约 + 油画 + 赛博朋克 + 星际 + 机械 + + + ); +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7fa454f..9a34f38 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,29 @@ importers: specifier: ^2.8.0 version: 2.9.12 + packages/css: + devDependencies: + '@types/node': + specifier: ^25.6.0 + version: 25.6.2 + tinyglobby: + specifier: ^0.2.16 + version: 0.2.16 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@25.6.2)(typescript@6.0.3) + typescript: + specifier: ^6.0.3 + version: 6.0.3 + vite: + specifier: ^8.0.10 + version: 8.0.12(@types/node@25.6.2)(jiti@2.7.0) + packages/ui-react: dependencies: + '@dg/css': + specifier: workspace:* + version: link:../css react: specifier: ^19 version: 19.2.6