feat(kin,movies): 家谱改用第三方库 family-chart;观影设置按钮改纯图标并统一页头度量
家谱(v13): - 自研布局是死结,不是样式问题:连线的横杆是网格项,只能横跨「父母列→子女列」 整段区间,中间夹着与血缘无关的人(如媳妇那侧的岳父母)时必然从卡片上穿过。 换成 family-chart(D3 生态,MIT)后,排布只走本家血脉 + 配偶,姻亲不进画布, 这个死结在构造上就不存在了。 - 接入踩到并修掉的坑:main_id = data[0].id(「我」必须排最前); 卡片回调里自定义字段在 d.data.data(双层);库的 family-chart.css 是死文件 (全挂在 .f3 作用域,运行时没有 .f3 元素);库的 svg 撑满选择器永不命中 (必须自己补 .kin-chart svg.main_svg);setCanAdd/setOnCardClick 不在 chart 上 (写错会抛异常,把 updateTree 一起带走 → 整张图空白,页面照样 200)。 - 关掉 setSingleParentEmptyCard:库默认给孩子只登记一位父母的人自动补一张无名 配偶卡,看着像「凭空多出一个配偶」。 - 卡片用原生 <a> 链成员页,不依赖库的点击回调。 观影按钮(用户本轮原话): - 「记一场电影」与「设置」高度仍不一致 —— 根因是文字按钮高度由 padding+line-height 自然推出(43.8px),而 .btn-icon 写死了 40px。抽出 --act-* / --act-h 变量,两边同源。 - 设置按钮去掉「设置」二字,只留图标,图标换成三条横线(☰)。 - 设置按钮在所有页面排最右(.movie-set 用 margin-left:auto 顶到行尾)。 - 除设置外其他按钮都有颜色,与设置区分(主按钮实心 / 次要浅底 / 危险淡红)。 顺带修掉一个特异性 bug:删除按钮被 .btn 品牌底盖成实心红,与「编辑」难分辨。 - 设置下拉四个条目文字前都加图标(行内 SVG,不引外部字体)。 测试与部署: - 新增 _fb_kin_check.py(桌面,12 条)+ _fb_kin_falsify.py(6/6)证明 「整张家谱空白」这类只靠通用几何抓不到的坏法能被抓住。 - _fb_geom_mobile.py 家谱段重写为窄屏语义(库按容器 fit 缩放是正常行为, 改为断「比例没被压扁 / 缩放不至于看不清」),并加 _fb_kin_mobile_falsify.py(4/4)。 - _fb_btn_check.py(59 条)+ _fb_btn_falsify.py(3/3)覆盖观影页头按钮五条需求。 - familybook_deploy.sh / familybook_smoke.sh 的家谱断言改为第三方库形态, 设置按钮断言改为 btn-icon 纯图标 + 三条横线 + 条目图标。 - 新增 .gitattributes:vendor 库与 .min.js 标 -text,原样入库不被改写行尾。
This commit is contained in:
+195
-121
@@ -21,6 +21,19 @@
|
||||
--radius-s: 10px;
|
||||
--shadow: 0 1px 2px rgba(44, 35, 29, .05);
|
||||
--shadow-l: 0 4px 16px rgba(44, 35, 29, .08);
|
||||
|
||||
/* ---- 动作按钮的统一度量 ----
|
||||
用户提过三次「设置按钮和记一场电影按钮高度要一致」。为杜绝再犯,
|
||||
这里把按钮高度拆成 4 个变量,并算出唯一的高度:
|
||||
--act-h = 上下内边距 + 行高 + 上下边框 = 9*2 + 14*1.7 + 1*2 = 43.8px
|
||||
文字按钮靠 padding + line-height 自然撑到这个高度;
|
||||
**只有图标的方形按钮**(.btn-icon)显式写高度,但取的是同一个 --act-h,
|
||||
这样两边永远相等,改一处就同步。 */
|
||||
--act-pad-y: 9px;
|
||||
--act-pad-x: 16px;
|
||||
--act-font: 14px;
|
||||
--act-line: 1.7;
|
||||
--act-h: calc(var(--act-pad-y) * 2 + var(--act-font) * var(--act-line) + 1px * 2);
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
@@ -100,15 +113,41 @@ a:hover { text-decoration: underline; }
|
||||
border-radius: 0 0 8px 8px; color: var(--muted);
|
||||
}
|
||||
.menu-list .menu-exit:hover { color: var(--brand); }
|
||||
/* ---- 观影页的「设置」下拉(v11):一个齿轮图标 + <details> 菜单 ---- */
|
||||
.movie-set { position: relative; }
|
||||
/* ---- 观影页的「设置」下拉:图标按钮 + 永远贴右 ----
|
||||
用户明确要求(2026-10-01):
|
||||
· 去掉「设置」二字,只留**三条横线**图标(☰);
|
||||
· 在**所有页面都排在最右侧**(位置统一);
|
||||
· 点开后的每条条目,**文字前都要有图标**;
|
||||
· 除设置外,其它按钮都要**有颜色**,跟设置区分开。
|
||||
贴右的做法:`margin-left:auto` 把它推到动作区最右端 —— 这样无论各页把片段
|
||||
require 在 actions 的哪个位置(有的写在最前、有的写在最后),它都贴右,
|
||||
不必逐页调顺序,也就不会有"某个页面漏了"的情况。 */
|
||||
.movie-set { position: relative; margin-left: auto; }
|
||||
.movie-set > summary {
|
||||
list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
|
||||
list-style: none; cursor: pointer; display: inline-flex; align-items: center;
|
||||
justify-content: center; gap: 6px;
|
||||
}
|
||||
.movie-set > summary::-webkit-details-marker { display: none; }
|
||||
.movie-set[open] > summary { border-color: var(--brand); color: var(--brand); }
|
||||
/* 观影设置菜单是顶栏菜单的复用:位置从右上角改成按钮下方左对齐 */
|
||||
.movie-set .menu-list { left: 0; right: auto; top: calc(100% + 8px); }
|
||||
|
||||
/* 方形图标按钮:只有图标、无文字。高度**必须**取 --act-h,
|
||||
与「记一场电影」等实心按钮同高(那个高度由 --act-pad-y/--act-font/--act-line 推出)。
|
||||
⚠️ 别在这里另写一个数字(曾写死 40px,比文字按钮的 43.8px 矮了 3.8px,被用户连续投诉)。 */
|
||||
.btn-icon {
|
||||
background: #fff; color: var(--ink); border: 1px solid var(--line);
|
||||
padding: 0 !important; width: var(--act-h); height: var(--act-h); min-width: var(--act-h);
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
line-height: 1;
|
||||
}
|
||||
.btn-icon:hover { background: #FAF7F1; color: var(--brand); border-color: var(--brand); }
|
||||
.btn-icon svg { display: block; }
|
||||
|
||||
/* 观影设置菜单:从右上角改成**按钮下方右对齐**(按钮贴右,菜单也贴右才不会跑出屏外) */
|
||||
.movie-set .menu-list { left: auto; right: 0; top: calc(100% + 8px); }
|
||||
.movie-set .menu-list a { display: flex; align-items: center; gap: 10px; }
|
||||
.movie-set .menu-list a .mi { flex: 0 0 16px; color: var(--muted); }
|
||||
.movie-set .menu-list a:hover .mi,
|
||||
.movie-set .menu-list a.on .mi { color: currentColor; }
|
||||
.movie-set .menu-list a.on { color: var(--brand); background: var(--line-2); }
|
||||
.link-quiet { color: var(--muted); font-size: 14px; }
|
||||
.link-quiet:hover { color: var(--brand); }
|
||||
@@ -124,21 +163,10 @@ a:hover { text-decoration: underline; }
|
||||
.page-head h1 { font-size: 22px; font-weight: 600; margin: 0; }
|
||||
.page-head .sub { color: var(--muted); font-size: 14px; }
|
||||
.page-head .actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
|
||||
/* ---- 页头动作区:所有按钮一律同尺寸 ----
|
||||
⚠️ 用户明确提过两次:「设置按钮和记一场电影按钮高度要一致,现在不好看」
|
||||
「返回等按钮和记一场电影等按钮的大小高度的统一问题」。
|
||||
根因是页头里混用了 .btn 与 .btn-sm 两档(padding 9px16px vs 5px12px),
|
||||
并排就一高一矮。这里**强制**让页头动作区的按钮回到基础档:
|
||||
· 按钮(.btn / .btn-ghost / .btn-danger,含 <details> 的 summary)统一 padding 与字号;
|
||||
· 表单包裹的按钮(删除那种 <form><button>)也一样 —— 它们才是真正的按钮。
|
||||
为什么用直接子选择器 + 后代 button:页头里只会有这两类交互元素,
|
||||
范围收敛、不会误伤正文里的 .btn-sm(那里小一档是刻意的)。 */
|
||||
.page-head .actions > .btn,
|
||||
.page-head .actions > .movie-set > summary.btn,
|
||||
.page-head .actions > form > .btn,
|
||||
.page-head .actions > form > button.btn {
|
||||
padding: 9px 16px; font-size: 14px;
|
||||
}
|
||||
/* ---- 页头动作区的完整规格见**文件靠后**的「页头动作区」一节 ----
|
||||
刻意放后面:.btn / .btn-ghost / .btn-icon 等基类定义在文件中部,
|
||||
CSS 同特异性「后写的赢」——放这里会被它们覆盖(踩过:设置按钮被染成品牌底、
|
||||
btn-ghost 仍是白的)。此处只留布局,样式集中在后面一处,便于对照。 */
|
||||
|
||||
.section { margin-top: 28px; }
|
||||
.section-title {
|
||||
@@ -272,7 +300,8 @@ textarea.input { min-height: 76px; resize: vertical; }
|
||||
|
||||
.btn {
|
||||
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
||||
padding: 9px 16px; font: inherit; font-size: 14px; font-weight: 500;
|
||||
padding: var(--act-pad-y) var(--act-pad-x);
|
||||
font: inherit; font-size: var(--act-font); line-height: var(--act-line); font-weight: 500;
|
||||
border-radius: var(--radius-s); border: 1px solid transparent; cursor: pointer;
|
||||
background: var(--brand); color: #fff; transition: background .15s ease;
|
||||
}
|
||||
@@ -396,111 +425,90 @@ textarea.input { min-height: 76px; resize: vertical; }
|
||||
}
|
||||
|
||||
/* ---------------- 家谱(以我为中心) ----------------
|
||||
v12 改版:**整棵树只有一个 grid**,「辈分行 / 卡片行 / 连线行」都只是它的行。
|
||||
连线(横杆 .tc-bar / 上引线 .tc-up / 下引线 .tc-down)全是网格项、靠 justify-self 落位,
|
||||
因此「竖线落在哪一列」由浏览器按列算 —— 没有任何 px 或百分比换算,天然对齐。
|
||||
v13:改由第三方库 **family-chart**(D3 生态,MIT)画,不再自研网格布局。
|
||||
|
||||
⚠️ v11 是「每代各建一个网格」,那是「线乱」的根因:列宽最小值是 minmax(min-content,1fr),
|
||||
由各自的内容决定 —— 有夫妻的那一代最小要「两卡 + 短横」、单身那代只要一卡,
|
||||
于是窄屏实测各代列宽 93.5px vs 164/78/78/78px,同一条竖线上下相差 31~62px。
|
||||
v12 用一份 grid-template-columns 贯穿全树,这个偏差从构造上就不存在。 */
|
||||
.tree { display: flex; flex-direction: column; align-items: center; gap: 0; }
|
||||
.tree-inner {
|
||||
为什么不再自研:v12 的「整棵树一个 grid」几何上对齐了,但连线的横杆是**网格项**,
|
||||
只能横跨「从父母列到子女列」的整段列区间 —— 中间只要夹着跟这条血缘无关的人
|
||||
(最典型是配偶带进来的岳父母),横杆就会从他们卡片中间穿过去。这是布局范式的死结,
|
||||
不是调样式能救的;换成库的树算法之后这层结构本身就不存在了。
|
||||
|
||||
⚠️ 库自己的 family-chart.css **没有引入**:实测库里所有规则都写在 `.f3` 作用域下,
|
||||
而运行时并不会生成任何 `.f3` 元素(卡片定位全靠 inline style)——引进来是死文件,
|
||||
白白多 16KB。所以下面这些是**库真正需要**的那几条,全部收在 `.kin-chart` 作用域里。
|
||||
|
||||
⚠️ 卡片/连线都不是我们生成的:卡片是库建的真实 <div>(.card_cont > .card > 我们的
|
||||
.kin-card),连线是 svg 里的 <path class="link">。改版式只能从这两个钩子下手。 */
|
||||
|
||||
.kin-chart {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow-x: auto; /* 家里人再多也不挤:横向滚,不改版心 */
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding-bottom: 4px;
|
||||
/* 太矮三代挤成一团、太高白占屏 */
|
||||
height: clamp(420px, 62vh, 720px);
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius);
|
||||
box-shadow: var(--shadow);
|
||||
overflow: hidden;
|
||||
/* 库自己接管拖拽/缩放,别让浏览器插手 */
|
||||
touch-action: none;
|
||||
}
|
||||
.tree-grid {
|
||||
--col-w: 96px; /* 一列 = 一张卡片宽(窄屏媒体查询里改 78px) */
|
||||
--col-gap: 14px; /* 列间距,同时也是夫妻短横的宽度(两处必须一致) */
|
||||
display: grid;
|
||||
gap: var(--col-gap);
|
||||
justify-content: center; /* 列宽固定,整棵树居中(家里人少时不左靠) */
|
||||
align-items: start;
|
||||
/* ⚠️ min-width 必须是 min-content:让网格按内容自然展开,.tree-inner 才有东西可滚。
|
||||
写成 100% 的话窄屏会把列一路压到 --col-w 以下,同代卡片就会重叠。 */
|
||||
min-width: min-content;
|
||||
/* 库在容器里自己建 #f3Canvas(position:relative; width/height:100%),
|
||||
再往里插 svg.main_svg 与 #htmlSvg。这里只要保证那两层撑满。 */
|
||||
.kin-chart #f3Canvas,
|
||||
.kin-chart #htmlSvg { width: 100%; height: 100%; }
|
||||
|
||||
/* ⚠️ 库的 `.f3 svg.main_svg{width:100%;height:100%}` 选择器**永远不会命中**
|
||||
(SVG 的直接父是 #f3Canvas,中间没有 .f3 元素)→ svg 会退回默认的 300×150,
|
||||
于是库按 300×150 算 fit,整棵树被缩到 0.4 倍、卡片只有 37px 宽。
|
||||
这里直接点名修掉。 */
|
||||
.kin-chart svg.main_svg { width: 100%; height: 100%; display: block; }
|
||||
|
||||
/* 连线:库默认 stroke="#fff"(深色主题),在浅色纸底上等于隐形 —— 必须覆盖成褐灰。
|
||||
用 !important 是因为颜色是**写在 path 的行内属性**上的(stroke="#fff"),
|
||||
普通 CSS 声明(无论特异性)都压不过行内属性;这个钩子是唯一入口。 */
|
||||
.kin-chart .link,
|
||||
.kin-chart path.link { stroke: #C9BDA9 !important; stroke-width: 1.5 !important; }
|
||||
|
||||
/* 卡片:库给 .card_cont 定位、给 .card 一律加 translate(-50%,-50%)(居中锚点),
|
||||
我们只负责卡面观感。 */
|
||||
.kin-chart .card { background: transparent; border: 0; }
|
||||
|
||||
.kin-card {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 3px;
|
||||
width: 116px; box-sizing: border-box; padding: 9px 8px 8px;
|
||||
text-align: center;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 14px;
|
||||
box-shadow: var(--shadow);
|
||||
color: var(--ink);
|
||||
transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
|
||||
}
|
||||
.tree-gen-label {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
margin: 0 0 8px; padding-left: 2px;
|
||||
.kin-chart .card:hover .kin-card {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-l);
|
||||
border-color: var(--brand-2);
|
||||
}
|
||||
.tree-gen-label .gname { font-size: 13px; font-weight: 600; color: var(--ink); }
|
||||
.tree-gen-label .gtag {
|
||||
font-size: 11px; color: var(--muted); background: var(--line-2);
|
||||
padding: 1px 8px; border-radius: 999px;
|
||||
.kin-card .kin-ph {
|
||||
width: 46px; height: 46px; border-radius: 50%; overflow: hidden;
|
||||
background: #F1E7D6; flex: 0 0 auto;
|
||||
}
|
||||
/* 一「户」= 网格里的连续若干列(夫妻跨 2 列、单人 1 列;inline 给 grid-column)。
|
||||
⚠️ width:100% 是必需的:grid 项默认按内容宽(stretch 只在没写 width 时生效),
|
||||
显式撑满它所占的那几列后,「两张卡 + 一根短横」才能正好落进「两列 + 一个间距」。 */
|
||||
.tree-unit {
|
||||
display: flex; align-items: center; justify-content: center; gap: 0;
|
||||
position: relative; width: 100%;
|
||||
}
|
||||
/* 夫妻之间的短横:宽度**必须等于列间距 --col-gap** —— 这样「同一户内的两个卡」
|
||||
与「相邻两户的两个卡」看起来是同一个节奏,且跨两列的户宽度正好等于该跨距。 */
|
||||
.tree-bond { width: var(--col-gap); flex: 0 0 auto; display: flex; align-items: center; }
|
||||
/* 夫妻之间的短横(那根"连着的两个人"的横线) */
|
||||
.tree-bond i {
|
||||
display: block; width: 100%; height: 2px; border-radius: 2px;
|
||||
background: var(--line); transform: translateY(2px);
|
||||
}
|
||||
.tnode {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 5px;
|
||||
/* ⚠️ flex:0 0 auto 是必需的(v11 实测踩到):.tnode 是 .tree-unit(flex)的子项,
|
||||
默认 flex-shrink:1 会让卡片**先被压**,列地板的 min-content 也跟着变小 ——
|
||||
等于把「列不许压到卡片以下」这条设计从内部掏空了。卡宽由下面的 width 定,
|
||||
窄屏另有 78px 的媒体查询(那是刻意的窄版式,不是压缩)。 */
|
||||
flex: 0 0 auto; width: 96px; padding: 12px 6px 10px; text-align: center;
|
||||
background: var(--surface); border: 1px solid var(--line);
|
||||
border-radius: 14px; box-shadow: var(--shadow);
|
||||
color: var(--ink); transition: transform .15s ease, box-shadow .15s ease;
|
||||
}
|
||||
.tnode:hover { transform: translateY(-2px); box-shadow: var(--shadow-l); text-decoration: none; }
|
||||
.tnode .tph { width: 52px; height: 52px; border-radius: 50%; overflow: hidden; background: #F1E7D6; }
|
||||
.tnode .tph img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
.tnode .tname { font-size: 13px; font-weight: 600; line-height: 1.3; }
|
||||
.tnode .tlabel { font-size: 11px; color: var(--brand); }
|
||||
.tnode .tph-mark { font-size: 10px; color: var(--faint); }
|
||||
.tnode.is-me {
|
||||
.kin-card .kin-ph img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
.kin-card .kin-nm { font-size: 13px; font-weight: 600; line-height: 1.3; }
|
||||
.kin-card .kin-lb { font-size: 11px; color: var(--brand); line-height: 1.35; }
|
||||
.kin-card .kin-mark { font-size: 10px; color: var(--faint); }
|
||||
|
||||
/* 「我」:品牌色描边 + 光圈 */
|
||||
.kin-card.is-me {
|
||||
border-color: var(--brand);
|
||||
box-shadow: 0 0 0 3px rgba(168, 74, 40, .12), var(--shadow);
|
||||
}
|
||||
.tnode.is-me .tlabel { color: var(--brand-ink); font-weight: 600; }
|
||||
.tnode.is-placeholder { border-style: dashed; }
|
||||
/* 因婚姻进图、上下都不接血的旁支(如妻子的父母):虚线边框 + 角标,免得像断线 */
|
||||
.tnode.is-inlaw { border-style: dashed; background: #FCFAF6; }
|
||||
.tree-inlaw-tag {
|
||||
position: absolute; top: -8px; right: 0;
|
||||
font-size: 10px; color: var(--faint); background: var(--paper);
|
||||
border: 1px solid var(--line); border-radius: 999px; padding: 0 6px;
|
||||
}
|
||||
/* ---- 父母折线(family elbow)----
|
||||
.tc-bar = 横杆(跨「父母户 → 它的子女们」那几列)
|
||||
.tc-up = 上引线(落在**父母那一户**的中心,从横杆往上接到父母)
|
||||
.tc-down = 下引线(落在**子女本人**那一列的中心,从横杆往下接到子女)
|
||||
⚠️ 三者都是网格项,靠 justify-self 定位,不写任何 left/百分比 —— 这是「线不乱」的关键。 */
|
||||
.tc-bar {
|
||||
align-self: end; justify-self: stretch;
|
||||
height: 30px; position: relative; margin-bottom: -2px;
|
||||
}
|
||||
.tc-bar::before {
|
||||
content: ''; position: absolute; left: 0; right: 0; bottom: 0;
|
||||
height: 2px; background: var(--line); border-radius: 2px;
|
||||
}
|
||||
.tc-up {
|
||||
align-self: end; justify-self: center;
|
||||
width: 2px; height: 15px; background: var(--line);
|
||||
margin-bottom: 14px; /* 横杆在上引线下方 14px 处,两者接得上 */
|
||||
}
|
||||
.tc-down {
|
||||
align-self: start; justify-self: center;
|
||||
width: 2px; height: 15px; background: var(--line);
|
||||
margin-top: -2px;
|
||||
}
|
||||
.tree-legend { font-size: 12px; color: var(--muted); margin: 14px 2px 0; }
|
||||
.kin-card.is-me .kin-lb { color: var(--brand-ink); font-weight: 600; }
|
||||
|
||||
/* 「待确认」(只填了称呼、没对应到真人):虚线 */
|
||||
.kin-card.is-ph { border-style: dashed; background: #FCFAF6; }
|
||||
|
||||
.tree-legend { font-size: 12px; color: var(--muted); margin: 14px 2px 0; }
|
||||
/* 详情页里的迷你家谱 */
|
||||
.mini-tree { display: flex; flex-direction: column; gap: 8px; }
|
||||
.mini-gen { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||
@@ -567,11 +575,6 @@ textarea.input { min-height: 76px; resize: vertical; }
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.rel-form { grid-template-columns: 1fr; }
|
||||
.tnode { width: 78px; padding: 8px 4px 7px; }
|
||||
.tnode .tph { width: 40px; height: 40px; }
|
||||
/* 窄屏收窄列宽与列间距:卡宽 78px,与上面 .tnode 的窄版式对齐 */
|
||||
.tree-grid { --col-w: 78px; --col-gap: 8px; }
|
||||
.tree-unit { padding: 0; }
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
@@ -784,6 +787,77 @@ textarea.input { min-height: 76px; resize: vertical; }
|
||||
.del-wrap > summary { list-style: none; cursor: pointer; }
|
||||
.del-wrap[open] { flex: 1 1 100%; }
|
||||
.del-confirm { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; padding: 8px 0 2px; }
|
||||
/* ---- 页头动作区:统一尺寸 + 除设置外都要「有颜色」 ----
|
||||
⚠️ 本节刻意放在**文件靠后**:.btn / .btn-ghost / .btn-danger / .btn-icon
|
||||
的定义都在前面,CSS 同特异性时「后写的赢」——放前面会被它们覆盖
|
||||
(实测过:放前面时 .btn-icon 白底被 .btn 的品牌底盖掉、.btn-ghost 也还是白的)。
|
||||
用户明确提过三次:
|
||||
·「设置按钮和记一场电影按钮高度要一致」
|
||||
·「返回等按钮和记一场电影等按钮的大小高度的统一问题」
|
||||
·「设置按钮…只保留图标,图标换成三条横线;除设置,其他按钮都要有颜色」 */
|
||||
.page-head .actions > .btn,
|
||||
.page-head .actions > .movie-set > summary.btn,
|
||||
.page-head .actions > form > .btn,
|
||||
.page-head .actions > form > button.btn {
|
||||
padding: var(--act-pad-y) var(--act-pad-x); font-size: var(--act-font);
|
||||
}
|
||||
/* 层 1:主按钮(裸 .btn,无修饰类)—— 品牌实心。
|
||||
⚠️ `.btn` 同时出现在 `<a class="btn">` 和 `<form><button class="btn">`,
|
||||
两条路径的选择器都要写出来,且**特异性必须相等**,否则后面层 2/3
|
||||
按类名匹配的规则压不住它(下层靠"同特异性 + 后写"取胜)。 */
|
||||
.page-head .actions > .btn:not(.btn-icon),
|
||||
.page-head .actions > form > .btn:not(.btn-icon),
|
||||
.page-head .actions > form > button.btn:not(.btn-icon) {
|
||||
background: var(--brand); color: #fff; border-color: transparent;
|
||||
}
|
||||
.page-head .actions > .btn:not(.btn-icon):hover,
|
||||
.page-head .actions > form > button.btn:not(.btn-icon):hover { background: #944022; }
|
||||
|
||||
/* 层 2:次要按钮(.btn-ghost)—— 品牌描边 + 极浅品牌底,比主按钮轻一档。
|
||||
a / button 两种形态各写一条、特异性对齐(见层 1 的警告)。 */
|
||||
.page-head .actions > .btn-ghost:not(.btn-icon),
|
||||
.page-head .actions > a.btn-ghost:not(.btn-icon),
|
||||
.page-head .actions > form > .btn-ghost:not(.btn-icon),
|
||||
.page-head .actions > form > button.btn-ghost:not(.btn-icon) {
|
||||
background: #FDF7F2; color: var(--brand); border-color: rgba(168, 74, 40, .45);
|
||||
}
|
||||
.page-head .actions > .btn-ghost:not(.btn-icon):hover,
|
||||
.page-head .actions > a.btn-ghost:not(.btn-icon):hover,
|
||||
.page-head .actions > form > .btn-ghost:not(.btn-icon):hover,
|
||||
.page-head .actions > form > button.btn-ghost:not(.btn-icon):hover {
|
||||
background: #F7EDE4; border-color: var(--brand);
|
||||
}
|
||||
|
||||
/* 层 3:危险按钮(.btn-danger)—— 淡红底 + 红字,同样要有颜色、但不能看着像主按钮。
|
||||
⚠️ 实测踩过:只写 `.actions > form > .btn-danger`(0,4,0)会被层 1 的
|
||||
`.actions > form > button.btn`(0,4,1)压掉 —— 详情页的「删除」按钮
|
||||
在浏览器里显示成品牌砖红实心,跟「编辑」几乎分不出来。补上 `button.`
|
||||
形态后特异性升到 (0,4,2),才真正生效。 */
|
||||
.page-head .actions > .btn-danger:not(.btn-icon),
|
||||
.page-head .actions > a.btn-danger:not(.btn-icon),
|
||||
.page-head .actions > form > .btn-danger:not(.btn-icon),
|
||||
.page-head .actions > form > button.btn-danger:not(.btn-icon) {
|
||||
background: #FDF1EE; color: var(--red); border-color: rgba(192, 83, 63, .45);
|
||||
}
|
||||
.page-head .actions > .btn-danger:not(.btn-icon):hover,
|
||||
.page-head .actions > a.btn-danger:not(.btn-icon):hover,
|
||||
.page-head .actions > form > .btn-danger:not(.btn-icon):hover,
|
||||
.page-head .actions > form > button.btn-danger:not(.btn-icon):hover { background: #F7E4DF; }
|
||||
/* 「设置」图标按钮:**唯一无色的**(白底描边、方形),与上面所有彩色按钮区分。
|
||||
padding 归零、做成正方形,但高度必须仍是 --act-h(= 文字按钮的 43.8px)——
|
||||
写死过 40px,比旁边按钮矮 3.8px,是用户反复反馈的那个问题。 */
|
||||
.page-head .actions > .movie-set > summary.btn-icon,
|
||||
.page-head .actions > .movie-set > summary.btn {
|
||||
padding: 0;
|
||||
width: var(--act-h); height: var(--act-h); min-width: var(--act-h); line-height: 1;
|
||||
background: #fff; color: var(--ink); border: 1px solid var(--line);
|
||||
}
|
||||
.page-head .actions > .movie-set > summary.btn-icon:hover,
|
||||
.page-head .actions > .movie-set > summary.btn:hover {
|
||||
background: #FAF7F1; border-color: var(--brand); color: var(--brand);
|
||||
}
|
||||
.movie-set[open] > summary.btn-icon,
|
||||
.movie-set[open] > summary.btn { border-color: var(--brand); color: var(--brand); }
|
||||
.btn.danger { color: var(--red); border-color: rgba(192, 83, 63, .35); }
|
||||
.btn.danger:hover { background: rgba(192, 83, 63, .08); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user