Files
workspace/code/g3soft-libs/docs/.vitepress/theme/api.css
T
2026-10-12 22:25:41 +08:00

241 lines
9.1 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ==========================================================================
API 文档版式(docs/content/api/**)
--------------------------------------------------------------------------
三处视觉缺口,对应下面三段:
1. 端点标题 `## `POST` `/data/page`` 与 `## 基础约定` 长得一样 → 方法徽章
2. 参数表是裸 markdown 表格(必填列原来是 emoji)→ G3ApiParams 面板
3. 请求体 / 响应体是两块一模一样的灰底 JSON → G3ApiPayload 面板(按 code 着色)
两条自我约束:
- 只用 --vp-c-* 变量,不引第三方样式表。站点其余部分是逐像素对齐 Docus 的
(见 custom.css),API 页必须留在同一套设计语言里。
- 一律逻辑属性(inline-* / block-*),站内已有 RTL 支持(见 content/ui/usage/rtl)。
========================================================================== */
/* ==========================================================================
1. 端点标题
--------------------------------------------------------------------------
写法:## `POST` `/data/page`
用 :has(> code:first-child) 把端点标题与普通 H2 区分开 —— 这既是样式的需要,
也是「为什么不用组件渲染标题」的答案:标题一旦交给 Vue 组件渲染,就不再进
markdown 的 heading token 流,右侧目录(G3DocAside)会丢掉全部条目、锚点
一并消失。所以标题仍是 markdown H2,只在 CSS 上做文章。
代价:方法徽章的颜色没法按 GET/POST 区分(CSS 不能按文本匹配)。当前
/api/** 下全部是 POST,所以是准确的;将来出现混合方法时,在 config.mts 的
markdown.config 里加一个「把首词换成 <span class="g3-api-method--get">」的
小插件即可,slug 由文本 token 决定,不受影响。
作用域:三张 API 页都带 frontmatter `pageClass: g3-api`(VitePress 把该 class
落到根 <div class="Layout"> 上,见主题 Layout.vue:34),下面全部规则都由
.g3-api 兜住,不会漏到组件页去。
========================================================================== */
.g3-api .vp-doc h2:has(> code:first-child) {
/* 覆盖 VitePress 的 .vp-doc h2(上边框 + padding-top):端点标题改为
「下方一条分隔线」,与紧随其后的参数面板构成一组,读起来是一个接口一节。 */
margin-block: 56px 20px;
padding-block: 0 14px;
border-block-start: 0;
border-block-end: 1px solid var(--vp-c-divider);
font-size: 20px;
line-height: 28px;
}
/* 方法徽章:第一个 code */
.g3-api .vp-doc h2:has(> code:first-child) > code:first-child {
padding: 2px 8px;
border-radius: 6px;
background-color: var(--vp-c-brand-soft);
color: var(--vp-c-brand-1);
font-family: var(--vp-font-family-mono);
font-size: 12px;
font-weight: 700;
line-height: 18px;
letter-spacing: 0.06em;
}
/* 路径:第二个 code(nth-of-type 只数 code,不受中间的空格文本与
末尾 header-anchor 的 <a> 影响) */
.g3-api .vp-doc h2:has(> code:first-child) > code:nth-of-type(2) {
padding: 0;
background-color: transparent;
color: var(--vp-c-text-1);
font-family: var(--vp-font-family-mono);
font-size: 18px;
font-weight: 600;
letter-spacing: -0.01em;
}
/* ==========================================================================
2 & 3. 面板(G3ApiParams / G3ApiPayload)
--------------------------------------------------------------------------
结构:标题栏 + 内容两段式。三个语气走同一组自定义变量,默认中性、
ok / warn / error 分别取 success / warning / danger。
⚠ 语气语义是 **body.code**,不是 HTTP 状态码 —— 这正是通用 OpenAPI
渲染器做不到的地方(它们的颜色模型绑死 HTTP 状态码,会把这里的
失败响应渲染成绿色成功块)。
========================================================================== */
.g3-api-panel {
--g3-api-accent: var(--vp-c-text-3);
--g3-api-accent-soft: var(--vp-c-bg-alt);
margin: 16px 0;
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
/* 圆角要裁掉子元素底色(标题栏、代码块),但横向滚动不能裁 ——
滚动交给 __body,见下。 */
overflow: hidden;
}
.g3-api-panel--ok {
--g3-api-accent: var(--vp-c-success-1, var(--vp-c-green-1));
--g3-api-accent-soft: var(--vp-c-success-soft, var(--vp-c-green-soft));
}
.g3-api-panel--warn {
--g3-api-accent: var(--vp-c-warning-1, var(--vp-c-yellow-1));
--g3-api-accent-soft: var(--vp-c-warning-soft, var(--vp-c-yellow-soft));
}
.g3-api-panel--error {
--g3-api-accent: var(--vp-c-danger-1, var(--vp-c-red-1));
--g3-api-accent-soft: var(--vp-c-danger-soft, var(--vp-c-red-soft));
}
.g3-api-panel__head {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 14px;
background-color: var(--vp-c-bg-soft);
border-block-end: 1px solid var(--vp-c-divider);
color: var(--vp-c-text-2);
font-size: 12px;
font-weight: 600;
line-height: 20px;
}
/* 语气点:与语气同色。文字标签(成功/失败)与它并存,
不让颜色成为唯一的区分手段。 */
.g3-api-panel__dot {
flex: 0 0 auto;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: var(--g3-api-accent);
}
.g3-api-panel--ok .g3-api-panel__head,
.g3-api-panel--warn .g3-api-panel__head,
.g3-api-panel--error .g3-api-panel__head {
color: var(--g3-api-accent);
}
.g3-api-panel__tone {
font-weight: 500;
opacity: 0.9;
}
/* code 徽章:仅 G3ApiPayload 传了 code 时出现 */
.g3-api-panel__code {
padding: 1px 7px;
border-radius: 9999px;
background-color: var(--g3-api-accent-soft);
color: inherit;
font-family: var(--vp-font-family-mono);
font-size: 11px;
font-weight: 600;
}
.g3-api-panel__body {
/* 宽表横向滚动由这一层承担:VitePress 给 .vp-doc table 设了
display:block + overflow-x:auto,那会让 table 自己成为滚动容器
(custom.css 里已记录过它导致 sticky 表头失效的问题)。 */
overflow-x: auto;
}
/* --- 参数表:去掉 .vp-doc 给 markdown 表格画的四边框与上下留白 ------ */
.g3-api-panel__body table {
display: table;
width: 100%;
margin: 0;
}
.g3-api-panel__body table th,
.g3-api-panel__body table td {
border: 0;
border-block-end: 1px solid var(--vp-c-divider);
padding: 8px 14px;
background-color: transparent;
}
.g3-api-panel__body table tr:nth-child(2n) {
background-color: transparent;
}
.g3-api-panel__body table tr:last-child td {
border-block-end: 0;
}
.g3-api-panel__body table th {
color: var(--vp-c-text-3);
font-size: 12px;
font-weight: 600;
text-align: start;
white-space: nowrap;
}
/* 列序约定:参数 / 类型 / 必填 / 说明。这两条按位置定样式,所以要两重限定:
1) variant="params" —— 参数表才有这个形状。bare 的表(错误码:code / 含义 /
典型原因 / 定位)若套上,散文列会被当成「类型」套等宽、被当成「必填」染成品牌色。
2) :has(td:nth-child(4)) —— 同一个 params 变体下,「字段 / 说明」两列表(如
/data/page 的 data 字段)第 2 列是散文,也不该套等宽小字。
第 1 列两种表都是标识符(参数名 / 字段名 / code),所以不加限定。 */
.g3-api-panel__body table td:first-child {
color: var(--vp-c-text-1);
font-family: var(--vp-font-family-mono);
font-size: 13px;
}
.g3-api-panel--params .g3-api-panel__body:has(td:nth-child(4)) table td:nth-child(2) {
color: var(--vp-c-text-3);
font-family: var(--vp-font-family-mono);
font-size: 12px;
white-space: nowrap;
}
.g3-api-panel--params .g3-api-panel__body:has(td:nth-child(4)) table td:nth-child(3) {
color: var(--vp-c-brand-1);
font-weight: 500;
white-space: nowrap;
}
/* --- 报文里的代码块:贴边(VitePress 默认 margin:20px 0 + 圆角 8px)- */
.g3-api-panel__body div[class*='language-'] {
margin: 0;
border-radius: 0;
}
/* ==========================================================================
4. 表格列宽:短中文列不被压扁
--------------------------------------------------------------------------
现象:/api/getting-started 的「接口一览」里「板块」列被压成一列一个字
(「数据查询」折成两行)。
原因不是这列太长,而是**太短**:CJK 没有「词」的边界,可以逐字换行,于是
该列的 min-content 宽度只有 1 个字。table-layout: auto 按 min-content 分配
空间时,浏览器会把这列压到最小、把余量让给旁边的长路径与长文案 —— 越短的列
越容易被牺牲,与直觉相反。
nowrap 把该列的 min-content 抬到「整格文字的宽度」,即不可再压。
API 页各表的首列都是短键(板块 / 项 / code / 字段 / 参数名),nowrap 安全;
长文案列(说明、触发场景)不带这条规则,照常换行。
========================================================================== */
.g3-api .vp-doc table th:first-child,
.g3-api .vp-doc table td:first-child {
white-space: nowrap;
}