632 lines
15 KiB
CSS
632 lines
15 KiB
CSS
/*
|
|
* Raiju Admin — Unified Component Library
|
|
* All classes prefixed with rj- to avoid collision with frontend site CSS.
|
|
* Requires: raiju-admin-tokens.css
|
|
*/
|
|
|
|
|
|
/* ============================================================
|
|
ADMIN SURFACES
|
|
============================================================ */
|
|
|
|
.rj-admin-panel,
|
|
.rj-admin-group,
|
|
.rj-admin-item {
|
|
color: var(--rj-text);
|
|
border: 1px solid var(--rj-border);
|
|
box-shadow: none;
|
|
}
|
|
|
|
.rj-admin-panel {
|
|
background: var(--rj-surface-panel, var(--rj-bg-elevated));
|
|
border-radius: var(--rj-radius-lg);
|
|
padding: var(--rj-space-5) var(--rj-space-6);
|
|
}
|
|
|
|
.rj-admin-group {
|
|
background: var(--rj-surface-group, color-mix(in srgb, var(--rj-bg-elevated) 88%, var(--rj-bg)));
|
|
border-radius: var(--rj-radius-lg);
|
|
padding: var(--rj-space-4) var(--rj-space-5);
|
|
}
|
|
|
|
.rj-admin-item {
|
|
background: var(--rj-surface-item, var(--rj-bg));
|
|
border-radius: var(--rj-radius-md);
|
|
padding: var(--rj-space-3);
|
|
}
|
|
|
|
.rj-admin-toolbar {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: var(--rj-space-2);
|
|
}
|
|
|
|
.rj-admin-icon-button {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 32px;
|
|
height: 32px;
|
|
padding: 0;
|
|
border: 1px solid var(--rj-border);
|
|
border-radius: var(--rj-radius-md);
|
|
background: var(--rj-bg-elevated);
|
|
color: var(--rj-text-muted);
|
|
cursor: pointer;
|
|
transition: background-color var(--rj-duration-fast) var(--rj-ease),
|
|
border-color var(--rj-duration-fast) var(--rj-ease),
|
|
color var(--rj-duration-fast) var(--rj-ease),
|
|
transform var(--rj-duration-fast) var(--rj-ease);
|
|
}
|
|
|
|
.rj-admin-icon-button:hover,
|
|
.rj-admin-icon-button:focus-visible {
|
|
background: var(--rj-bg-hover);
|
|
border-color: var(--rj-border-strong);
|
|
color: var(--rj-text);
|
|
outline: none;
|
|
}
|
|
|
|
.rj-admin-icon-button:focus-visible {
|
|
box-shadow: 0 0 0 3px var(--rj-focus-ring, var(--rj-primary-muted));
|
|
}
|
|
|
|
.rj-admin-icon-button:active {
|
|
transform: scale(0.98);
|
|
}
|
|
|
|
.rj-admin-icon-button svg {
|
|
width: 16px;
|
|
height: 16px;
|
|
stroke-width: 1.5;
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
BUTTONS
|
|
============================================================ */
|
|
|
|
.rj-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--rj-space-2);
|
|
height: var(--rj-control-h, 2.5rem);
|
|
padding: 0 var(--rj-space-5, 1.25rem);
|
|
border: 1px solid transparent;
|
|
border-radius: var(--editor-btn-radius, var(--rj-radius-md));
|
|
font-family: var(--rj-font-sans);
|
|
font-size: var(--rj-text-md, 0.875rem);
|
|
font-weight: 500;
|
|
line-height: 1.2;
|
|
cursor: pointer;
|
|
transition: background-color var(--rj-duration-fast) var(--rj-ease),
|
|
color var(--rj-duration-fast) var(--rj-ease),
|
|
border-color var(--rj-duration-fast) var(--rj-ease),
|
|
transform var(--rj-duration-fast) var(--rj-ease),
|
|
box-shadow var(--rj-duration-fast) var(--rj-ease);
|
|
text-decoration: none;
|
|
white-space: nowrap;
|
|
user-select: none;
|
|
}
|
|
|
|
.rj-btn:active {
|
|
transform: scale(0.98);
|
|
}
|
|
|
|
.rj-btn:focus-visible {
|
|
outline: 2px solid var(--rj-primary);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
.rj-btn:disabled {
|
|
opacity: 0.5;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* Primary */
|
|
/* Same hover as .btn-primary in admin/style.css: lift, then settle; glow is a sheen
|
|
plus shadow that .rj-flat-buttons removes */
|
|
.rj-btn--primary {
|
|
--rj-hover-from: var(--rj-primary);
|
|
--rj-hover-peak: var(--rj-hover-lift, var(--rj-primary-hover));
|
|
--rj-hover-to: var(--rj-hover-settle, var(--rj-primary-hover));
|
|
background-color: var(--rj-primary);
|
|
background-image: var(--rj-primary-sheen, none);
|
|
color: var(--rj-text-on-primary);
|
|
text-shadow: 0 1px 1px rgba(255,255,255,0.25), 0 -1px 1px rgba(0,0,0,0.15);
|
|
box-shadow: 0 2px 8px color-mix(in srgb, var(--rj-primary) 15%, transparent);
|
|
transition: background-color var(--rj-duration-hover-out, 320ms) ease-out,
|
|
box-shadow var(--rj-duration-hover-out, 320ms) ease-out,
|
|
transform var(--rj-duration-fast) var(--rj-ease);
|
|
}
|
|
|
|
.rj-btn--primary:hover {
|
|
background-color: var(--rj-hover-settle, var(--rj-primary-hover));
|
|
box-shadow: 0 4px 20px color-mix(in srgb, var(--rj-primary) 35%, transparent);
|
|
animation: rj-hover-fill var(--rj-duration-hover-in, 1400ms) linear both;
|
|
transition: box-shadow calc(var(--rj-duration-hover-in, 1400ms) * 0.4) var(--rj-ease),
|
|
transform var(--rj-duration-fast) var(--rj-ease);
|
|
}
|
|
|
|
.rj-btn--primary:active {
|
|
background-color: var(--rj-primary-active);
|
|
animation: none;
|
|
transition-duration: var(--rj-duration-press, 100ms);
|
|
}
|
|
|
|
.rj-flat-buttons .rj-btn--primary,
|
|
.rj-flat-buttons .rj-btn--primary:hover,
|
|
.rj-flat-buttons .rj-btn--primary:active {
|
|
background-image: none;
|
|
box-shadow: none;
|
|
text-shadow: none;
|
|
}
|
|
|
|
.rj-btn:disabled,
|
|
.rj-btn[aria-busy="true"] {
|
|
animation: none;
|
|
pointer-events: none;
|
|
}
|
|
|
|
@keyframes rj-hover-fill {
|
|
0% { background-color: var(--rj-hover-from); }
|
|
36% { background-color: var(--rj-hover-peak); }
|
|
62% { background-color: var(--rj-hover-peak); }
|
|
100% { background-color: var(--rj-hover-to); }
|
|
}
|
|
|
|
/* Secondary */
|
|
.rj-btn--secondary {
|
|
background: var(--rj-bg-sunken);
|
|
color: var(--rj-text);
|
|
border-color: var(--rj-border);
|
|
}
|
|
|
|
.rj-btn--secondary:hover {
|
|
background: var(--rj-bg-hover);
|
|
border-color: var(--rj-border-strong);
|
|
}
|
|
|
|
/* Ghost */
|
|
.rj-btn--ghost {
|
|
background: transparent;
|
|
color: var(--rj-text-secondary);
|
|
}
|
|
|
|
.rj-btn--ghost:hover {
|
|
background: var(--rj-bg-hover);
|
|
color: var(--rj-text);
|
|
}
|
|
|
|
/* Danger */
|
|
.rj-btn--danger {
|
|
background: var(--rj-danger);
|
|
color: #ffffff;
|
|
}
|
|
|
|
.rj-btn--danger:hover {
|
|
background: var(--rj-danger-hover);
|
|
}
|
|
|
|
/* Success */
|
|
.rj-btn--success {
|
|
background: var(--rj-success);
|
|
color: #ffffff;
|
|
}
|
|
|
|
.rj-btn--success:hover {
|
|
background: #15803d;
|
|
}
|
|
|
|
/* Icon-only button */
|
|
.rj-btn--icon {
|
|
width: var(--rj-control-h, 2.5rem);
|
|
height: var(--rj-control-h, 2.5rem);
|
|
padding: 0;
|
|
border-radius: var(--editor-btn-radius, var(--rj-radius-md));
|
|
}
|
|
|
|
/* Sizes */
|
|
.rj-btn--sm {
|
|
height: var(--rj-control-h-sm, 2rem);
|
|
padding: 0 var(--rj-space-3, 0.75rem);
|
|
font-size: var(--rj-text-sm, 0.8125rem);
|
|
}
|
|
|
|
.rj-btn--sm.rj-btn--icon {
|
|
width: var(--rj-control-h-sm, 2rem);
|
|
}
|
|
|
|
.rj-btn--block {
|
|
display: flex;
|
|
width: 100%;
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
FORM FIELDS
|
|
============================================================ */
|
|
|
|
.rj-field {
|
|
margin-bottom: var(--rj-space-5);
|
|
}
|
|
|
|
.rj-field__label {
|
|
display: block;
|
|
margin-bottom: var(--rj-space-2);
|
|
font-family: var(--rj-font-sans);
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
color: var(--rj-text);
|
|
}
|
|
|
|
.rj-field__label--optional {
|
|
font-weight: 400;
|
|
color: var(--rj-text-muted);
|
|
}
|
|
|
|
.rj-field__input,
|
|
.rj-field__textarea,
|
|
.rj-field__select {
|
|
width: 100%;
|
|
padding: 10px 14px;
|
|
border: 1px solid var(--rj-border);
|
|
border-radius: var(--rj-radius-md);
|
|
background: var(--rj-bg-elevated);
|
|
color: var(--rj-text);
|
|
font-family: var(--rj-font-sans);
|
|
font-size: 0.9375rem;
|
|
line-height: 1.5;
|
|
transition: border-color var(--rj-duration-fast) var(--rj-ease),
|
|
box-shadow var(--rj-duration-fast) var(--rj-ease);
|
|
}
|
|
|
|
.rj-field__input::placeholder,
|
|
.rj-field__textarea::placeholder {
|
|
color: var(--rj-text-muted);
|
|
}
|
|
|
|
.rj-field__input:focus,
|
|
.rj-field__textarea:focus,
|
|
.rj-field__select:focus {
|
|
outline: none;
|
|
border-color: var(--rj-primary);
|
|
box-shadow: 0 0 0 3px var(--rj-primary-muted);
|
|
}
|
|
|
|
.rj-field__textarea {
|
|
min-height: 80px;
|
|
resize: vertical;
|
|
}
|
|
|
|
.rj-field__select {
|
|
appearance: none;
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' stroke='%23525252' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
background-repeat: no-repeat;
|
|
background-position: right 12px center;
|
|
padding-right: 40px;
|
|
}
|
|
|
|
.rj-field__hint {
|
|
display: block;
|
|
margin-top: var(--rj-space-1);
|
|
font-family: var(--rj-font-sans);
|
|
font-size: 0.8125rem;
|
|
color: var(--rj-text-muted);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.rj-field__hint code {
|
|
background: var(--rj-bg-sunken);
|
|
padding: 1px 5px;
|
|
border-radius: var(--rj-radius-sm);
|
|
font-family: var(--rj-font-mono);
|
|
font-size: 0.8em;
|
|
}
|
|
|
|
.rj-field__error {
|
|
display: block;
|
|
margin-top: var(--rj-space-1);
|
|
font-family: var(--rj-font-sans);
|
|
font-size: 0.8125rem;
|
|
color: var(--rj-danger);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
CARDS
|
|
============================================================ */
|
|
|
|
.rj-card {
|
|
background: var(--rj-bg-elevated);
|
|
border: 1px solid var(--rj-border);
|
|
border-radius: var(--rj-radius-lg);
|
|
box-shadow: none;
|
|
}
|
|
|
|
.rj-card__header {
|
|
padding: var(--rj-space-5) var(--rj-space-6);
|
|
border-bottom: 1px solid var(--rj-border);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.rj-card__header h2,
|
|
.rj-card__header h3 {
|
|
margin: 0;
|
|
font-family: var(--rj-font-sans);
|
|
font-weight: 600;
|
|
color: var(--rj-text);
|
|
}
|
|
|
|
.rj-card__body {
|
|
padding: var(--rj-space-5) var(--rj-space-6);
|
|
}
|
|
|
|
.rj-card--flat {
|
|
box-shadow: none;
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
TABS (Pill-style)
|
|
============================================================ */
|
|
|
|
.rj-tabs {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--rj-space-1);
|
|
}
|
|
|
|
.rj-tab {
|
|
position: relative;
|
|
padding: 8px 16px;
|
|
border: none;
|
|
border-radius: var(--rj-radius-full);
|
|
background: transparent;
|
|
color: var(--rj-text-secondary);
|
|
font-family: var(--rj-font-sans);
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: background-color var(--rj-duration-fast) var(--rj-ease),
|
|
color var(--rj-duration-fast) var(--rj-ease);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.rj-tab:hover {
|
|
background: var(--rj-bg-hover);
|
|
color: var(--rj-text);
|
|
}
|
|
|
|
.rj-tab:focus-visible {
|
|
outline: 2px solid var(--rj-primary);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
.rj-tab--active {
|
|
background: var(--rj-primary-subtle);
|
|
color: var(--rj-primary);
|
|
}
|
|
|
|
.rj-tab--active:hover {
|
|
background: var(--rj-primary-muted);
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
BADGE
|
|
============================================================ */
|
|
|
|
.rj-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-width: 18px;
|
|
height: 18px;
|
|
padding: 0 5px;
|
|
border-radius: var(--rj-radius-full);
|
|
background: var(--rj-danger);
|
|
color: #ffffff;
|
|
font-family: var(--rj-font-sans);
|
|
font-size: 0.6875rem;
|
|
font-weight: 600;
|
|
line-height: 1;
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
MODALS
|
|
============================================================ */
|
|
|
|
.rj-modal {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
z-index: var(--rj-z-modal);
|
|
display: none;
|
|
}
|
|
|
|
.rj-modal.active {
|
|
display: block;
|
|
}
|
|
|
|
.rj-modal__backdrop {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
animation: rj-fade-in var(--rj-duration-normal) var(--rj-ease);
|
|
}
|
|
|
|
.rj-modal__dialog {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
background: var(--rj-bg-elevated);
|
|
border-radius: var(--rj-radius-lg);
|
|
box-shadow: var(--rj-shadow-xl);
|
|
width: 90%;
|
|
max-width: 550px;
|
|
max-height: 90vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
animation: rj-slide-in var(--rj-duration-normal) var(--rj-ease);
|
|
}
|
|
|
|
.rj-modal--sm .rj-modal__dialog { max-width: 400px; }
|
|
.rj-modal--lg .rj-modal__dialog { max-width: 700px; }
|
|
.rj-modal--xl .rj-modal__dialog { max-width: 900px; }
|
|
|
|
.rj-modal__header {
|
|
padding: var(--rj-space-4) var(--rj-space-5);
|
|
border-bottom: 1px solid var(--rj-border);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.rj-modal__header h3 {
|
|
margin: 0;
|
|
font-family: var(--rj-font-sans);
|
|
font-size: 1.125rem;
|
|
font-weight: 600;
|
|
color: var(--rj-text);
|
|
}
|
|
|
|
.rj-modal__close {
|
|
width: 32px;
|
|
height: 32px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: none;
|
|
border-radius: var(--rj-radius-md);
|
|
background: transparent;
|
|
color: var(--rj-text-muted);
|
|
font-size: 1.25rem;
|
|
cursor: pointer;
|
|
transition: background-color var(--rj-duration-fast) var(--rj-ease),
|
|
color var(--rj-duration-fast) var(--rj-ease);
|
|
}
|
|
|
|
.rj-modal__close:hover {
|
|
background: var(--rj-bg-hover);
|
|
color: var(--rj-text);
|
|
}
|
|
|
|
.rj-modal__body {
|
|
padding: var(--rj-space-5);
|
|
overflow-y: auto;
|
|
flex: 1;
|
|
}
|
|
|
|
.rj-modal__footer {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: var(--rj-space-2);
|
|
padding: var(--rj-space-4) var(--rj-space-5);
|
|
border-top: 1px solid var(--rj-border);
|
|
background: var(--rj-bg-sunken);
|
|
border-radius: 0 0 var(--rj-radius-lg) var(--rj-radius-lg);
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
TOASTS
|
|
============================================================ */
|
|
|
|
.rj-toast {
|
|
position: fixed;
|
|
bottom: var(--rj-space-5);
|
|
right: var(--rj-space-5);
|
|
z-index: var(--rj-z-toast);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--rj-space-3);
|
|
padding: var(--rj-space-3) var(--rj-space-5);
|
|
background: var(--rj-bg-elevated);
|
|
border: 1px solid var(--rj-border);
|
|
border-left: 4px solid var(--rj-primary);
|
|
border-radius: var(--rj-radius-md);
|
|
box-shadow: var(--rj-shadow-lg);
|
|
color: var(--rj-text);
|
|
font-family: var(--rj-font-sans);
|
|
font-size: 0.875rem;
|
|
animation: rj-slide-in-right var(--rj-duration-normal) var(--rj-ease);
|
|
}
|
|
|
|
.rj-toast--success {
|
|
border-left-color: var(--rj-success);
|
|
}
|
|
|
|
.rj-toast--error {
|
|
border-left-color: var(--rj-danger);
|
|
}
|
|
|
|
.rj-toast--info {
|
|
border-left-color: var(--rj-primary);
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
ALERTS / MESSAGES
|
|
============================================================ */
|
|
|
|
.rj-alert {
|
|
padding: var(--rj-space-3) var(--rj-space-4);
|
|
border-radius: var(--rj-radius-md);
|
|
font-family: var(--rj-font-sans);
|
|
font-size: 0.875rem;
|
|
line-height: 1.5;
|
|
margin-bottom: var(--rj-space-5);
|
|
}
|
|
|
|
.rj-alert--error {
|
|
background: var(--rj-danger-subtle);
|
|
color: var(--rj-danger);
|
|
border: 1px solid rgba(220, 38, 38, 0.15);
|
|
}
|
|
|
|
.rj-alert--success {
|
|
background: var(--rj-success-subtle);
|
|
color: var(--rj-success);
|
|
border: 1px solid rgba(22, 163, 74, 0.15);
|
|
}
|
|
|
|
.rj-alert--warning {
|
|
background: var(--rj-warning-subtle);
|
|
color: var(--rj-warning);
|
|
border: 1px solid rgba(217, 119, 6, 0.15);
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
ANIMATIONS
|
|
============================================================ */
|
|
|
|
@keyframes rj-fade-in {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
@keyframes rj-slide-in {
|
|
from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }
|
|
to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
|
}
|
|
|
|
@keyframes rj-slide-in-right {
|
|
from { opacity: 0; transform: translateX(100%); }
|
|
to { opacity: 1; transform: translateX(0); }
|
|
}
|