Compare commits

...

8 Commits

Author SHA1 Message Date
鲁汀
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
15 changed files with 292 additions and 43 deletions

View File

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

29
.github/release.md vendored
View File

@@ -1,31 +1,20 @@
## ✨ Feat ## ✨ Feature
🎉 支持自定义 CSS 变量设置主题样式
#### CSS 变量 #### CSS 变量
- 支持克隆菜单自定义长度 - 支持自定义探索/组织/用户页面的仓库列表列数
- 支持自定义探索/组织页面的用户/组织列表列数
## 🌈 Style ## 🌈 Style
- 分支菜单项目添加动画效果
#### 更符合 GitHub 风格 #### 更符合 GitHub 风格
- 同步 PR 的合并提交操作面板样式 - 同步 Issue/PR 的评论样式
- 同步 Issue/PR 的时间线样式 - 同步表情菜单样式
- 仓库同步派生栏样式同步 - 同步探索/组织/用户页面的仓库列表样式
- 添加一些颜色的渐变过渡动画 - 同步探索/组织页面的用户列表样式
- 同步 Issue/PR 的评论标题颜色 - 同步探索页面的组织列表样式
- 同步 PR/Actions 的分支字体
- 同步文件打开时的提交栏样式
## 🎈 Perf
- 优化全局按钮样式
- 优化顶部导航栏按钮圆角
## 🐞 Fix ## 🐞 Fix
- 修复一些圆角问题 - 修复探索页面下仓库的类型标签意外触发悬浮效果
- 修复工单下依赖工单选择框的高度对齐

View File

@@ -32,28 +32,33 @@ THEMES = gitea-dark, github-dark
### 使用方法 ### 使用方法
在主题的 CSS 文件头部或尾部添加以下代码 在主题的 CSS 文件头部或尾部添加以下代码
```css ```css
:root { :root {
--custom-clone-menu-width: 150px;. --custom-clone-menu-width: 150px;
... ...
} }
``` ```
>[!IMPORTANT] > [!IMPORTANT]
> >
>请确保在 `:root` 选择器中添加自定义变量,否则无法生效 > 请确保在 `:root` 选择器中添加自定义变量,否则无法生效
> >
>变量之间用 `;` 分隔 > 变量之间用 `;` 分隔
> >
>建议自定义变量放在单独的文件中, 通过 shell 命令等方式追加到主题文件中 > 建议自定义变量放在单独的文件中, 通过 shell 命令等方式追加到主题文件中
### CSS 变量 ### CSS 变量
| 变量名 | 描述 | Gitea (默认值) | Github | 推荐 | 最小值 | 最大值 | | 变量名 | 描述 | 默认值 | Github | 推荐 | 最小值 | 最大值 |
| :------------------------ | :----------- | :------------- | :----- | :---- | :----- | :----- | | :-------------------------------- | :-------------------------- | :----- | :----- | :---- | :----- | :----- |
| --custom-clone-menu-width | 克隆菜单宽度 | 232px | 332px | 200px | 150px | 400px | | --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 | 2 | | |
| --custom-org-repolist-columns | 组织页面的仓库列表列数 | 1 | 1 | 1 | | |
| --custom-org-userlist-columns | 组织页面的用户列表列数 | 2 | 1 | 2 | | |
## 截图 ## 截图
@@ -74,7 +79,3 @@ THEMES = gitea-dark, github-dark
## 贡献 ## 贡献
欢迎提交 Issue 或 Pull Request 欢迎提交 Issue 或 Pull Request
```
```

View File

@@ -1,7 +1,6 @@
### 重大 ### 重大
- gitea issue 默认标签颜色匹配使用 github 样式 - gitea issue 默认标签颜色匹配使用 github 样式
- 探索/组织/用户仓库样式 github 布局
- issue/PR 列表样式 github 布局 - issue/PR 列表样式 github 布局
- styles/themes 库组件导出整理 - styles/themes 库组件导出整理
- defineTheme 颜色生成代码重构 - defineTheme 颜色生成代码重构

View File

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

View File

@@ -1 +1,2 @@
export { scaleColorLight } from "./scss"; 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` 左侧子作业激活伪元素颜色 * @actions `actionViewLeft` 左侧子作业激活伪元素颜色
* @release `releaseTagMenu` 顶部栏左侧按钮激活背景色 * @release `releaseTagMenu` 顶部栏左侧按钮激活背景色
* @navbar `navbarRight` 头像管理员标识背景颜色 * @navbar `navbarRight` 头像管理员标识背景颜色
* @dropdown `dropdown` emoji 的悬停背景色
*/ */
emphasis: null, emphasis: null,
/** 暗淡的背景颜色 /** 暗淡的背景颜色

View File

@@ -38,6 +38,15 @@ const otherVars = {
const customVars = { const customVars = {
custom: { custom: {
cloneMenuWidth: "custom-clone-menu-width", 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` export const clone = css`

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 "./commit";
import "./dashboard"; import "./dashboard";
import "./diff"; import "./diff";
import "./explore";
import "./filelist"; import "./filelist";
import "./heatmap"; import "./heatmap";
import "./issue"; import "./issue";

View File

@@ -85,7 +85,7 @@ export const prBranch = css`
// 评论 // 评论
export const comment = css` export const comment = css`
.comment { .comment .comment-container {
// 去除评论标题左侧指向头像的小箭头 // 去除评论标题左侧指向头像的小箭头
.comment-header, .comment-header,
&:target .comment-header { &:target .comment-header {
@@ -101,12 +101,31 @@ export const comment = css`
box-shadow: 0 0 0 1px ${themeVars.color.primary.self} !important; box-shadow: 0 0 0 1px ${themeVars.color.primary.self} !important;
} }
} }
.comment-header {
padding: 4px 4px 4px 16px;
}
.comment-header-right { .comment-header-right {
> .item, > .item,
> .label { > .label {
color: ${themeVars.color.text.light.num1}; 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 { .context-dropdown {
a.context-menu {
display: flex;
align-items: center;
}
// 评论菜单的删除按钮 // 评论菜单的删除按钮
.menu .item.delete-comment { .menu .item.delete-comment {
color: ${themeVars.color.red.self}; 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,13 +74,13 @@ export const repoMenu = css`
export const repoTopic = css` export const repoTopic = css`
// 理应只能覆盖探索/组织/用户下仓库的 topic 标签 // 理应只能覆盖探索/组织/用户下仓库的 topic 标签
.label-list .ui.label, // 避免渲染到仓库的类型标签
.flex-item-main > .label-list .ui.label,
// 仓库文件列表下的 topic 标签 // 仓库文件列表下的 topic 标签
#repo-topics .ui.label.repo-topic { #repo-topics .ui.label.repo-topic {
border-radius: 25px; border-radius: 25px;
font-size: 12px; font-size: 12px;
padding: 5px 10px; padding: 5px 10px;
margin: 0px 1.5px 3.5px 0px;
background-color: ${themeVars.github.bgColor.accent.muted}; background-color: ${themeVars.github.bgColor.accent.muted};
color: ${themeVars.github.fgColor.accent}; color: ${themeVars.github.fgColor.accent};
&:hover { &:hover {

View File

@@ -19,13 +19,15 @@ export const dropdown = css`
gap: 0.5rem; gap: 0.5rem;
padding: 8px 10px !important; padding: 8px 10px !important;
border-radius: ${otherThemeVars.border.radius} !important; border-radius: ${otherThemeVars.border.radius} !important;
margin: 0 0.5rem; &:not(.emoji) {
&:first-of-type { margin: 0 0.5rem;
}
&:not(.emoji):first-of-type {
margin-top: 0.5rem; margin-top: 0.5rem;
} }
// 不知道为什么提交差异对比页面操作中的 cherrypick 按钮无法被选中 // 不知道为什么提交差异对比页面操作中的 cherrypick 按钮无法被选中
&.cherry-pick-button, &.cherry-pick-button,
&:last-of-type { &:not(.emoji):last-of-type {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
&:hover { &:hover {
@@ -180,3 +182,23 @@ export const branchDropdown = css`
animation: ${animationDown}; 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;
}
}
}
`;