Compare commits

..

11 Commits

Author SHA1 Message Date
lutinglt
065d7893d8 亮色主题适配 2025-08-07 18:26:21 +08:00
lutinglt
0a6770c28e 亮色主题 2025-08-07 16:19:18 +08:00
lutinglt
0825efeb2c update readme 2025-08-06 15:23:48 +08:00
鲁汀
8dcd7cf002 探索/组织/用户仓库样式 github 布局 (#8)
Co-authored-by: lutinglt <lutinglt@users.noreply.github.com>
2025-08-06 15:05:43 +08:00
lutinglt
93e5fa8a7d update todo 2025-08-06 11:10:19 +08:00
lutinglt
8c5020fa09 同步探索页面仓库样式 2025-08-06 11:05:57 +08:00
lutinglt
35520fb3fc 难受 2025-08-05 18:18:54 +08:00
lutinglt
728673ffcd Gitea 大便的 UI 逻辑问题 2025-08-05 18:14:04 +08:00
lutinglt
f7c1cf430f 评论和表情样式同步 2025-08-05 18:08:24 +08:00
lutinglt
c6306a23d4 update readme 2025-08-05 16:04:54 +08:00
lutinglt
f813122573 update readme 2025-08-05 16:00:46 +08:00
23 changed files with 392 additions and 73 deletions

View File

@@ -1,4 +1,4 @@
## ✨ Feat
## ✨ Feature
#### CSS 变量

28
.github/release.md vendored
View File

@@ -1,31 +1,11 @@
## ✨ Feat
## ✨ Feature
🎉 支持自定义 CSS 变量设置主题样式
#### CSS 变量
- 支持克隆菜单自定义长度
## 🌈 Style
- 分支菜单项目添加动画效果
#### 更符合 GitHub 风格
- 同步 PR 的合并提交操作面板样式
- 同步 Issue/PR 的时间线样式
- 仓库同步派生栏样式同步
- 添加一些颜色的渐变过渡动画
- 同步 Issue/PR 的评论标题颜色
- 同步 PR/Actions 的分支字体
- 同步文件打开时的提交栏样式
- 支持亮色主题
## 🎈 Perf
- 优化全局按钮样式
- 优化顶部导航栏按钮圆角
- 优化差异对比的代码折叠/展开按钮的高度和动画效果
## 🐞 Fix
- 修复一些圆角问题
- 修复工单下依赖工单选择框的高度对齐
- 修复仓库页面与探索页面下仓库主题标签字重不一致的问题

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@ dist
node_modules
package-lock.json
.env
.VSCodeCounter

View File

@@ -32,11 +32,11 @@ THEMES = gitea-dark, github-dark
### 使用方法
在主题的 CSS 文件头部或尾部添加以下代码
在主题的 CSS 文件头部或尾部添加以下代码
```css
:root {
--custom-clone-menu-width: 150px;.
--custom-clone-menu-width: 150px;
...
}
```
@@ -51,9 +51,14 @@ THEMES = gitea-dark, github-dark
### CSS 变量
| 变量名 | 描述 | Gitea (默认值) | Github | 推荐 | 最小值 | 最大值 |
| :------------------------ | :----------- | :------------- | :----- | :---- | :----- | :----- |
| --custom-clone-menu-width | 克隆菜单宽度 | 232px | 332px | 200px | 150px | 400px |
| 变量名 | 描述 | 默认值 | Github | 推荐 | 最小值 | 最大值 |
| :-------------------------------- | :-------------------------- | :----- | :----- | :---- | :----- | :----- |
| --custom-clone-menu-width | 克隆菜单宽度 | Gitea | 332px | 200px | 150px | 400px |
| --custom-explore-repolist-columns | 探索页面的仓库列表列数 | 2 | 2 | 2 | | |
| --custom-explore-userlist-columns | 探索页面的用户/组织列表列数 | 3 | 1 | 2/3 | | |
| --custom-user-repolist-columns | 用户页面的仓库列表列数 | 2 | 2 | 1/2 | | |
| --custom-org-repolist-columns | 组织页面的仓库列表列数 | 1 | 1 | 1/2 | | |
| --custom-org-userlist-columns | 组织页面的用户列表列数 | 2 | 1 | 1/2 | | |
## 截图
@@ -74,7 +79,3 @@ THEMES = gitea-dark, github-dark
## 贡献
欢迎提交 Issue 或 Pull Request
```
```

View File

@@ -1,13 +1,11 @@
### 重大
- gitea issue 默认标签颜色匹配使用 github 样式
- 探索/组织/用户仓库样式 github 布局
- issue/PR 列表样式 github 布局
- styles/themes 库组件导出整理
- defineTheme 颜色生成代码重构
- 亮色主题适配/测试
- 自动颜色主题生成
- github primer 官方库集成
### 其他

View File

@@ -1,4 +1,6 @@
import { saturate } from "polished";
import type { Console, Diff, Other } from "src";
import { scaleColorLight } from "src/functions";
import type { Github } from "src/types";
import { themeVars } from "src/types/vars";
import { defineTheme } from "./color";
@@ -81,11 +83,9 @@ export type GithubColor = {
button: {
primary: {
fgColor: {
accent: string;
rest: string;
};
bgColor: {
rest: string;
hover: string;
};
};
@@ -114,7 +114,9 @@ export type GithubColor = {
};
};
shadow: {
floating: string;
floating: {
small: string;
};
};
overlay: {
backdrop: {
@@ -134,7 +136,6 @@ export type GithubColor = {
num2: string;
num3: string;
num4: string;
num5: string;
};
borderColor: {
num0: string;
@@ -244,7 +245,7 @@ export function defineGithubTheme(githubColor: GithubColor): Theme {
button: githubColor.control.bgColor.rest,
codeBg: "unset",
shadow: {
self: githubColor.shadow.floating,
self: githubColor.shadow.floating.small,
opaque: themeVars.color.shadow.self,
},
secondaryBg: "unset",
@@ -323,11 +324,11 @@ export function defineGithubTheme(githubColor: GithubColor): Theme {
},
primary: {
fgColor: {
accent: githubColor.button.primary.fgColor.accent,
accent: saturate(0.1, scaleColorLight(githubColor.fgColor.success, githubColor.isDarkTheme ? 10 : -10)),
rest: githubColor.button.primary.fgColor.rest,
},
bgColor: {
rest: githubColor.button.primary.bgColor.rest,
rest: themeVars.github.bgColor.success.emphasis,
hover: githubColor.button.primary.bgColor.hover,
},
borderColor: {
@@ -377,7 +378,10 @@ export function defineGithubTheme(githubColor: GithubColor): Theme {
num2: githubColor.contribution.default.bgColor.num2,
num3: githubColor.contribution.default.bgColor.num3,
num4: githubColor.contribution.default.bgColor.num4,
num5: githubColor.contribution.default.bgColor.num5,
num5: saturate(
0.2,
scaleColorLight(githubColor.contribution.default.bgColor.num4, githubColor.isDarkTheme ? 58 : -58)
),
},
borderColor: {
num0: githubColor.contribution.default.borderColor.num0,

View File

@@ -1,8 +1,8 @@
type Primitive = string | boolean | number | null | undefined;
type Tokens = { [key: string]: string | Tokens };
export type CSSVarFunction = `var(--${string})`;
export type WithOptionalLayer<T extends Tokens> = T & { "@layer"?: string };
export type MapLeafNodes<Obj, LeafType> = {
[Prop in keyof Obj]: Obj[Prop] extends Primitive
? LeafType

View File

@@ -1 +1,2 @@
export { scaleColorLight } from "./scss";
export { fallbackVar } from "./var";

7
src/functions/var.ts Normal file
View File

@@ -0,0 +1,7 @@
import type { CSSVarFunction } from "src/core/types";
type CSSFallbackVar = `var(--${string}, ${string})`;
export function fallbackVar(cssvar: CSSVarFunction, fallback: string): CSSFallbackVar {
const var_name = cssvar.replace("var(--", "").replace(")", "");
return `var(--${var_name}, ${fallback})`;
}

View File

@@ -28,6 +28,7 @@ export const github = {
* @actions `actionViewLeft` 左侧子作业激活伪元素颜色
* @release `releaseTagMenu` 顶部栏左侧按钮激活背景色
* @navbar `navbarRight` 头像管理员标识背景颜色
* @dropdown `dropdown` emoji 的悬停背景色
*/
emphasis: null,
/** 暗淡的背景颜色

View File

@@ -38,6 +38,15 @@ const otherVars = {
const customVars = {
custom: {
cloneMenuWidth: "custom-clone-menu-width",
explore: {
repolistColumns: "custom-explore-repolist-columns",
userlistColumns: "custom-explore-userlist-columns",
},
userRepolistColumns: "custom-user-repolist-columns",
org: {
repolistColumns: "custom-org-repolist-columns",
userlistColumns: "custom-org-userlist-columns",
},
},
};

View File

@@ -1,4 +1,4 @@
import { css, otherThemeVars, themeVars, customThemeVars } from "src/types/vars";
import { css, customThemeVars, otherThemeVars, themeVars } from "src/types/vars";
// 克隆按钮的弹窗
export const clone = css`

View File

@@ -29,11 +29,11 @@ export const diff = css`
}
/* 展开/收缩按钮 */
.code-expander-button {
height: 24px !important;
line-height: 24px;
height: 28px !important;
&:hover {
background: ${themeVars.github.bgColor.accent.emphasis};
color: ${themeVars.color.white}
}
}
/* 行号居中 */

View File

@@ -0,0 +1,161 @@
import { fallbackVar } from "src/functions";
import { css, customThemeVars, otherThemeVars, themeVars } from "src/types/vars";
const userRepoVar = fallbackVar(customThemeVars.custom.userRepolistColumns, "2");
const exploreRepoVar = fallbackVar(customThemeVars.custom.explore.repolistColumns, "2");
const orgRepoVar = fallbackVar(customThemeVars.custom.org.repolistColumns, "1");
// 仓库列表
export const repoList = css`
// 组织
.page-content.organization.profile > .ui.container > .ui.stackable > .ui.eleven,
// 用户
.page-content.user.profile > .ui.container > .ui.stackable > .ui.twelve,
// 探索
.page-content.explore.repositories > .ui.container {
> .flex-list {
display: grid;
> .flex-item {
border: 1px solid ${themeVars.color.light.border};
border-radius: ${otherThemeVars.border.radius};
padding: 16px;
// 仓库头像
> .flex-item-leading {
img,
svg {
color: ${themeVars.color.text.light.num1};
}
}
// 仓库信息
> .flex-item-main {
// 仓库标题
> .flex-item-header {
// 仓库名称
> .flex-item-title {
gap: 8px;
// 仓库中间的间隔线
&:not(a) {
color: ${themeVars.color.text.light.num1};
}
// 仓库类型和状态标签
> .label-list .label {
padding: 3px 6px;
}
}
// 仓库语言, 星标
> .flex-item-trailing {
color: ${themeVars.color.text.light.num1};
gap: 16px;
font-size: 12px;
> .flex-text-inline .color-icon {
width: 12px;
height: 12px;
margin-right: 0 !important;
}
}
}
// 描述和更新时间
> .flex-item-body {
margin-top: 8px;
// 更新时间
&:last-child {
font-size: 12px;
}
}
// 主题标签
> .label-list {
margin-top: 8px;
}
}
}
}
}
// 仓库列表列数
// 组织
.page-content.organization.profile > .ui.container > .ui.stackable > .ui.eleven > .flex-list {
grid-template-columns: repeat(${orgRepoVar}, 1fr);
gap: min(${orgRepoVar} * 8px, 16px);
}
// 用户
.page-content.user.profile > .ui.container > .ui.stackable > .ui.twelve > .flex-list {
grid-template-columns: repeat(${userRepoVar}, 1fr);
gap: min(${userRepoVar} * 8px, 16px);
}
// 探索
.page-content.explore.repositories > .ui.container > .flex-list {
grid-template-columns: repeat(${exploreRepoVar}, 1fr);
gap: min(${exploreRepoVar} * 8px, 16px);
}
`;
const exploreUserVar = fallbackVar(customThemeVars.custom.explore.userlistColumns, "3");
const orgUserVar = fallbackVar(customThemeVars.custom.org.userlistColumns, "2");
// 用户列表
export const userList = css`
// 组织
.page-content.organization.members > .ui.container,
// 探索的用户和组织
.page-content.explore.users > .ui.container {
> .flex-list {
display: grid;
> .flex-item {
border: 1px solid ${themeVars.color.light.border};
border-radius: ${otherThemeVars.border.radius};
padding: 16px;
> .flex-item-main {
// 用户名称
> .flex-item-title {
gap: 8px;
margin-bottom: 8px;
// 用户标签
> .label {
font-size: 12px;
padding: 3px 6px;
}
}
// 用户描述
> .flex-item-body {
font-size: 12px;
svg {
width: 12px;
min-width: 12px;
}
}
}
}
}
}
// 用户列表列数
// 组织
.page-content.organization.members > .ui.container > .flex-list {
grid-template-columns: repeat(${orgUserVar}, 1fr);
gap: min(${orgUserVar} * 8px, 16px);
}
// 探索的用户和组织
.page-content.explore.users > .ui.container > .flex-list {
grid-template-columns: repeat(${exploreUserVar}, 1fr);
gap: min(${exploreUserVar} * 8px, 16px);
}
`;
// 手机下的仓库和用户列表
export const mobileList = css`
@media (max-width: 767.98px) {
// 组织的仓库列表
.page-content.organization.profile > .ui.container > .ui.stackable > .ui.eleven,
// 用户的仓库列表
.page-content.user.profile > .ui.container > .ui.stackable > .ui.twelve,
// 探索的仓库列表
.page-content.explore.repositories > .ui.container,
// 组织的成员列表
.page-content.organization.members >.ui.container,
// 探索的用户和组织列表
.page-content.explore.users >.ui.container {
> .flex-list {
grid-template-columns: 1fr;
gap: 8px;
}
}
}
`;

View File

@@ -3,6 +3,7 @@ import "./clone";
import "./commit";
import "./dashboard";
import "./diff";
import "./explore";
import "./filelist";
import "./heatmap";
import "./issue";

View File

@@ -42,19 +42,19 @@ export const babel = css`
border-radius: 25px !important;
&.green {
color: ${themeVars.color.text.self} !important;
color: ${themeVars.color.white} !important;
background-color: ${themeVars.github.bgColor.success.emphasis} !important;
border-color: ${themeVars.github.bgColor.success.emphasis} !important;
}
&.red {
color: ${themeVars.color.text.self} !important;
color: ${themeVars.color.white} !important;
background-color: ${themeVars.github.bgColor.done.emphasis} !important;
border-color: ${themeVars.github.bgColor.done.emphasis} !important;
}
&.purple {
color: ${themeVars.color.text.self} !important;
color: ${themeVars.color.white} !important;
background-color: ${themeVars.github.bgColor.done.emphasis} !important;
border-color: ${themeVars.github.bgColor.done.emphasis} !important;
}
@@ -85,7 +85,7 @@ export const prBranch = css`
// 评论
export const comment = css`
.comment {
.comment .comment-container {
// 去除评论标题左侧指向头像的小箭头
.comment-header,
&:target .comment-header {
@@ -101,12 +101,31 @@ export const comment = css`
box-shadow: 0 0 0 1px ${themeVars.color.primary.self} !important;
}
}
.comment-header {
padding: 4px 4px 4px 16px;
}
.comment-header-right {
> .item,
> .label {
color: ${themeVars.color.text.light.num1};
}
> .ui.label {
background-color: initial;
font-size: 12px;
height: 20px;
padding: 0 6px;
}
// 隐藏顶部菜单的表情按钮
// 无法使用此样式, 评论无表情时底部的表情按钮元素不会渲染, 这是一个先有鸡还是先有蛋的问题
// 很蛋疼, 希望 Gitea 早日使用 Github 的样式, 因为 Github 的更合理, 无论是操作的方便程度还是按钮的冗余度
// .ui.dropdown.action.select-reaction {
// display: none;
// }
.context-dropdown {
a.context-menu {
display: flex;
align-items: center;
}
// 评论菜单的删除按钮
.menu .item.delete-comment {
color: ${themeVars.color.red.self};
@@ -117,6 +136,45 @@ export const comment = css`
}
}
}
// 表情菜单按钮头部+底部
.ui.dropdown.action.select-reaction > a {
display: flex;
align-items: center;
justify-content: center;
background: ${themeVars.color.button};
border-radius: 25px;
border: 1px solid ${themeVars.color.light.border};
color: ${themeVars.color.text.light.num1};
padding: 0px 8px !important;
height: 28px;
width: 28px;
}
// 底部表情栏
.bottom-reactions {
.ui.ui.ui.label {
background-color: unset !important;
border-radius: 25px;
border-color: ${themeVars.color.light.border};
&:hover {
background-color: ${themeVars.color.reaction.hoverBg} !important;
border-color: ${themeVars.color.light.border};
}
.reaction {
font-size: 12px;
}
.reaction-count {
color: ${themeVars.color.text.light.self};
font-weight: 500;
margin-left: 0;
}
}
// 显示表情菜单按钮
.select-reaction {
padding: 0;
// 两个表情按钮看着怪怪的, 很难受
// visibility: visible;
}
}
}
`;

View File

@@ -74,18 +74,19 @@ export const repoMenu = css`
export const repoTopic = css`
// 理应只能覆盖探索/组织/用户下仓库的 topic 标签
.label-list .ui.label,
// 避免渲染到仓库的类型标签
.flex-item-main > .label-list .ui.label,
// 仓库文件列表下的 topic 标签
#repo-topics .ui.label.repo-topic {
border-radius: 25px;
font-size: 12px;
font-weight: 500;
padding: 5px 10px;
margin: 0px 1.5px 3.5px 0px;
background-color: ${themeVars.github.bgColor.accent.muted};
color: ${themeVars.github.fgColor.accent};
&:hover {
background-color: ${themeVars.github.bgColor.accent.emphasis};
color: ${themeVars.color.text.self};
color: ${themeVars.color.white};
}
}
`;

View File

@@ -19,13 +19,15 @@ export const dropdown = css`
gap: 0.5rem;
padding: 8px 10px !important;
border-radius: ${otherThemeVars.border.radius} !important;
&:not(.emoji) {
margin: 0 0.5rem;
&:first-of-type {
}
&:not(.emoji):first-of-type {
margin-top: 0.5rem;
}
// 不知道为什么提交差异对比页面操作中的 cherrypick 按钮无法被选中
&.cherry-pick-button,
&:last-of-type {
&:not(.emoji):last-of-type {
margin-bottom: 0.5rem;
}
&:hover {
@@ -180,3 +182,23 @@ export const branchDropdown = css`
animation: ${animationDown};
}
`;
// 包含表情的下拉菜单
export const emojiDropdown = css`
.ui.dropdown.action.select-reaction.active .menu:has(.emoji) {
display: flex !important;
flex-direction: row;
gap: 4px;
padding: 4px;
min-width: auto;
> .item.emoji {
font-size: 14px;
min-height: 32px;
height: 32px;
margin: 0px;
&:hover {
background-color: ${themeVars.github.bgColor.accent.emphasis} !important;
}
}
}
`;

View File

@@ -68,7 +68,7 @@ export const navbarRight = css`
.navbar-profile-admin {
background-color: ${themeVars.github.bgColor.accent.emphasis};
border-radius: 25px;
color: ${themeVars.color.text.self};
color: ${themeVars.color.white};
font-size: 8px;
font-weight: 600;
padding: 2px 5px;

View File

@@ -9,6 +9,8 @@ export const transition = css`
.job-step-logs,
.job-brief-item,
.repo-file-cell,
// 差异对比的代码折叠按钮
.code-expander-button,
.tippy-box .flex-items-block .item,
.clone-panel-tab .item,
.ui.form select,

View File

@@ -1,6 +1,6 @@
import { defineGithubTheme, type GithubColor } from "src/core/github";
import { defineGithubTheme } from "src/core/github";
const github: GithubColor = {
export default defineGithubTheme({
isDarkTheme: true,
display: {
brown: { fgColor: "#b69a6d" },
@@ -53,22 +53,20 @@ const github: GithubColor = {
translucent: "#ffffff26",
},
button: {
primary: { fgColor: { accent: "#39d353", rest: "#ffffff" }, bgColor: { rest: "#238636", hover: "#29903b" } },
primary: { fgColor: { rest: "#ffffff" }, bgColor: { hover: "#29903b" } },
danger: { fgColor: { rest: "#fa5e55", hover: "#ffffff" }, bgColor: { hover: "#b62324" } },
},
control: {
bgColor: { active: "#2a313c", hover: "#262c36", rest: "#212830" },
transparent: { bgColor: { active: "#656c7640", hover: "#656c7633", selected: "#656c761a" } },
},
shadow: { floating: "#01040966" },
shadow: { floating: { small: "#01040966" } },
overlay: { backdrop: { bgColor: "#21283066" } },
underlineNav: { borderColor: { active: "#f78166" } },
contribution: {
default: {
bgColor: { num0: "#151b23", num1: "#033a16", num2: "#196c2e", num3: "#2ea043", num4: "#56d364", num5: "#7ee787" },
bgColor: { num0: "#151b23", num1: "#033a16", num2: "#196c2e", num3: "#2ea043", num4: "#56d364" },
borderColor: { num0: "#0104090d" },
},
},
};
export default defineGithubTheme(github);
});

74
themes/light.css.ts Normal file
View File

@@ -0,0 +1,74 @@
import { defineGithubTheme } from "src/core/github";
// [TODO] chroma 语法高亮的颜色
export default defineGithubTheme({
isDarkTheme: false,
display: {
brown: { fgColor: "#755f43" },
cyan: { fgColor: "#006a80" },
indigo: { fgColor: "#494edf" },
lemon: { fgColor: "#786002" },
olive: { fgColor: "#56682c" },
teal: { fgColor: "#106e75" },
},
diffBlob: {
addtionNum: { bgColor: "#aceebb" },
addtionWord: { bgColor: "#aceebb" },
deletionNum: { bgColor: "#ffcecb" },
deletionWord: { bgColor: "#ffcecb" },
hunkNum: { bgColor: { rest: "#b6e3ff" } },
},
fgColor: {
accent: "#0969da",
attention: "#9a6700",
danger: "#d1242f",
default: "#1f2328",
disabled: "#818b98",
done: "#8250df",
neutral: "#59636e",
severe: "#bc4c00",
sponsors: "#bf3989",
success: "#1a7f37",
black: "#1f2328",
white: "#ffffff",
muted: "#59636e",
},
bgColor: {
accent: { emphasis: "#0969da", muted: "#ddf4ff" },
attention: { muted: "#fff8c5" },
success: { emphasis: "#1f883d", muted: "#dafbe1" },
danger: { muted: "#ffebe9" },
done: { emphasis: "#8250df" },
default: "#ffffff",
inset: "#f6f8fa",
muted: "#f6f8fa",
neutral: { muted: "#818b981f" },
},
borderColor: {
accent: { emphasis: "#0969da" },
default: "#d1d9e0",
attention: { emphasis: "#9a6700" },
success: { emphasis: "#1a7f37" },
done: { emphasis: "#8250df" },
muted: "#d1d9e0b3",
translucent: "#1f232826",
},
button: {
primary: { fgColor: { rest: "#ffffff" }, bgColor: { hover: "#1c8139" } },
danger: { fgColor: { rest: "#d1242f", hover: "#ffffff" }, bgColor: { hover: "#cf222e" } },
},
control: {
bgColor: { active: "#e6eaef", hover: "#eff2f5", rest: "#f6f8fa" },
transparent: { bgColor: { active: "#818b9826", hover: "#818b981a", selected: "#818b9826" } },
},
shadow: { floating: { small: "#25292e0a" } },
overlay: { backdrop: { bgColor: "#c8d1da66" } },
underlineNav: { borderColor: { active: "#fd8c73" } },
contribution: {
default: {
bgColor: { num0: "#eff2f5", num1: "#aceebb", num2: "#4ac26b", num3: "#2da44e", num4: "#116329" },
borderColor: { num0: "#1f23280d" },
},
},
});

View File

@@ -34,7 +34,7 @@ export default defineConfig(({ mode }) => {
},
plugins: [
linaria({
include: ["**/*.{ts,tsx}"],
include: ["**/*.ts"],
babelOptions: {
presets: ["@babel/preset-typescript"],
},