Files
opencloud/src/styles/components.css
T
2026-07-30 22:35:51 +08:00

633 lines
18 KiB
CSS

@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-hero__split {
@apply grid gap-6;
}
@media (min-width: 900px) {
.oc-page-hero__split {
grid-template-columns: minmax(0, 1fr) minmax(18rem, 0.9fr);
align-items: start;
}
.oc-page-hero__split--stretch {
align-items: stretch;
}
}
.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;
}
.oc-brand-mark {
@apply flex h-10 w-10 items-center justify-center border border-sky-200 bg-sky-100;
box-shadow: var(--oc-shadow-sm);
}
/* 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-xl {
box-shadow: var(--oc-shadow-xl) !important;
}
.oc-floating-panel {
box-shadow: var(--oc-shadow-lg);
}
.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-modal-shell {
@apply border border-slate-200 bg-white;
box-shadow: var(--oc-shadow-xl);
}
.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 border border-slate-200 bg-white text-slate-600;
box-shadow: var(--oc-shadow-xs);
}
/* Shared interactive contracts */
.oc-panel-button:not(.n-button),
.oc-header-button,
.oc-icon-button,
.oc-map-button,
.oc-choice-button,
.oc-text-button,
.oc-menu-item,
.oc-nav-link,
.oc-interactive-card {
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-panel-button:not(.n-button) {
@apply inline-flex min-h-9 items-center justify-center border px-3 py-2 text-sm font-medium;
}
.oc-panel-button:not(.n-button):not(:disabled):hover,
.oc-header-button:not(:disabled):hover,
.oc-icon-button:not(:disabled):hover,
.oc-map-button:not(:disabled):hover,
.oc-choice-button:not(:disabled):hover {
transform: translate(-1px, -1px);
}
.oc-panel-button--neutral:not(.n-button) {
@apply border-slate-200 bg-white text-slate-600;
box-shadow: var(--oc-shadow-xs);
}
.oc-panel-button--neutral:not(.n-button):hover,
.oc-panel-button--neutral:not(.n-button):focus-visible {
@apply border-teal-200 bg-teal-50 text-teal-800;
box-shadow: var(--oc-shadow-primary);
}
.oc-panel-button--sky:not(.n-button) {
@apply border-sky-200 bg-sky-100 text-sky-800;
box-shadow: var(--oc-shadow-sky);
}
.oc-panel-button--sky:not(.n-button):hover,
.oc-panel-button--sky:not(.n-button):focus-visible {
@apply border-sky-300 bg-sky-50 text-sky-900;
box-shadow: 5px 5px 0 0 rgb(14 165 233 / 18%);
}
.oc-panel-button--teal:not(.n-button) {
@apply border-teal-200 bg-teal-50 text-teal-800;
box-shadow: var(--oc-shadow-teal);
}
.oc-panel-button--teal:not(.n-button):hover,
.oc-panel-button--teal:not(.n-button):focus-visible {
@apply border-teal-300 bg-teal-100 text-teal-900;
box-shadow: var(--oc-shadow-primary-hover);
}
.oc-panel-button--danger:not(.n-button) {
@apply border-rose-200 bg-rose-50 text-rose-700;
box-shadow: 4px 4px 0 0 rgb(244 63 94 / 10%);
}
.oc-panel-button--danger:not(.n-button):hover,
.oc-panel-button--danger:not(.n-button):focus-visible {
@apply border-rose-300 bg-rose-100 text-rose-800;
box-shadow: 5px 5px 0 0 rgb(244 63 94 / 14%);
}
.oc-panel-button--amber:not(.n-button) {
@apply border-amber-200 bg-amber-50 text-amber-800;
box-shadow: 4px 4px 0 0 rgb(245 158 11 / 10%);
}
.oc-panel-button--amber:not(.n-button):hover,
.oc-panel-button--amber:not(.n-button):focus-visible {
@apply border-amber-300 bg-amber-100 text-amber-900;
box-shadow: 5px 5px 0 0 rgb(245 158 11 / 14%);
}
.oc-icon-button {
@apply flex h-10 w-10 shrink-0 items-center justify-center border border-slate-200 bg-white text-slate-600;
box-shadow: var(--oc-shadow-xs);
}
.oc-icon-button:hover,
.oc-icon-button:focus-visible,
.oc-map-button:hover,
.oc-map-button:focus-visible {
@apply border-teal-200 bg-teal-50 text-teal-800;
box-shadow: var(--oc-shadow-primary);
}
.oc-icon-button--small {
@apply h-8 w-8;
}
.oc-icon-button--tiny {
@apply h-6 w-6 text-xs;
box-shadow: 2px 2px 0 0 rgb(15 23 42 / 8%);
}
.oc-icon-button--sky {
@apply border-sky-200 bg-sky-50 text-sky-700;
box-shadow: 3px 3px 0 0 rgb(14 165 233 / 12%);
}
.oc-icon-button--sky:hover,
.oc-icon-button--sky:focus-visible {
@apply border-sky-300 bg-sky-100 text-sky-900;
box-shadow: 4px 4px 0 0 rgb(14 165 233 / 16%);
}
.oc-icon-button--danger {
@apply border-rose-300 bg-rose-500 text-white;
box-shadow: 3px 3px 0 0 rgb(159 18 57 / 18%);
}
.oc-icon-button--danger:hover,
.oc-icon-button--danger:focus-visible {
@apply border-rose-400 bg-rose-600 text-white;
box-shadow: 4px 4px 0 0 rgb(159 18 57 / 22%);
}
.oc-overlay-button {
@apply flex shrink-0 items-center justify-center text-white/75 hover:bg-white/10 hover:text-white;
transition:
background-color var(--oc-duration-fast) var(--oc-ease-standard),
color var(--oc-duration-fast) var(--oc-ease-standard),
transform var(--oc-duration-fast) var(--oc-ease-standard);
}
.oc-text-button {
@apply inline-flex items-center font-medium text-sky-700 underline-offset-4 hover:text-sky-900 hover:underline;
}
.oc-text-button--muted {
@apply text-slate-500 hover:text-slate-800;
}
.oc-text-button--danger {
@apply text-rose-600 hover:text-rose-800;
}
.oc-choice-button {
@apply inline-flex min-h-9 items-center justify-center border px-3 py-2 text-sm font-medium;
}
.oc-choice-button--inactive {
@apply border-slate-200 bg-white text-slate-600 hover:border-teal-200 hover:bg-teal-50 hover:text-teal-800;
box-shadow: var(--oc-shadow-xs);
}
.oc-choice-button--active {
@apply border-teal-200 bg-teal-50 text-teal-800;
box-shadow: var(--oc-shadow-primary);
}
.oc-menu-item {
@apply flex w-full items-center gap-3 px-4 py-2.5 text-left text-sm font-medium text-slate-700 hover:bg-teal-50 hover:text-teal-800;
}
.oc-menu-item--danger {
@apply text-rose-600 hover:bg-rose-50 hover:text-rose-700;
}
.oc-menu-item--amber {
@apply hover:bg-amber-50 hover:text-amber-700;
}
.oc-nav-link {
@apply px-3 py-2 text-sm font-medium uppercase tracking-[0.12em];
}
.oc-header-button {
@apply inline-flex h-8 items-center justify-center border px-3 text-sm font-medium md:h-10 md:px-4;
}
.oc-header-button--neutral {
@apply border-slate-200 bg-white/80 text-slate-700 hover:border-teal-200 hover:bg-teal-50 hover:text-teal-800;
box-shadow: var(--oc-shadow-xs);
}
.oc-header-button--sky {
@apply border-sky-200 bg-sky-100 text-sky-800 hover:border-sky-300 hover:bg-sky-50 hover:text-sky-900;
box-shadow: var(--oc-shadow-sky);
}
.oc-header-button--teal {
@apply border-teal-100 bg-white/80 text-teal-700 hover:border-teal-200 hover:bg-teal-50 hover:text-teal-800;
box-shadow: var(--oc-shadow-teal);
}
.oc-header-button:hover {
box-shadow: 5px 5px 0 0 rgb(15 23 42 / 8%);
}
.oc-interactive-card:focus-visible {
@apply outline-none ring-2 ring-sky-600 ring-offset-2;
}
.oc-interactive-card {
box-shadow: var(--oc-shadow-md);
}
.oc-interactive-card:hover {
box-shadow: var(--oc-shadow-lg);
}
.oc-interactive-card--selected {
@apply border-sky-500;
box-shadow: var(--oc-shadow-sky) !important;
}
.oc-interactive-row {
transition:
background-color var(--oc-duration-fast) var(--oc-ease-standard),
color var(--oc-duration-fast) var(--oc-ease-standard),
box-shadow var(--oc-duration-fast) var(--oc-ease-standard);
}
.oc-interactive-row:hover {
@apply bg-sky-50/60;
}
.oc-interactive-row:focus-visible,
.oc-heatmap-cell:focus-visible {
@apply outline-none ring-2 ring-sky-600 ring-offset-2;
}
.oc-heatmap-cell {
transition:
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);
}
:is(
.oc-primary-button,
.oc-panel-button,
.oc-header-button,
.oc-icon-button,
.oc-overlay-button,
.oc-map-button,
.oc-choice-button,
.oc-text-button,
.oc-menu-item,
.oc-nav-link
):focus-visible {
outline: 2px solid rgb(2 132 199);
outline-offset: 2px;
}
.oc-overlay-button:focus-visible {
outline-color: rgb(125 211 252);
}
:is(.oc-panel-button, .oc-header-button, .oc-icon-button, .oc-map-button, .oc-choice-button):disabled {
@apply cursor-not-allowed border-slate-200 bg-slate-100 text-slate-400 shadow-none;
transform: none !important;
}
.oc-map-button:disabled {
box-shadow: var(--oc-shadow-xs);
}
:is(.oc-panel-button, .oc-primary-button, .oc-header-button, .oc-icon-button, .oc-map-button, .oc-choice-button):not(:disabled):active {
transform: translate(0, 0);
}
.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--disabled,
.oc-panel-button.n-button.n-button--disabled {
border-color: rgb(226 232 240) !important;
background: rgb(241 245 249) !important;
color: var(--oc-color-text-disabled) !important;
box-shadow: none !important;
opacity: 0.72;
transform: none !important;
}
.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: var(--color-teal-200) !important;
background: white !important;
color: var(--color-teal-700) !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: var(--color-teal-300) !important;
background: var(--color-teal-50) !important;
color: var(--color-teal-800) !important;
}
.oc-primary-button--teal.n-button:not(.n-button--disabled):hover {
box-shadow: var(--oc-shadow-primary-hover) !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: white !important;
--n-color-hover: var(--color-teal-50) !important;
--n-color-pressed: var(--color-teal-100) !important;
--n-border: 1px solid rgb(226 232 240) !important;
--n-border-hover: 1px solid var(--color-teal-200) !important;
--n-border-pressed: 1px solid var(--color-teal-300) !important;
--n-text-color: rgb(71 85 105) !important;
--n-text-color-hover: var(--color-teal-800) !important;
--n-text-color-pressed: var(--color-teal-700) !important;
border-color: rgb(226 232 240) !important;
background: white !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: var(--color-teal-200) !important;
background: var(--color-teal-50) !important;
color: var(--color-teal-800) !important;
box-shadow: var(--oc-shadow-primary) !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: var(--color-teal-50) !important;
--n-color-hover: var(--color-teal-100) !important;
--n-color-pressed: var(--color-teal-200) !important;
--n-border: 1px solid var(--color-teal-200) !important;
--n-border-hover: 1px solid var(--color-teal-300) !important;
--n-border-pressed: 1px solid var(--color-teal-400) !important;
--n-text-color: var(--color-teal-700) !important;
--n-text-color-hover: var(--color-teal-800) !important;
--n-text-color-pressed: var(--color-teal-800) !important;
border-color: var(--color-teal-200) !important;
background: var(--color-teal-50) !important;
color: var(--color-teal-700) !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: var(--color-teal-300) !important;
background: var(--color-teal-100) !important;
color: var(--color-teal-800) !important;
box-shadow: var(--oc-shadow-primary-hover) !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;
}
}