This commit is contained in:
2026-08-04 17:57:01 +08:00
parent 768fd4a3a9
commit f77034edd7
641 changed files with 26137 additions and 0 deletions
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

+66
View File
@@ -0,0 +1,66 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=1920, initial-scale=1">
<base href="../../">
<title>button component catalog</title>
<link rel="stylesheet" href="src-web/index.css">
</head>
<body>
<!-- Root pages load individual templates through index.html#fragment references. -->
<template id="construction">
<div class="panel">
<div class="panel-heading"><div class="panel-title">3-slice control surface</div><div class="spec-chip asset">SOURCE ASSET</div></div>
<div class="panel-body">
<div class="anatomy">
<div class="asset-tile"><img src="src-web/button/img/sprite_interface_ninepatch_resource.NPK/ninepatch_resource.img/24.PNG" width="102" alt="button source asset"></div>
<div class="anatomy-list">
<div class="anatomy-line"><strong>Left cap</strong><span>固定像素,不横向拉伸</span></div>
<div class="anatomy-line"><strong>Center</strong><span>仅中段伸缩,承载文字</span></div>
<div class="anatomy-line"><strong>Right cap</strong><span>保留边角和金属高光</span></div>
</div>
</div>
<div class="divider"></div>
<div class="rule-label">Responsive reconstruction</div>
<div class="slice-demo">
<span class="cut left"></span><span class="cut right"></span>
<span class="slice-label" style="left:0">CAP</span><span class="slice-label" style="left:46%">STRETCHABLE FILL</span><span class="slice-label" style="right:0">CAP</span>
</div>
<div style="height:28px"></div>
<div class="btn-shell"><div class="dnf-btn large normal dnf-ui"><span class="btn-icon">+</span>创建预设</div></div>
</div>
</div>
</template>
<template id="showcase">
<div class="panel button-showcase-panel" style="height:292px;margin-bottom:18px;">
<div class="panel-heading"><div class="panel-title">TextButton / IconButton</div><div class="spec-row"><span class="spec-chip captured">CSS + NINE-PATCH PRIMARY</span><span class="spec-chip asset">ninepatch_resource.img</span></div></div>
<div class="panel-body">
<div class="sample-grid button-state-grid" style="grid-template-columns:repeat(5,1fr);">
<div class="button-implementation-label">Implementation / CSS<small>原生渐变与描边 · 可编辑</small></div>
<div class="sample-cell"><div class="sample-label">Rest</div><div class="btn-shell"><div class="dnf-btn normal dnf-ui"><span class="btn-icon">+</span>创建角色</div></div></div>
<div class="sample-cell"><div class="sample-label">Hover</div><div class="btn-shell"><div class="dnf-btn hover dnf-ui"><span class="btn-icon">+</span>创建角色</div></div></div>
<div class="sample-cell"><div class="sample-label">Pressed</div><div class="btn-shell"><div class="dnf-btn pressed dnf-ui"><span class="btn-icon">+</span>创建角色</div></div></div>
<div class="sample-cell"><div class="sample-label">Disabled</div><div class="btn-shell"><div class="dnf-btn disabled dnf-ui">购买</div></div></div>
<div class="button-implementation-label">Implementation / CSS Replica<small>CSS gradient + inner glow · primary</small></div>
<div class="sample-cell"><div class="sample-label">Rest</div><div class="btn-shell"><div class="dnf-btn image normal dnf-ui"><span class="btn-icon">+</span>创建角色</div></div></div>
<div class="sample-cell"><div class="sample-label">Hover</div><div class="btn-shell"><div class="dnf-btn image hover dnf-ui"><span class="btn-icon">+</span>创建角色</div></div></div>
<div class="sample-cell"><div class="sample-label">Pressed</div><div class="btn-shell"><div class="dnf-btn image pressed dnf-ui"><span class="btn-icon">+</span>创建角色</div></div></div>
<div class="sample-cell"><div class="sample-label">Disabled</div><div class="btn-shell"><div class="dnf-btn image disabled dnf-ui">购买</div></div></div>
<div class="button-implementation-label">CSS / Tone family<small>derived states · hover / press interactive</small></div>
<div class="sample-cell"><div class="sample-label">Default · 4–7</div><div class="btn-shell"><button type="button" class="dnf-btn raster-tone normal dnf-ui">确认</button></div></div>
<div class="sample-cell"><div class="sample-label">Green · 12–15</div><div class="btn-shell"><button type="button" class="dnf-btn raster-tone tone-green normal dnf-ui">应用</button></div></div>
<div class="sample-cell"><div class="sample-label">Orange Red · 20–23</div><div class="btn-shell"><button type="button" class="dnf-btn raster-tone tone-orange normal dnf-ui">取消</button></div></div>
<div class="sample-cell"><div class="sample-label">Disabled · captured</div><div class="btn-shell"><button type="button" class="dnf-btn raster-tone disabled dnf-ui" disabled>确认</button></div></div>
</div>
<div class="spec-row" style="margin-top:14px"><span class="spec-chip">Corner Radius = 0</span><span class="spec-chip">Shadow = None</span><span class="spec-chip">Size = Compact · Default · Large</span><span class="spec-chip">LeadingIcon = Boolean</span><span class="spec-chip">Label = Text</span><span class="spec-chip captured">Hover = Lighter 1 Tone</span><span class="spec-chip captured">Pressed = Hover Tone + Y 1px</span></div>
</div>
</div>
</template>
<script>
document.querySelectorAll('template').forEach((template) => document.body.append(template.content.cloneNode(true)));
</script>
</body>
</html>
+204
View File
@@ -0,0 +1,204 @@
/* Source module: button.css */
.btn-shell {
display: inline-flex;
padding: 4px;
border-radius: 0;
background: none;
box-shadow: none;
}
.dnf-btn {
appearance: none;
position: relative;
height: 30px;
min-width: 110px;
padding: 0 14px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 7px;
color: var(--gold);
border: 1px solid transparent;
border-radius: 0;
background:
linear-gradient(180deg, #1f355e 0%, #1d2f53 55%, #1a2849 100%) padding-box,
linear-gradient(180deg, #684f2d 0%, #483423 100%) border-box;
box-shadow: none;
font-size: 13px;
line-height: 1;
text-align: center;
white-space: nowrap;
}
button.dnf-btn {
font-family: inherit;
cursor: pointer;
}
button.dnf-btn.normal:not(.raster-tone):not(.image):hover,
button.dnf-btn.normal:not(.raster-tone):not(.image):focus-visible {
color: #eee2aa;
background:
linear-gradient(180deg, #29457f 0%, #273f74 55%, #24386a 100%) padding-box,
linear-gradient(180deg, #725f4e 0%, #524444 100%) border-box;
outline: none;
}
button.dnf-btn.normal:not(.raster-tone):not(.image):active {
color: #eee2aa;
transform: translateY(1px);
background:
linear-gradient(180deg, #29457f 0%, #273f74 55%, #24386a 100%) padding-box,
linear-gradient(180deg, #725f4e 0%, #524444 100%) border-box;
}
button.dnf-btn:disabled {
cursor: default;
}
.dnf-btn.normal {
background:
linear-gradient(180deg, #1f355e 0%, #1d2f53 55%, #1a2849 100%) padding-box,
linear-gradient(180deg, #684f2d 0%, #483423 100%) border-box;
}
.dnf-btn.hover {
color: #eee2aa;
background:
linear-gradient(180deg, #29457f 0%, #273f74 55%, #24386a 100%) padding-box,
linear-gradient(180deg, #725f4e 0%, #524444 100%) border-box;
}
.dnf-btn.pressed {
transform: translateY(1px);
background:
linear-gradient(180deg, #29457f 0%, #263e73 58%, #213462 100%) padding-box,
linear-gradient(180deg, #725f4e 0%, #524444 100%) border-box;
}
.dnf-btn.disabled {
color: #666566;
background:
linear-gradient(180deg, #2c2c2c 0%, #272727 55%, #222 100%) padding-box,
linear-gradient(180deg, #343434 0%, #262626 100%) border-box;
}
.dnf-btn.large {
height: 44px;
min-width: 168px;
font-size: 16px;
}
/* CSS replica of the compact NinePatch family. State colors are derived from the base tone. */
.dnf-btn.image,
.dnf-btn.raster-tone {
--button-top: var(--control-blue-top);
--button-bottom: var(--control-blue-bottom);
--button-edge-top: var(--control-edge-top);
--button-edge-bottom: var(--control-edge-bottom);
--button-state-top: var(--button-top);
--button-state-bottom: var(--button-bottom);
--button-state-edge-top: var(--button-edge-top);
--button-state-edge-bottom: var(--button-edge-bottom);
--button-hover-r: 10;
--button-hover-g: 16;
--button-hover-b: 33;
height: 26px;
min-width: 112px;
padding: 0 10px;
isolation:isolate;
border:1px solid rgba(0,0,0,.6);
border-radius: 0;
background:transparent;
box-shadow:none;
}
.dnf-btn.image::before,
.dnf-btn.raster-tone::before {
content:"";
position:absolute;
z-index:-1;
inset:0;
margin:1px;
border:1px solid transparent;
background:
linear-gradient(180deg,var(--button-state-top),var(--button-state-bottom)) padding-box,
linear-gradient(180deg,var(--button-state-edge-top),var(--button-state-edge-bottom)) border-box;
box-shadow:inset 0 0 0 1px rgba(0,0,0,.12);
pointer-events:none;
}
.dnf-btn.image.hover,
.dnf-btn.raster-tone.normal:hover,
.dnf-btn.raster-tone.hover {
--button-state-top:rgb(from var(--button-top) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b)));
--button-state-bottom:rgb(from var(--button-bottom) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b)));
--button-state-edge-top:rgb(from var(--button-edge-top) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b)));
--button-state-edge-bottom:rgb(from var(--button-edge-bottom) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b)));
}
.dnf-btn.image.pressed,
.dnf-btn.raster-tone.normal:active,
.dnf-btn.raster-tone.pressed {
--button-state-top:rgb(from var(--button-top) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b)));
--button-state-bottom:rgb(from var(--button-bottom) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b)));
--button-state-edge-top:rgb(from var(--button-edge-top) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b)));
--button-state-edge-bottom:rgb(from var(--button-edge-bottom) calc(r + var(--button-hover-r)) calc(g + var(--button-hover-g)) calc(b + var(--button-hover-b)));
transform:translateY(1px);
}
.dnf-btn.image.disabled,
.dnf-btn.raster-tone.disabled {
--button-state-top:var(--control-disabled-top);
--button-state-bottom:var(--control-disabled-bottom);
--button-state-edge-top:var(--control-disabled-edge-top);
--button-state-edge-bottom:var(--control-disabled-edge-bottom);
color:#666566;
}
.dnf-btn.raster-tone.tone-green {
--button-top:var(--control-green-top);
--button-bottom:var(--control-green-bottom);
--button-hover-r:10;
--button-hover-g:33;
--button-hover-b:14;
}
.dnf-btn.raster-tone.tone-orange {
--button-top:var(--control-orange-top);
--button-bottom:var(--control-orange-bottom);
--button-hover-r:33;
--button-hover-g:22;
--button-hover-b:10;
}
.button-showcase-panel .panel-body { padding:10px 18px; }
.button-state-grid { gap:4px 14px; }
.button-state-grid .sample-cell { height:44px;padding:4px 12px;display:grid;grid-template-columns:auto 1fr;align-items:center;gap:8px; }
.button-state-grid .sample-label { margin:0; }
.button-state-grid .button-implementation-label { min-height:44px;padding:5px 10px; }
.button-showcase-panel .spec-row[style] { margin-top:8px!important; }
.button-implementation-label {
min-height: 52px;
padding: 8px 10px;
display: flex;
flex-direction: column;
justify-content: center;
border-left: 2px solid var(--brass);
background: #080908;
color: var(--gold);
font-size: 13px;
}
.button-implementation-label small {
margin-top: 4px;
color: var(--muted);
font-size: 11px;
}
.dnf-btn:has(> .btn-icon),
.dnf-btn:has(> .button-glyph) { padding-inline:30px; }
.dnf-btn > .btn-icon,
.dnf-btn > .button-glyph { position:absolute;left:10px;top:50%;transform:translateY(-50%); }
.btn-icon { font: 18px/1 Georgia, serif; color: #e4c98f; }
.icon-btn {
width: 30px;
height: 30px;
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid #7a6238;
background: linear-gradient(#2e4779, #1b2b4f);
box-shadow: inset 0 0 0 1px #12203d, 0 0 0 3px #111317;
color: #ddc47e;
}
.icon-btn img, .pixel { image-rendering: pixelated; }