refactor(styles): 建立统一的生产级样式体系 (#4)
## 变更内容 - 将全局样式拆分为设计令牌、基础规则和语义组件层 - 集中管理 Naive UI 主题配置 - 迁移页面容器、表单、信息面板和按钮等重复样式 - 增加样式体系文档与自动契约检查 ## 验证 - `npm run check:styles` - `npm run build`Reviewed-on: #4
This commit was merged in pull request #4.
This commit is contained in:
@@ -0,0 +1,314 @@
|
||||
@layer components {
|
||||
/* Application and page structure */
|
||||
.oc-app-shell {
|
||||
@apply flex min-h-screen flex-col;
|
||||
background: var(--oc-gradient-canvas);
|
||||
}
|
||||
|
||||
.oc-app-grid {
|
||||
@apply pointer-events-none absolute inset-0 opacity-35;
|
||||
background-image: var(--oc-gradient-grid);
|
||||
background-size: 32px 32px;
|
||||
}
|
||||
|
||||
.oc-page-hero {
|
||||
@apply border-b border-sky-100;
|
||||
background: var(--oc-gradient-page);
|
||||
}
|
||||
|
||||
.oc-page-hero--soft {
|
||||
background: var(--oc-gradient-page-soft);
|
||||
}
|
||||
|
||||
.oc-container {
|
||||
@apply mx-auto w-full px-4 sm:px-6 lg:px-8;
|
||||
}
|
||||
|
||||
.oc-container--narrow {
|
||||
@apply max-w-4xl;
|
||||
}
|
||||
|
||||
.oc-container--content {
|
||||
@apply max-w-6xl;
|
||||
}
|
||||
|
||||
.oc-container--wide {
|
||||
@apply max-w-7xl;
|
||||
}
|
||||
|
||||
.oc-page-hero__inner {
|
||||
@apply py-10;
|
||||
}
|
||||
|
||||
.oc-page-content {
|
||||
@apply py-8;
|
||||
}
|
||||
|
||||
.oc-page-eyebrow {
|
||||
@apply text-sm font-medium uppercase tracking-[0.24em] text-sky-700;
|
||||
}
|
||||
|
||||
.oc-page-title {
|
||||
@apply mt-3 text-4xl font-bold text-slate-900;
|
||||
}
|
||||
|
||||
.oc-page-description {
|
||||
@apply mt-4 max-w-2xl text-sm leading-7 text-slate-600;
|
||||
}
|
||||
|
||||
/* Reusable text hierarchy */
|
||||
.oc-section-label {
|
||||
@apply text-xs uppercase tracking-[0.18em] text-slate-500;
|
||||
}
|
||||
|
||||
.oc-stat-label {
|
||||
@apply text-xs uppercase tracking-[0.2em] text-slate-500;
|
||||
}
|
||||
|
||||
.oc-stat-value {
|
||||
@apply mt-2 text-2xl font-bold text-slate-900;
|
||||
}
|
||||
|
||||
.oc-meta {
|
||||
@apply text-sm text-slate-500;
|
||||
}
|
||||
|
||||
.oc-field-label {
|
||||
@apply mb-1 block text-sm font-medium text-slate-700;
|
||||
}
|
||||
|
||||
.oc-field-required {
|
||||
@apply text-rose-500;
|
||||
}
|
||||
|
||||
.oc-field-control {
|
||||
@apply w-full border border-slate-300 bg-white px-3 py-2.5 text-sm text-slate-800 outline-none transition-colors;
|
||||
@apply focus:border-sky-500 focus:ring-2 focus:ring-sky-100;
|
||||
}
|
||||
|
||||
.oc-field-error {
|
||||
@apply mt-1 text-sm text-rose-600;
|
||||
}
|
||||
|
||||
.oc-field-help {
|
||||
@apply mt-1 text-sm text-slate-500;
|
||||
}
|
||||
|
||||
/* Surfaces */
|
||||
.oc-panel-card {
|
||||
box-shadow: var(--oc-shadow-md) !important;
|
||||
}
|
||||
|
||||
.oc-panel-card-soft {
|
||||
box-shadow: 6px 6px 0 0 rgb(15 23 42 / 4%) !important;
|
||||
}
|
||||
|
||||
.oc-empty-card {
|
||||
box-shadow: 6px 6px 0 0 rgb(15 23 42 / 4%);
|
||||
}
|
||||
|
||||
.oc-surface {
|
||||
@apply border border-slate-200 bg-white;
|
||||
box-shadow: var(--oc-shadow-md);
|
||||
}
|
||||
|
||||
.oc-inset-panel {
|
||||
@apply border border-slate-200 bg-slate-50 p-4;
|
||||
}
|
||||
|
||||
.oc-map-button {
|
||||
@apply flex h-10 w-10 items-center justify-center bg-white shadow-md transition-colors hover:bg-slate-50;
|
||||
border-radius: 0.5rem !important;
|
||||
}
|
||||
|
||||
.oc-system-page {
|
||||
@apply flex min-h-[calc(100vh-4rem)] items-center justify-center px-4 py-10;
|
||||
}
|
||||
|
||||
.oc-system-card {
|
||||
@apply w-full max-w-2xl border border-slate-200 bg-white px-8 py-14 text-center;
|
||||
box-shadow: var(--oc-shadow-xl);
|
||||
}
|
||||
|
||||
/* Naive UI button contract */
|
||||
.oc-primary-button.n-button,
|
||||
.oc-panel-button.n-button {
|
||||
transition:
|
||||
background-color var(--oc-duration-fast) var(--oc-ease-standard),
|
||||
color var(--oc-duration-fast) var(--oc-ease-standard),
|
||||
border-color var(--oc-duration-fast) var(--oc-ease-standard),
|
||||
box-shadow var(--oc-duration-fast) var(--oc-ease-standard),
|
||||
transform var(--oc-duration-fast) var(--oc-ease-standard);
|
||||
}
|
||||
|
||||
.oc-primary-button.n-button .n-button__content,
|
||||
.oc-panel-button.n-button .n-button__content {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.oc-primary-button.n-button .n-button__content {
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
|
||||
.oc-primary-button.n-button:not(.n-button--disabled):hover,
|
||||
.oc-panel-button.n-button:not(.n-button--disabled):hover,
|
||||
.oc-panel-button.n-button:focus-visible {
|
||||
transform: translate(-1px, -1px);
|
||||
}
|
||||
|
||||
.oc-primary-button--teal.n-button {
|
||||
border-color: rgb(153 246 228) !important;
|
||||
background: rgb(255 255 255) !important;
|
||||
color: rgb(17 94 89) !important;
|
||||
box-shadow: var(--oc-shadow-teal) !important;
|
||||
}
|
||||
|
||||
.oc-primary-button--teal.n-button:hover,
|
||||
.oc-primary-button--teal.n-button:focus-visible {
|
||||
border-color: rgb(94 234 212) !important;
|
||||
background: rgb(234 250 245) !important;
|
||||
color: rgb(19 78 74) !important;
|
||||
}
|
||||
|
||||
.oc-primary-button--teal.n-button:not(.n-button--disabled):hover {
|
||||
box-shadow: 5px 5px 0 0 rgb(20 184 166 / 14%) !important;
|
||||
}
|
||||
|
||||
.oc-primary-button--sky.n-button {
|
||||
border-color: rgb(186 230 253) !important;
|
||||
background: rgb(255 255 255) !important;
|
||||
color: rgb(7 89 133) !important;
|
||||
box-shadow: var(--oc-shadow-sky) !important;
|
||||
}
|
||||
|
||||
.oc-primary-button--sky.n-button:hover,
|
||||
.oc-primary-button--sky.n-button:focus-visible {
|
||||
border-color: rgb(125 211 252) !important;
|
||||
background: rgb(240 249 255) !important;
|
||||
color: rgb(12 74 110) !important;
|
||||
}
|
||||
|
||||
.oc-primary-button--sky.n-button:not(.n-button--disabled):hover {
|
||||
box-shadow: 5px 5px 0 0 rgb(14 165 233 / 18%) !important;
|
||||
}
|
||||
|
||||
.oc-panel-button.n-button {
|
||||
--n-color: rgb(255 255 255) !important;
|
||||
--n-color-hover: rgb(240 253 250) !important;
|
||||
--n-color-pressed: rgb(236 253 245) !important;
|
||||
--n-border: 1px solid rgb(226 232 240) !important;
|
||||
--n-border-hover: 1px solid rgb(153 246 228) !important;
|
||||
--n-border-pressed: 1px solid rgb(94 234 212) !important;
|
||||
--n-text-color: rgb(71 85 105) !important;
|
||||
--n-text-color-hover: rgb(19 78 74) !important;
|
||||
--n-text-color-pressed: rgb(17 94 89) !important;
|
||||
border-color: rgb(226 232 240) !important;
|
||||
background: rgb(255 255 255) !important;
|
||||
color: rgb(71 85 105) !important;
|
||||
box-shadow: var(--oc-shadow-xs) !important;
|
||||
}
|
||||
|
||||
.oc-panel-button--neutral.n-button:hover,
|
||||
.oc-panel-button--neutral.n-button:focus-visible {
|
||||
border-color: rgb(153 246 228) !important;
|
||||
background: rgb(240 253 250) !important;
|
||||
color: rgb(19 78 74) !important;
|
||||
box-shadow: 4px 4px 0 0 rgb(20 184 166 / 10%) !important;
|
||||
}
|
||||
|
||||
.oc-panel-button--sky.n-button {
|
||||
--n-color: rgb(224 242 254) !important;
|
||||
--n-color-hover: rgb(240 249 255) !important;
|
||||
--n-color-pressed: rgb(224 242 254) !important;
|
||||
--n-border: 1px solid rgb(186 230 253) !important;
|
||||
--n-border-hover: 1px solid rgb(125 211 252) !important;
|
||||
--n-border-pressed: 1px solid rgb(56 189 248) !important;
|
||||
--n-text-color: rgb(7 89 133) !important;
|
||||
--n-text-color-hover: rgb(12 74 110) !important;
|
||||
--n-text-color-pressed: rgb(12 74 110) !important;
|
||||
border-color: rgb(186 230 253) !important;
|
||||
background: rgb(224 242 254) !important;
|
||||
color: rgb(7 89 133) !important;
|
||||
box-shadow: var(--oc-shadow-sky) !important;
|
||||
}
|
||||
|
||||
.oc-panel-button--sky.n-button:hover,
|
||||
.oc-panel-button--sky.n-button:focus-visible {
|
||||
border-color: rgb(125 211 252) !important;
|
||||
background: rgb(240 249 255) !important;
|
||||
color: rgb(12 74 110) !important;
|
||||
box-shadow: 5px 5px 0 0 rgb(14 165 233 / 18%) !important;
|
||||
}
|
||||
|
||||
.oc-panel-button--teal.n-button {
|
||||
--n-color: rgb(242 250 247) !important;
|
||||
--n-color-hover: rgb(234 250 245) !important;
|
||||
--n-color-pressed: rgb(220 252 231) !important;
|
||||
--n-border: 1px solid rgb(153 246 228) !important;
|
||||
--n-border-hover: 1px solid rgb(94 234 212) !important;
|
||||
--n-border-pressed: 1px solid rgb(45 212 191) !important;
|
||||
--n-text-color: rgb(17 94 89) !important;
|
||||
--n-text-color-hover: rgb(19 78 74) !important;
|
||||
--n-text-color-pressed: rgb(19 78 74) !important;
|
||||
border-color: rgb(153 246 228) !important;
|
||||
background: rgb(242 250 247) !important;
|
||||
color: rgb(17 94 89) !important;
|
||||
box-shadow: var(--oc-shadow-teal) !important;
|
||||
}
|
||||
|
||||
.oc-panel-button--teal.n-button:hover,
|
||||
.oc-panel-button--teal.n-button:focus-visible {
|
||||
border-color: rgb(94 234 212) !important;
|
||||
background: rgb(234 250 245) !important;
|
||||
color: rgb(19 78 74) !important;
|
||||
box-shadow: 5px 5px 0 0 rgb(20 184 166 / 14%) !important;
|
||||
}
|
||||
|
||||
.oc-panel-button--danger.n-button {
|
||||
--n-color: rgb(255 241 242) !important;
|
||||
--n-color-hover: rgb(255 228 230) !important;
|
||||
--n-color-pressed: rgb(255 228 230) !important;
|
||||
--n-border: 1px solid rgb(254 205 211) !important;
|
||||
--n-border-hover: 1px solid rgb(253 164 175) !important;
|
||||
--n-border-pressed: 1px solid rgb(251 113 133) !important;
|
||||
--n-text-color: rgb(190 24 93) !important;
|
||||
--n-text-color-hover: rgb(159 18 57) !important;
|
||||
--n-text-color-pressed: rgb(159 18 57) !important;
|
||||
border-color: rgb(254 205 211) !important;
|
||||
background: rgb(255 241 242) !important;
|
||||
color: rgb(190 24 93) !important;
|
||||
box-shadow: 4px 4px 0 0 rgb(244 63 94 / 10%) !important;
|
||||
}
|
||||
|
||||
.oc-panel-button--danger.n-button:hover,
|
||||
.oc-panel-button--danger.n-button:focus-visible {
|
||||
border-color: rgb(253 164 175) !important;
|
||||
background: rgb(255 228 230) !important;
|
||||
color: rgb(159 18 57) !important;
|
||||
box-shadow: 5px 5px 0 0 rgb(244 63 94 / 14%) !important;
|
||||
}
|
||||
|
||||
.oc-panel-button--amber.n-button {
|
||||
--n-color: rgb(255 251 235) !important;
|
||||
--n-color-hover: rgb(254 243 199) !important;
|
||||
--n-color-pressed: rgb(253 230 138) !important;
|
||||
--n-border: 1px solid rgb(253 230 138) !important;
|
||||
--n-border-hover: 1px solid rgb(252 211 77) !important;
|
||||
--n-border-pressed: 1px solid rgb(245 158 11) !important;
|
||||
--n-text-color: rgb(146 64 14) !important;
|
||||
--n-text-color-hover: rgb(120 53 15) !important;
|
||||
--n-text-color-pressed: rgb(120 53 15) !important;
|
||||
border-color: rgb(253 230 138) !important;
|
||||
background: rgb(255 251 235) !important;
|
||||
color: rgb(146 64 14) !important;
|
||||
box-shadow: 4px 4px 0 0 rgb(245 158 11 / 10%) !important;
|
||||
}
|
||||
|
||||
.oc-panel-button--amber.n-button:hover,
|
||||
.oc-panel-button--amber.n-button:focus-visible {
|
||||
border-color: rgb(252 211 77) !important;
|
||||
background: rgb(254 243 199) !important;
|
||||
color: rgb(120 53 15) !important;
|
||||
box-shadow: 5px 5px 0 0 rgb(245 158 11 / 14%) !important;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user