apps/ui: Warp's design system for Vue 3 + Tailwind v4. Tokens, fonts, icons and logo come from the brand package, with a Tailwind theme on the tokens and Vue components on the brand component styles. apps/admin: the admin panel as a separate, optional service. warp-admin embeds the built Vue app and proxies only the login endpoints and /_warp/admin/v1 to the homeserver. Pages: dashboard, users, rooms, federation, registration and tokens, server notices, application services, audit log. Also: pnpm workspace, go.work entry, Dockerfile, an `admin` compose profile, Makefile targets, a CI job with a proxy smoke test, and docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
70 lines
5.9 KiB
CSS
70 lines
5.9 KiB
CSS
/* Components the brand package does not ship yet, drawn with the same
|
|
* tokens and rules: controls bordered in line-strong, radius-sm for
|
|
* controls, radius-md for cards, radius-lg for dialogs, shadow-lg for
|
|
* anything floating, focus-ring on keyboard focus.
|
|
*/
|
|
|
|
@layer components {
|
|
/* Card */
|
|
.wp-card { background: var(--surface-raised); border: 1px solid var(--line); border-radius: var(--radius-md); }
|
|
|
|
/* Textarea and select share the input's look */
|
|
.wp-textarea { font: inherit; font-size: 14px; line-height: 20px; min-height: 96px; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); border: 1px solid var(--line-strong); background: var(--surface-raised); color: var(--ink); resize: vertical; }
|
|
.wp-textarea::placeholder { color: var(--ink-muted); }
|
|
.wp-textarea:focus-visible, .wp-select:focus-visible { outline: 2px solid transparent; border-color: var(--teal-strong); box-shadow: var(--focus-ring); }
|
|
.wp-select { font: inherit; font-size: 14px; height: 40px; padding: 0 var(--space-8) 0 var(--space-3); border-radius: var(--radius-sm); border: 1px solid var(--line-strong); background-color: var(--surface-raised); color: var(--ink); appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--ink-muted) 50%), linear-gradient(135deg, var(--ink-muted) 50%, transparent 50%); background-position: calc(100% - 17px) 50%, calc(100% - 12px) 50%; background-size: 5px 5px; background-repeat: no-repeat; }
|
|
.wp-field-wide { max-width: none; }
|
|
|
|
/* Switch */
|
|
.wp-switch { position: relative; flex: none; width: 40px; height: 24px; padding: 0; border: 1px solid var(--line-strong); border-radius: var(--radius-full); background: var(--line); cursor: pointer; transition: background-color .15s ease, border-color .15s ease; }
|
|
.wp-switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: var(--radius-full); background: var(--surface-raised); box-shadow: var(--shadow-sm); transition: transform .15s ease; }
|
|
.wp-switch[aria-checked="true"] { background: var(--teal-strong); border-color: var(--teal-strong); }
|
|
.wp-switch[aria-checked="true"]::after { transform: translateX(16px); background: var(--on-teal); }
|
|
.wp-switch:disabled { opacity: .45; cursor: not-allowed; }
|
|
.wp-switch:focus-visible { outline: 2px solid transparent; box-shadow: var(--focus-ring); }
|
|
|
|
/* Checkbox */
|
|
.wp-check { display: inline-flex; align-items: center; gap: var(--space-2); cursor: pointer; }
|
|
.wp-check input { width: 18px; height: 18px; margin: 0; accent-color: var(--teal-strong); cursor: pointer; }
|
|
|
|
/* Dialog */
|
|
.wp-dialog { margin: auto; width: calc(100% - 2 * var(--space-4)); max-width: 480px; max-height: calc(100vh - 2 * var(--space-4)); box-sizing: border-box; overflow: auto; padding: var(--space-6); border-radius: var(--radius-lg); background: var(--surface-raised); color: var(--ink); box-shadow: var(--shadow-lg); border: 1px solid var(--line); }
|
|
.wp-dialog[open] { display: flex; flex-direction: column; gap: var(--space-4); }
|
|
.wp-dialog::backdrop { background: #0f121399; }
|
|
.wp-dialog-head { display: flex; align-items: flex-start; gap: var(--space-3); }
|
|
.wp-dialog-title { flex: 1; margin: 0; font-family: var(--font-display); font-size: 20px; line-height: 26px; font-weight: 600; }
|
|
.wp-dialog-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); }
|
|
|
|
/* Table */
|
|
.wp-table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface-raised); }
|
|
.wp-table { width: 100%; border-collapse: collapse; font-size: 14px; line-height: 20px; }
|
|
.wp-table th { text-align: left; font-size: 12px; line-height: 16px; font-weight: 600; letter-spacing: .02em; color: var(--ink-muted); padding: var(--space-2) var(--space-4); background: var(--surface-sunken); border-bottom: 1px solid var(--line); white-space: nowrap; }
|
|
.wp-table td { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--line); vertical-align: middle; }
|
|
.wp-table tr:last-child td { border-bottom: 0; }
|
|
.wp-table tbody tr.wp-row-link { cursor: pointer; }
|
|
.wp-table tbody tr.wp-row-link:hover { background: var(--surface-sunken); }
|
|
.wp-table .wp-num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
|
|
/* Spinner */
|
|
.wp-spinner { display: inline-block; flex: none; border-radius: var(--radius-full); border: 2px solid var(--line); border-top-color: var(--teal); animation: wp-spin .8s linear infinite; }
|
|
@keyframes wp-spin { to { transform: rotate(360deg); } }
|
|
|
|
/* Navigation item, for rails and sidebars */
|
|
.wp-nav { font: inherit; color: var(--ink); text-decoration: none; display: flex; align-items: center; gap: var(--space-3); height: 40px; padding: 0 var(--space-3); border-radius: var(--radius-md); font-weight: 600; }
|
|
.wp-nav > .wp-icon { color: var(--ink-muted); }
|
|
.wp-nav:hover { background: var(--line); }
|
|
.wp-nav-active, .wp-nav-active:hover { background: var(--teal-soft); color: var(--teal-text); }
|
|
.wp-nav-active > .wp-icon { color: var(--teal-text); }
|
|
|
|
/* Segmented control */
|
|
.wp-segmented { display: inline-flex; padding: 2px; gap: 2px; border-radius: var(--radius-sm); border: 1px solid var(--line-strong); background: var(--surface-raised); }
|
|
.wp-segmented button { font: inherit; font-size: 13px; font-weight: 600; height: 30px; padding: 0 var(--space-3); display: inline-flex; align-items: center; gap: var(--space-1); border: 0; border-radius: 6px; background: transparent; color: var(--ink-muted); cursor: pointer; }
|
|
.wp-segmented button[aria-pressed="true"] { background: var(--teal-soft); color: var(--teal-text); }
|
|
.wp-segmented button:focus-visible { outline: 2px solid transparent; box-shadow: var(--focus-ring); }
|
|
|
|
/* Danger text button */
|
|
.wp-btn-danger-solid { background: var(--danger); color: var(--surface); border-color: var(--danger); }
|
|
.wp-btn-danger-solid:hover { filter: brightness(1.06); }
|
|
.wp-btn-danger:hover { filter: brightness(0.98); }
|
|
}
|