diff --git a/.gitignore b/.gitignore index d0355bc..c9c68df 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .gitea-data dist node_modules +.playwright-mcp \ No newline at end of file diff --git a/README.md b/README.md index da7b6c6..8b91168 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,4 @@ bun run preview bun run test ``` -构建会生成 `dist/theme-gitea-auto.css`,并同步输出到 `.gitea/custom/public/assets/css/theme-gitea-auto.css` 供 Gitea custom 目录使用。 +构建会生成 `dist/theme-gitea-dev.css`,并同步输出到 `.gitea/custom/public/assets/css/theme-gitea-dev.css` 供 Gitea custom 目录使用。 diff --git a/compose.dev.yaml b/compose.dev.yaml index cfab80c..cfac1b1 100644 --- a/compose.dev.yaml +++ b/compose.dev.yaml @@ -9,8 +9,8 @@ services: - GITEA__service_0x2E_explore__DISABLE_USERS_PAGE=true - GITEA__service_0x2E_explore__DISABLE_ORGANIZATIONS_PAGE=true - GITEA__service_0x2E_explore__DISABLE_CODE_PAGE=true - - GITEA__ui__THEMES=gitea-auto - - GITEA__ui__DEFAULT_THEME=gitea-auto + - GITEA__ui__THEMES=gitea-dev + - GITEA__ui__DEFAULT_THEME=gitea-dev restart: always volumes: - ./.gitea-data:/data diff --git a/docs/official-style-map.md b/docs/official-style-map.md new file mode 100644 index 0000000..df17d69 --- /dev/null +++ b/docs/official-style-map.md @@ -0,0 +1,73 @@ +# 官方样式来源映射 + +## 当前基线 + +当前 `gitea-dev` 主题以 Gitea 官方 light 主题为基线。 + +官方主题文件: + +`/.gitea/web_src/css/themes/theme-gitea-light.css` + +项目入口: + +`/styles/tokens/index.ts` + +构建输出: + +`/dist/theme-gitea-dev.css` + +Gitea custom 输出: + +`/.gitea/custom/public/assets/css/theme-gitea-dev.css` + +## 主题层拆解 + +`styles/tokens/` 当前已经把官方 `theme-gitea-light.css` 拆分成本项目自己的 token 模块。构建时不直接读取 `.gitea`,`.gitea` 只作为官方源码参考和测试基线。 + +拆分文件: + +`styles/tokens/theme-meta.ts`:主题显示名称和色彩模式元信息。 + +`styles/tokens/core.ts`:核心 primary、secondary 和基础明暗变量。 + +`styles/tokens/console.ts`:Actions console 和 console 文件使用的颜色。 + +`styles/tokens/named-colors.ts`:red、orange、green、blue 等命名色及明暗变体。 + +`styles/tokens/ansi-colors.ts`:终端 ANSI 颜色。 + +`styles/tokens/semantic-colors.ts`:页面、边框、文本、差异、markup、代码等语义颜色。 + +`styles/tokens/target-colors.ts`:组件和状态面向的目标变量,例如 input、menu、card、button、issue、notification、heatmap 等。 + +`styles/primitives/` 当前保持空。官方基础控件来源主要在 `.gitea/web_src/css/modules/`,例如 `button.css`、`input.css`、`form.css`、`checkbox.css`、`dropdown.css`、`table.css`、`menu.css`、`tippy.css`。 + +`styles/components/` 当前保持空。官方可复用业务组件来源主要在 `.gitea/web_src/css/repo/`、`.gitea/web_src/css/features/`、`.gitea/web_src/css/shared/`,例如 `repo/home-file-list.css`、`repo/clone.css`、`features/heatmap.css`、`features/gitgraph.css`、`shared/flex-list.css`。 + +`styles/pages/` 当前保持空。官方页面级来源主要在 `.gitea/web_src/css/` 根目录,例如 `dashboard.css`、`explore.css`、`install.css`、`org.css`、`repo.css`、`user.css`、`admin.css`、`actions.css`。 + +## 迁移原则 + +第一阶段只迁移官方主题 token,不改任何 primitive、component 或 page 规则。这样 `gitea-dev` 的渲染结果应与官方 `gitea-light` 一致。 + +后续迁移时,如果只是改颜色、阴影、圆角、字体或间距变量,优先放到 `themes/` 或 `styles/tokens/`。 + +如果要改所有按钮、输入框、表单、下拉菜单等基础控件,放到 `styles/primitives/`,并确认这是全站影响。 + +如果只改仓库列表、热力图、动态列表、clone 面板等业务组件,放到 `styles/components/`。 + +如果只改 dashboard、explore、登录页、组织创建页等页面布局,放到 `styles/pages/`。 + +## 校验方式 + +`bun run test` 会执行三步: + +1. 构建 `theme-gitea-dev.css`。 +2. 检查 `dist/` 和 `.gitea/custom/` 输出存在且非空。 +3. 将生成的 CSS 与官方 `theme-gitea-light.css` 经过同样 Lightning CSS 转换后的结果做字节级比较。 + +`bun run docker:test` 会执行三步: + +1. 构建 `theme-gitea-dev.css`。 +2. 启动 Gitea Docker 预览容器。 +3. 检查首页返回 `200`,首页 HTML 加载 `/assets/css/theme-gitea-dev.css`,并确认主题 CSS 内包含官方 light 主题变量。 diff --git a/docs/rules.md b/docs/rules.md index 13afef6..eef73a3 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -6,7 +6,7 @@ ## 目录职责 -`themes/` 放颜色主题和主题 token,例如 `light.ts`。主题文件只定义值,不写 Gitea 选择器。 +`themes/` 预留给后续新增主题源数据。当前官方 light 基线已经拆到 `styles/tokens/`,构建时不直接读取 `.gitea`。 `styles/tokens/` 放最底层设计变量,例如颜色、字号、间距、圆角、阴影、动效时长。这里不应该出现具体页面选择器。 @@ -20,7 +20,7 @@ `src/` 放构建辅助代码、类型和聚合逻辑。这里不直接承载某个具体页面的样式规则。 -`.gitea/` 放 Gitea custom 目录和源代码参考资源。构建产物会输出到 `.gitea/custom/public/assets/css/theme-gitea-auto.css`。 +`.gitea/` 放 Gitea custom 目录和源代码参考资源。构建产物会输出到 `.gitea/custom/public/assets/css/theme-gitea-dev.css`。 `dist/` 放本地构建产物,主要用于检查和 Preview。 @@ -30,15 +30,15 @@ 低层不能依赖高层。`tokens/` 不能依赖 `primitives/`、`components/` 或 `pages/`;`primitives/` 不能依赖页面结构;`components/` 不应该修复具体页面布局。 -避免重复定义颜色、阴影、圆角和间距。优先在 `themes/` 与 `styles/tokens/` 中新增 token,再在其他层使用 `var(--gt-*)`。 +避免重复定义颜色、阴影、圆角和间距。优先在 `styles/tokens/` 中新增或修改 token,再在其他层使用官方兼容的 `var(--color-*)`。 页面级选择器必须足够具体,避免影响全站控件。例如登录页按钮间距问题应该放在登录页或登录组件范围内,不应该修改所有 `.ui.button`。 ## 命名规则 -自定义 CSS 变量统一使用 `--gt-*` 前缀,例如 `--gt-color-accent`、`--gt-radius-md`、`--gt-space-lg`。 +主题 CSS 变量优先保持 Gitea 官方兼容命名,例如 `--color-primary`、`--color-body`、`--color-input-background`。只有新增且无法映射到官方变量的项目私有变量,才使用自定义前缀。 -主题名与 Gitea CSS 文件名保持一致。当前默认主题名是 `gitea-auto`,输出文件是 `theme-gitea-auto.css`。 +主题名与 Gitea CSS 文件名保持一致。当前默认主题名是 `gitea-dev`,输出文件是 `theme-gitea-dev.css`。不要使用 `gitea`、`gitea-auto`、`arc-green` 这类内置主题名,避免 Gitea 加载内置 hashed 资源而不是 custom 主题文件。 样式模块默认导出字符串常量,由 `styles/index.ts` 按 `tokens -> primitives -> components -> pages` 顺序聚合。 @@ -58,6 +58,8 @@ ## 修改流程 +官方样式基线和源码映射见 `docs/official-style-map.md`。当前项目必须先保持 `gitea-dev` 与官方 `theme-gitea-light.css` 一致,再在对应层做增量迁移。 + 新增视觉值时,先判断是否应该成为 token。能复用的值放到 `themes/` 或 `styles/tokens/`。 修改控件外观时,优先检查 `styles/primitives/`,确保不会破坏页面级布局。 diff --git a/package.json b/package.json index f2cc426..f56e733 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dev": "bun scripts/build.ts --watch", "preview": "bun run build && bun scripts/preview.ts", "build:min": "bun scripts/build.ts --minify", - "test": "bun run build && bun scripts/verify-theme.ts", + "test": "bun run build && bun scripts/verify-theme.ts && bun scripts/verify-official-theme.ts", "compose:up": "docker compose -f compose.dev.yaml up -d", "compose:down": "docker compose -f compose.dev.yaml down", "compose:logs": "docker compose -f compose.dev.yaml logs -f server", diff --git a/scripts/build.ts b/scripts/build.ts index be21fa5..62a3719 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -8,13 +8,13 @@ const root = process.cwd(); const minify = process.argv.includes("--minify"); const watchMode = process.argv.includes("--watch"); const outputs = [ - join(root, "dist", "theme-gitea-auto.css"), - join(root, ".gitea", "custom", "public", "assets", "css", "theme-gitea-auto.css"), + join(root, "dist", "theme-gitea-dev.css"), + join(root, ".gitea", "custom", "public", "assets", "css", "theme-gitea-dev.css"), ]; async function build() { const result = transform({ - filename: "theme-gitea-auto.css", + filename: "theme-gitea-dev.css", code: Buffer.from(stylesheet), minify, targets: { diff --git a/scripts/preview.ts b/scripts/preview.ts index 7bb261b..d0d04b8 100644 --- a/scripts/preview.ts +++ b/scripts/preview.ts @@ -10,7 +10,7 @@ const server = Bun.serve({ - + Gitea Theme Preview @@ -29,8 +29,8 @@ const server = Bun.serve({ ); } - if (url.pathname === "/theme-gitea-auto.css") { - return new Response(Bun.file("dist/theme-gitea-auto.css"), { + if (url.pathname === "/theme-gitea-dev.css") { + return new Response(Bun.file("dist/theme-gitea-dev.css"), { headers: { "content-type": "text/css; charset=utf-8" }, }); } diff --git a/scripts/verify-docker.ts b/scripts/verify-docker.ts index c820dea..118351f 100644 --- a/scripts/verify-docker.ts +++ b/scripts/verify-docker.ts @@ -23,10 +23,15 @@ async function waitFor(url: string) { } const home = await waitFor(baseUrl); -const theme = await waitFor(`${baseUrl}/assets/css/theme-gitea-auto.css`); +const html = await home.text(); +const theme = await waitFor(`${baseUrl}/assets/css/theme-gitea-dev.css`); const css = await theme.text(); -if (!css.includes("--gt-color-accent")) { +if (!html.includes("/assets/css/theme-gitea-dev.css")) { + throw new Error("Gitea page is not loading the custom theme-gitea-dev.css file"); +} + +if (!css.includes("--color-primary: #4183c4")) { throw new Error("theme css is reachable but does not contain generated tokens"); } diff --git a/scripts/verify-official-theme.ts b/scripts/verify-official-theme.ts new file mode 100644 index 0000000..4d0b699 --- /dev/null +++ b/scripts/verify-official-theme.ts @@ -0,0 +1,30 @@ +import { readFile } from "node:fs/promises"; +import { join } from "node:path"; +import { transform } from "lightningcss"; + +const root = process.cwd(); +const officialPath = join(root, ".gitea", "web_src", "css", "themes", "theme-gitea-light.css"); +const generatedPath = join(root, "dist", "theme-gitea-dev.css"); + +const normalize = (css: Uint8Array | string) => + Buffer.from(css).toString("utf8").replace(/\r\n/g, "\n").trim(); + +const official = await readFile(officialPath); +const generated = await readFile(generatedPath); + +const transformedOfficial = transform({ + filename: "theme-gitea-dev.css", + code: official, + minify: process.argv.includes("--minify"), + targets: { + chrome: 108 << 16, + firefox: 108 << 16, + safari: 16 << 16, + }, +}); + +if (normalize(transformedOfficial.code) !== normalize(generated)) { + throw new Error("generated theme differs from official theme-gitea-light.css baseline"); +} + +console.log("generated theme matches official theme-gitea-light.css baseline"); diff --git a/scripts/verify-theme.ts b/scripts/verify-theme.ts index da94e49..a13e9ab 100644 --- a/scripts/verify-theme.ts +++ b/scripts/verify-theme.ts @@ -3,8 +3,8 @@ import { stat } from "node:fs/promises"; import { join } from "node:path"; const requiredOutputs = [ - join(process.cwd(), "dist", "theme-gitea-auto.css"), - join(process.cwd(), ".gitea", "custom", "public", "assets", "css", "theme-gitea-auto.css"), + join(process.cwd(), "dist", "theme-gitea-dev.css"), + join(process.cwd(), ".gitea", "custom", "public", "assets", "css", "theme-gitea-dev.css"), ]; for (const output of requiredOutputs) { diff --git a/src/css.ts b/src/css.ts deleted file mode 100644 index 52d2f02..0000000 --- a/src/css.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { ThemeScale, ThemeTokens } from "./theme-types"; - -const toKebab = (value: string) => - value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`); - -const scaleToVars = (group: string, scale: ThemeScale) => - Object.entries(scale) - .map(([key, value]) => ` --gt-${group}-${toKebab(key)}: ${value};`) - .join("\n"); - -export const themeToRootVars = (theme: ThemeTokens) => { - const groups = Object.entries(theme) - .filter(([key]) => key !== "name") - .map(([group, scale]) => scaleToVars(group, scale as ThemeScale)); - - return `:root,\n.theme-${theme.name} {\n${groups.join("\n")}\n}`; -}; diff --git a/src/theme-types.ts b/src/theme-types.ts deleted file mode 100644 index 315c5d1..0000000 --- a/src/theme-types.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type ThemeScale = Record; - -export interface ThemeTokens { - name: string; - color: ThemeScale; - radius: ThemeScale; - shadow: ThemeScale; - font: ThemeScale; - space: ThemeScale; - motion: ThemeScale; -} diff --git a/styles/components/index.ts b/styles/components/index.ts index dfebc48..cb514af 100644 --- a/styles/components/index.ts +++ b/styles/components/index.ts @@ -1,26 +1 @@ -export const components = ` -.following.bar.light { - background: color-mix(in srgb, var(--gt-color-surface) 92%, transparent); - border-bottom: 1px solid var(--gt-color-border); - backdrop-filter: blur(14px); -} - -.repository .header-wrapper, -.repository.file.list #repo-files-table { - border-radius: var(--gt-radius-lg); - border: 1px solid var(--gt-color-border); - box-shadow: var(--gt-shadow-sm); -} - -.feeds .news, -.dashboard.feeds .news { - border-radius: var(--gt-radius-lg); - background: var(--gt-color-surface); -} - -.user.signin .ui.form, -.user.signup .ui.form { - border-radius: var(--gt-radius-lg); - box-shadow: var(--gt-shadow-md); -} -`; +export const components = ""; diff --git a/styles/pages/index.ts b/styles/pages/index.ts index de87299..6a0e1dc 100644 --- a/styles/pages/index.ts +++ b/styles/pages/index.ts @@ -1,22 +1 @@ -export const pages = ` -.page-content.dashboard { - padding-top: var(--gt-space-lg); -} - -.page-content.explore { - padding-top: var(--gt-space-xl); -} - -.user.signin .page-content, -.user.signup .page-content { - min-height: calc(100vh - 8rem); - display: grid; - place-items: center; -} - -.organization.new.org .page-content, -.organization.new.team .page-content { - max-width: 72rem; - margin-inline: auto; -} -`; +export const pages = ""; diff --git a/styles/primitives/index.ts b/styles/primitives/index.ts index abca5a3..4f8ec92 100644 --- a/styles/primitives/index.ts +++ b/styles/primitives/index.ts @@ -1,51 +1 @@ -export const primitives = ` -body { - color: var(--gt-color-text); - background: - radial-gradient(circle at 12% 8%, rgb(29 111 95 / 0.12), transparent 28rem), - linear-gradient(180deg, var(--gt-color-canvas), #efe6d4); - font-family: var(--gt-font-sans); -} - -a { - color: var(--gt-color-accent); -} - -.ui.button, -button.ui.button { - border-radius: var(--gt-radius-md); - border-color: var(--gt-color-border); - box-shadow: var(--gt-shadow-sm); - transition: - background-color var(--gt-motion-fast) ease, - border-color var(--gt-motion-fast) ease, - box-shadow var(--gt-motion-fast) ease; -} - -.ui.primary.button, -.ui.green.button { - background: var(--gt-color-accent); - color: #ffffff; -} - -.ui.primary.button:hover, -.ui.green.button:hover { - background: var(--gt-color-accent-hover); -} - -.ui.input > input, -.ui.form input:not([type]), -.ui.form input[type="text"], -.ui.form input[type="password"], -.ui.form input[type="email"], -.ui.form textarea { - border-radius: var(--gt-radius-md); - border-color: var(--gt-color-border); - background: var(--gt-color-surface-raised); -} - -.ui.dropdown, -.tippy-box { - border-radius: var(--gt-radius-md); -} -`; +export const primitives = ""; diff --git a/styles/tokens/ansi-colors.ts b/styles/tokens/ansi-colors.ts new file mode 100644 index 0000000..aed93b1 --- /dev/null +++ b/styles/tokens/ansi-colors.ts @@ -0,0 +1 @@ +export const ansiColorTokens = " /* ansi colors used for actions console and console files */\n --color-ansi-black: #1e2327;\n --color-ansi-red: #cc4848;\n --color-ansi-green: #87ab63;\n --color-ansi-yellow: #cc9903;\n --color-ansi-blue: #3a8ac6;\n --color-ansi-magenta: #d22e8b;\n --color-ansi-cyan: #00918a;\n --color-ansi-white: var(--color-console-fg-subtle);\n --color-ansi-bright-black: #46494d;\n --color-ansi-bright-red: #d15a5a;\n --color-ansi-bright-green: #93b373;\n --color-ansi-bright-yellow: #eaaf03;\n --color-ansi-bright-blue: #4e96cc;\n --color-ansi-bright-magenta: #d74397;\n --color-ansi-bright-cyan: #00b6ad;\n --color-ansi-bright-white: var(--color-console-fg);"; diff --git a/styles/tokens/console.ts b/styles/tokens/console.ts new file mode 100644 index 0000000..e9912ca --- /dev/null +++ b/styles/tokens/console.ts @@ -0,0 +1 @@ +export const consoleTokens = " /* console colors - used for actions console and console files */\n --color-console-fg: #0d1117;\n --color-console-fg-subtle: #40474d;\n --color-console-bg: #ffffff;\n --color-console-border: #d0d7de;\n --color-console-hover-bg: #f1f3f5;\n --color-console-active-bg: #d0d7de;\n --color-console-menu-bg: #f8f9fb;\n --color-console-menu-border: #d0d7de;\n --color-console-link: #5c656d;"; diff --git a/styles/tokens/core.ts b/styles/tokens/core.ts new file mode 100644 index 0000000..aeaebf4 --- /dev/null +++ b/styles/tokens/core.ts @@ -0,0 +1 @@ +export const coreTokens = " --is-dark-theme: false;\n --color-primary: #4183c4;\n --color-primary-contrast: #ffffff;\n --color-primary-dark-1: #3876b3;\n --color-primary-dark-2: #31699f;\n --color-primary-dark-3: #2b5c8b;\n --color-primary-dark-4: #254f77;\n --color-primary-dark-5: #193450;\n --color-primary-dark-6: #0c1a28;\n --color-primary-dark-7: #04080c;\n --color-primary-light-1: #548fca;\n --color-primary-light-2: #679cd0;\n --color-primary-light-3: #7aa8d6;\n --color-primary-light-4: #8db5dc;\n --color-primary-light-5: #b3cde7;\n --color-primary-light-6: #d9e6f3;\n --color-primary-light-7: #f4f8fb;\n --color-primary-alpha-10: #4183c419;\n --color-primary-alpha-20: #4183c433;\n --color-primary-alpha-30: #4183c44b;\n --color-primary-alpha-40: #4183c466;\n --color-primary-alpha-50: #4183c480;\n --color-primary-alpha-60: #4183c499;\n --color-primary-alpha-70: #4183c4b3;\n --color-primary-alpha-80: #4183c4cc;\n --color-primary-alpha-90: #4183c4e1;\n --color-primary-hover: var(--color-primary-dark-1);\n --color-primary-active: var(--color-primary-dark-2);\n --color-secondary: #d0d7de;\n --color-secondary-dark-1: #c7ced5;\n --color-secondary-dark-2: #b9c0c7;\n --color-secondary-dark-3: #99a0a7;\n --color-secondary-dark-4: #899097;\n --color-secondary-dark-5: #7a8188;\n --color-secondary-dark-6: #6a7178;\n --color-secondary-dark-7: #5b6269;\n --color-secondary-dark-8: #4b5259;\n --color-secondary-dark-9: #3c434a;\n --color-secondary-dark-10: #2c333a;\n --color-secondary-dark-11: #1d242b;\n --color-secondary-dark-12: #0d141b;\n --color-secondary-dark-13: #00040b;\n --color-secondary-light-1: #dee5ec;\n --color-secondary-light-2: #e4ebf2;\n --color-secondary-light-3: #ebf2f9;\n --color-secondary-light-4: #f1f8ff;\n --color-secondary-alpha-10: #d0d7de19;\n --color-secondary-alpha-20: #d0d7de33;\n --color-secondary-alpha-30: #d0d7de4b;\n --color-secondary-alpha-40: #d0d7de66;\n --color-secondary-alpha-50: #d0d7de80;\n --color-secondary-alpha-60: #d0d7de99;\n --color-secondary-alpha-70: #d0d7deb3;\n --color-secondary-alpha-80: #d0d7decc;\n --color-secondary-alpha-90: #d0d7dee1;\n --color-secondary-button: var(--color-secondary-dark-4);\n --color-secondary-hover: var(--color-secondary-dark-5);\n --color-secondary-active: var(--color-secondary-dark-6);"; diff --git a/styles/tokens/index.ts b/styles/tokens/index.ts index d7da1eb..5bb89f6 100644 --- a/styles/tokens/index.ts +++ b/styles/tokens/index.ts @@ -1,4 +1,18 @@ -import { themeToRootVars } from "../../src/css"; -import { lightTheme } from "../../themes/light"; +import { ansiColorTokens } from "./ansi-colors"; +import { consoleTokens } from "./console"; +import { coreTokens } from "./core"; +import { namedColorTokens } from "./named-colors"; +import { semanticColorTokens } from "./semantic-colors"; +import { targetColorTokens } from "./target-colors"; +import { themeMeta } from "./theme-meta"; -export const tokens = themeToRootVars(lightTheme); +const rootTokens = [ + coreTokens, + consoleTokens, + namedColorTokens, + ansiColorTokens, + semanticColorTokens, + targetColorTokens, +].join("\n"); + +export const tokens = `${themeMeta}\n\n:root {\n${rootTokens}\n}`; diff --git a/styles/tokens/named-colors.ts b/styles/tokens/named-colors.ts new file mode 100644 index 0000000..4da50dd --- /dev/null +++ b/styles/tokens/named-colors.ts @@ -0,0 +1 @@ +export const namedColorTokens = " /* named colors */\n --color-red: #db2828;\n --color-orange: #f2711c;\n --color-yellow: #fbbd08;\n --color-olive: #b5cc18;\n --color-green: #21ba45;\n --color-teal: #00b5ad;\n --color-blue: #2185d0;\n --color-violet: #6435c9;\n --color-purple: #a333c8;\n --color-pink: #e03997;\n --color-brown: #a5673f;\n --color-black: #1d2328;\n /* light variants - produced via Sass scale-color(color, $lightness: +25%) */\n --color-red-light: #e45e5e;\n --color-orange-light: #f59555;\n --color-yellow-light: #fcce46;\n --color-olive-light: #d3e942;\n --color-green-light: #46de6a;\n --color-teal-light: #08fff4;\n --color-blue-light: #51a5e3;\n --color-violet-light: #8b67d7;\n --color-purple-light: #bb64d8;\n --color-pink-light: #e86bb1;\n --color-brown-light: #c58b66;\n --color-black-light: #4b5b68;\n /* dark 1 variants - produced via Sass scale-color(color, $lightness: -10%) */\n --color-red-dark-1: #c82121;\n --color-orange-dark-1: #e6630d;\n --color-yellow-dark-1: #e5ac04;\n --color-olive-dark-1: #a3b816;\n --color-green-dark-1: #1ea73e;\n --color-teal-dark-1: #00a39c;\n --color-blue-dark-1: #1e78bb;\n --color-violet-dark-1: #5a30b5;\n --color-purple-dark-1: #932eb4;\n --color-pink-dark-1: #db228a;\n --color-brown-dark-1: #955d39;\n --color-black-dark-1: #2c3339;\n /* dark 2 variants - produced via Sass scale-color(color, $lightness: -20%) */\n --color-red-dark-2: #b11e1e;\n --color-orange-dark-2: #cc580c;\n --color-yellow-dark-2: #cc9903;\n --color-olive-dark-2: #91a313;\n --color-green-dark-2: #1a9537;\n --color-teal-dark-2: #00918a;\n --color-blue-dark-2: #1a6aa6;\n --color-violet-dark-2: #502aa1;\n --color-purple-dark-2: #8229a0;\n --color-pink-dark-2: #c21e7b;\n --color-brown-dark-2: #845232;\n --color-black-dark-2: #131619;"; diff --git a/styles/tokens/semantic-colors.ts b/styles/tokens/semantic-colors.ts new file mode 100644 index 0000000..89f4999 --- /dev/null +++ b/styles/tokens/semantic-colors.ts @@ -0,0 +1 @@ +export const semanticColorTokens = " /* other colors */\n --color-grey: #697077;\n --color-grey-light: #7c838a;\n --color-gold: #a1882b;\n --color-white: #ffffff;\n --color-diff-added-fg: #21ba45;\n --color-diff-added-linenum-bg: #d1f8d9;\n --color-diff-added-row-bg: #e6ffed;\n --color-diff-added-row-border: #e6ffed;\n --color-diff-added-word-bg: #acf2bd;\n --color-diff-moved-row-bg: #f1f8d1;\n --color-diff-moved-row-border: #d0e27f;\n --color-diff-removed-fg: #db2828;\n --color-diff-removed-linenum-bg: #ffcecb;\n --color-diff-removed-row-bg: #ffeef0;\n --color-diff-removed-row-border: #f1c0c0;\n --color-diff-removed-word-bg: #fdb8c0;\n --color-diff-inactive: #f0f2f4;\n --color-error-border: #ff818266;\n --color-error-bg: #ffebe9;\n --color-error-bg-active: #ffcecb;\n --color-error-bg-hover: #ffdcd7;\n --color-error-text: #d1242f;\n --color-success-border: #4ac26b66;\n --color-success-bg: #dafbe1;\n --color-success-text: #1a7f37;\n --color-warning-border: #d4a72c66;\n --color-warning-bg: #fff8c5;\n --color-warning-text: #9a6700;\n --color-info-border: #54aeff66;\n --color-info-bg: #ddf4ff;\n --color-info-text: #0969da;\n --color-priority-border: #b9a1ff66;\n --color-priority-bg: #f3e7ff;\n --color-priority-text: #8250df;\n --color-red-badge: #db2828;\n --color-red-badge-bg: #db28281a;\n --color-red-badge-hover-bg: #db28284d;\n --color-green-badge: #21ba45;\n --color-green-badge-bg: #21ba451a;\n --color-green-badge-hover-bg: #21ba454d;\n --color-yellow-badge: #fbbd08;\n --color-yellow-badge-bg: #fbbd081a;\n --color-yellow-badge-hover-bg: #fbbd084d;\n --color-orange-badge: #f2711c;\n --color-orange-badge-bg: #f2711c1a;\n --color-orange-badge-hover-bg: #f2711c4d;\n --color-git: #f05133;\n --color-logo: #609926;"; diff --git a/styles/tokens/target-colors.ts b/styles/tokens/target-colors.ts new file mode 100644 index 0000000..0c05f6d --- /dev/null +++ b/styles/tokens/target-colors.ts @@ -0,0 +1 @@ +export const targetColorTokens = " /* target-based colors */\n --color-body: #ffffff;\n --color-box-header: #f1f3f5;\n --color-box-body: #ffffff;\n --color-box-body-highlight: #ecf5fd;\n --color-text-dark: #01050a;\n --color-text: #181c21;\n --color-text-light: #30363b;\n --color-text-light-1: #40474d;\n --color-text-light-2: #5b6167;\n --color-text-light-3: #747c84;\n --color-footer: var(--color-nav-bg);\n --color-timeline: #d0d7de;\n --color-input-text: var(--color-text-dark);\n --color-input-background: #fff;\n --color-input-toggle-background: #d0d7de;\n --color-input-border: var(--color-secondary-dark-1);\n --color-light: #00001706;\n --color-light-border: #0000171d;\n --color-hover: #00001708;\n --color-hover-opaque: #f1f3f5; /* TODO: color-mix(in srgb, var(--color-body), var(--color-hover)); */\n --color-active: #00001714;\n --color-menu: #f8f9fb;\n --color-card: #f8f9fb;\n --color-markup-table-row: #0030600a;\n --color-markup-code-block: #00306010;\n --color-markup-code-inline: #00306012;\n --color-button: #f8f9fb;\n --color-code-bg: #fafdff;\n --color-shadow: #00001726;\n --color-shadow-opaque: #c7ced5;\n --color-secondary-bg: #f2f5f8;\n --color-expand-button: #cfe8fa;\n --color-placeholder-text: var(--color-text-light-3);\n --color-editor-line-highlight: var(--color-secondary-alpha-30);\n --color-editor-selection: var(--color-primary-alpha-30);\n --color-project-column-bg: var(--color-secondary-light-4);\n --color-caret: var(--color-text-dark);\n --color-reaction-bg: #0000170a;\n --color-reaction-hover-bg: var(--color-primary-light-5);\n --color-reaction-active-bg: var(--color-primary-light-6);\n --color-tooltip-text: #fbfdff;\n --color-tooltip-bg: #000017f0;\n --color-nav-bg: #f6f7fa;\n --color-nav-hover-bg: var(--color-secondary-light-1);\n --color-nav-text: var(--color-text);\n --color-secondary-nav-bg: #f9fafb;\n --color-label-text: var(--color-text);\n --color-label-bg: #949da64b;\n --color-label-hover-bg: #949da6a0;\n --color-label-active-bg: #949da6ff;\n --color-accent: var(--color-primary-light-1);\n --color-small-accent: var(--color-primary-light-6);\n --color-highlight-fg: #eed200;\n --color-highlight-bg: #f5efc5;\n --color-overlay-backdrop: #080808c0;\n --color-danger: var(--color-red);\n --color-transparency-grid-light: #fafafa;\n --color-transparency-grid-dark: #e2e2e2;\n --color-workflow-edge-hover: #b1b7bd;\n --color-syntax-keyword: #a73a00;\n --color-syntax-bool: #076872;\n --color-syntax-control: #7d5700;\n --color-syntax-name: #785900;\n --color-syntax-type: #ae2368;\n --color-syntax-number: #105ead;\n --color-syntax-operator: #a73a00;\n --color-syntax-regexp: #773dc5;\n --color-syntax-string: #456800;\n --color-syntax-comment: #506070;\n --color-syntax-invalid: #c00000;\n --color-syntax-link: var(--color-primary);\n --color-syntax-tag: #a73a00;\n --color-syntax-attribute: #6f41c5;\n --color-syntax-property: #2060a0;\n --color-syntax-variable: #944a00;\n --color-syntax-string-special: #7d5700;\n --color-syntax-escape: #785900;\n --color-syntax-entity: #6f41c5;\n --color-syntax-preproc: #2d6a4b;\n --color-syntax-preproc-file: #105ead;\n --color-syntax-decorator: #2d6a4b;\n --color-syntax-namespace: #555555;\n --color-syntax-name-pseudo: #6f41c5;\n --color-syntax-comment-special: #773dc5;\n --color-syntax-text: inherit;\n --color-syntax-text-alt: #47525b;\n --color-syntax-punctuation: inherit;\n --color-syntax-whitespace: #bbbbbb;\n --color-syntax-diff-fg: #000000;\n --color-syntax-deleted-bg: #ffdddd;\n --color-syntax-inserted-bg: #ddffdd;\n --color-syntax-emph: #8b5000;\n --color-syntax-strong: inherit;\n --color-syntax-heading: #7d5700;\n --color-syntax-subheading: #456800;\n --color-syntax-output: #506070;\n --color-syntax-prompt: #944a00;\n --color-syntax-traceback: #c00000;\n --color-syntax-matching-bracket-bg: #00b5ad38;\n --color-syntax-nonmatching-bracket-bg: #db282838;\n accent-color: var(--color-accent);\n color-scheme: light;"; diff --git a/styles/tokens/theme-meta.ts b/styles/tokens/theme-meta.ts new file mode 100644 index 0000000..8d526e7 --- /dev/null +++ b/styles/tokens/theme-meta.ts @@ -0,0 +1 @@ +export const themeMeta = "gitea-theme-meta-info {\n --theme-display-name: \"Light\";\n --theme-color-scheme: \"light\";\n}"; diff --git a/themes/light.ts b/themes/light.ts deleted file mode 100644 index 31183aa..0000000 --- a/themes/light.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { ThemeTokens } from "../src/theme-types"; - -export const lightTheme: ThemeTokens = { - name: "gitea-auto", - color: { - canvas: "#f7f3ea", - surface: "#fffaf0", - surfaceRaised: "#ffffff", - border: "#d8cdb8", - text: "#1f2933", - textMuted: "#667085", - accent: "#1d6f5f", - accentHover: "#15574b", - danger: "#b42318", - warning: "#b54708", - success: "#027a48", - }, - radius: { - sm: "6px", - md: "10px", - lg: "16px", - pill: "999px", - }, - shadow: { - sm: "0 1px 2px rgb(31 41 51 / 0.08)", - md: "0 12px 30px rgb(31 41 51 / 0.12)", - }, - font: { - sans: "\"IBM Plex Sans\", \"Noto Sans SC\", sans-serif", - mono: "\"IBM Plex Mono\", \"Noto Sans Mono\", monospace", - sizeSm: "0.875rem", - sizeBase: "1rem", - sizeLg: "1.125rem", - }, - space: { - xs: "0.25rem", - sm: "0.5rem", - md: "1rem", - lg: "1.5rem", - xl: "2rem", - }, - motion: { - fast: "120ms", - normal: "180ms", - }, -};