Compare commits

...
1 Commits
Author SHA1 Message Date
LeoVasanko 4ebe5ae968 Style overhaul. 2026-02-11 01:18:19 +00:00
17 changed files with 234 additions and 121 deletions
-3
View File
@@ -148,6 +148,3 @@ onUnmounted(() => {
removeAuthIframe()
})
</script>
<style scoped>
</style>
-1
View File
@@ -841,7 +841,6 @@ async function submitDialog() {
<style scoped>
.view-admin { padding-bottom: var(--space-3xl); }
.view-header { display: flex; flex-direction: column; gap: var(--space-sm); }
.admin-section { margin-top: var(--space-xl); }
.admin-section-body { display: flex; flex-direction: column; gap: var(--space-xl); }
.admin-panels { display: flex; flex-direction: column; gap: var(--space-xl); }
+10 -9
View File
@@ -1,14 +1,14 @@
<template>
<div class="app-shell">
<div v-if="status.show" class="global-status" style="display: block;">
<div v-if="status.show" class="global-status show">
<div :class="['status', status.type]">
{{ status.message }}
</div>
</div>
<main class="view-root">
<div class="surface surface--tight" style="max-width: 560px; margin: 0 auto; width: 100%;">
<header class="view-header" style="text-align: center;">
<div class="surface surface--tight reset-container">
<header class="view-header reset-header">
<h1>🔑 Registration</h1>
<p class="view-lede">
{{ subtitleMessage }}
@@ -23,7 +23,7 @@
<section class="section-block" v-else-if="!canRegister">
<div class="section-body center">
<div class="button-row center" style="justify-content: center;">
<div class="button-row button-row--center">
<button class="btn-secondary" @click="goHome">Return to sign-in</button>
</div>
</div>
@@ -203,13 +203,14 @@ onMounted(async () => {
</script>
<style scoped>
.center {
text-align: center;
.reset-container {
max-width: 560px;
margin: 0 auto;
width: 100%;
}
.button-row.center {
display: flex;
justify-content: center;
.reset-header {
text-align: center;
}
.section-body {
-3
View File
@@ -110,8 +110,5 @@ const rpId = computed(() => props.settings?.rp_id || 'the configured domain')
</template>
<style scoped>
.error { color: var(--color-danger-text); }
.small { font-size: 0.9rem; }
.muted { color: var(--color-text-muted); }
.optional { font-weight: normal; color: var(--color-text-muted); font-size: 0.85em; }
</style>
+1 -14
View File
@@ -381,25 +381,15 @@ defineExpose({ focusFirstElement })
.card.surface { padding: var(--space-lg); }
.org-title { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-lg); }
.org-name { font-size: 1.5rem; font-weight: 600; color: var(--color-heading); }
.icon-btn { background: none; border: none; color: var(--color-text-muted); padding: 0.2rem; border-radius: var(--radius-sm); cursor: pointer; transition: background 0.2s ease, color 0.2s ease; }
.icon-btn:hover { color: var(--color-heading); background: var(--color-surface-muted); }
.matrix-wrapper { margin: var(--space-md) 0; padding: var(--space-lg); }
.matrix-scroll { overflow-x: auto; }
.matrix-hint { font-size: 0.8rem; color: var(--color-text-muted); }
.perm-matrix-grid { display: inline-grid; gap: 0.25rem; align-items: stretch; }
.perm-matrix-grid > * { padding: 0.35rem 0.45rem; font-size: 0.75rem; }
.perm-matrix-grid .grid-head { color: var(--color-text-muted); text-transform: uppercase; font-weight: 600; letter-spacing: 0.05em; }
.perm-matrix-grid .perm-head { display: flex; align-items: flex-end; justify-content: flex-start; padding: 0.35rem 0.45rem; font-size: 0.75rem; }
.perm-matrix-grid .role-head { display: flex; align-items: flex-end; justify-content: center; }
.perm-matrix-grid .role-head span { writing-mode: vertical-rl; transform: rotate(180deg); font-size: 0.65rem; }
.perm-matrix-grid .add-role-head { cursor: pointer; }
.perm-name { font-weight: 600; color: var(--color-heading); padding: 0.35rem 0.45rem; font-size: 0.75rem; }
.roles-grid { display: flex; gap: var(--space-lg); margin-top: var(--space-lg); }
.role-column { flex: 1; min-width: 200px; border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-md); }
.role-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-md); }
.role-name { display: flex; align-items: center; gap: var(--space-xs); font-size: 1.1rem; color: var(--color-heading); }
.role-actions { display: flex; gap: var(--space-xs); }
.plus-btn { background: var(--color-accent-soft); color: var(--color-accent); border: none; border-radius: var(--radius-sm); padding: 0.25rem 0.45rem; font-size: 1.1rem; cursor: pointer; }
.plus-btn { background: none; color: var(--color-accent); border: none; border-radius: var(--radius-sm); padding: 0.25rem 0.45rem; font-size: 1.1rem; cursor: pointer; }
.plus-btn:hover { background: rgba(37, 99, 235, 0.18); }
.user-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--space-xs); }
.user-chip { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 0.45rem 0.6rem; display: flex; justify-content: space-between; gap: var(--space-sm); cursor: grab; }
@@ -407,9 +397,6 @@ defineExpose({ focusFirstElement })
.user-chip .meta { font-size: 0.7rem; color: var(--color-text-muted); }
.empty-role { border: 1px dashed var(--color-border-strong); border-radius: var(--radius-md); padding: var(--space-sm); display: flex; flex-direction: column; gap: var(--space-xs); align-items: flex-start; }
.empty-text { margin: 0; }
.delete-icon { color: var(--color-danger); }
.delete-icon:hover { background: var(--color-danger-bg); color: var(--color-danger-text); }
.muted { color: var(--color-text-muted); }
@media (max-width: 720px) {
.roles-grid { flex-direction: column; }
-16
View File
@@ -353,8 +353,6 @@ defineExpose({ focusFirstElement })
<style scoped>
.permissions-section { margin-bottom: var(--space-xl); }
.permissions-section h2 { margin-bottom: var(--space-md); }
.actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); align-items: center; }
.actions button { width: auto; }
.org-table a { text-decoration: none; color: var(--color-link); }
.org-table a:hover { text-decoration: underline; }
.org-table .center { width: 6rem; min-width: 6rem; }
@@ -363,24 +361,10 @@ defineExpose({ focusFirstElement })
.perm-title { font-weight: 600; color: var(--color-heading); }
.perm-id-info { font-size: 0.8rem; color: var(--color-text-muted); display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.perm-domain { color: var(--color-text-muted); font-size: 0.9rem; }
.icon-btn { background: none; border: none; color: var(--color-text-muted); padding: 0.2rem; border-radius: var(--radius-sm); cursor: pointer; transition: background 0.2s ease, color 0.2s ease; }
.icon-btn:hover { color: var(--color-heading); background: var(--color-surface-muted); }
.delete-icon { color: var(--color-danger); }
.delete-icon:hover { background: var(--color-danger-bg); color: var(--color-danger-text); }
.matrix-wrapper { margin: var(--space-md) 0; padding: var(--space-lg); }
.matrix-scroll { overflow-x: auto; }
.matrix-hint { font-size: 0.8rem; color: var(--color-text-muted); }
.perm-matrix-grid { display: inline-grid; gap: 0.25rem; align-items: stretch; }
.perm-matrix-grid > * { padding: 0.35rem 0.45rem; font-size: 0.75rem; }
.perm-matrix-grid .grid-head { color: var(--color-text-muted); text-transform: uppercase; font-weight: 600; letter-spacing: 0.05em; }
.perm-matrix-grid .perm-head { display: flex; align-items: flex-end; justify-content: flex-start; padding: 0.35rem 0.45rem; font-size: 0.75rem; }
.perm-matrix-grid .org-head { display: flex; align-items: flex-end; justify-content: center; }
.perm-matrix-grid .org-head span { writing-mode: vertical-rl; transform: rotate(180deg); font-size: 0.65rem; }
.perm-name { font-weight: 600; color: var(--color-heading); padding: 0.35rem 0.45rem; font-size: 0.75rem; }
.display-text { margin-right: var(--space-xs); }
.edit-display-btn { padding: 0.1rem 0.2rem; font-size: 0.8rem; }
.edit-org-btn { padding: 0.1rem 0.2rem; font-size: 0.8rem; margin-left: var(--space-xs); }
.perm-actions { text-align: center; }
.center { text-align: center; }
.muted { color: var(--color-text-muted); }
</style>
-6
View File
@@ -256,11 +256,5 @@ defineExpose({ focusFirstElement })
<style scoped>
.user-detail { display: flex; flex-direction: column; gap: var(--space-lg); }
.admin-actions { display: flex; gap: 0.5rem; }
.actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); align-items: center; }
.ancillary-actions { margin-top: -0.5rem; }
.icon-btn { background: none; border: none; color: var(--color-text-muted); padding: 0.2rem; border-radius: var(--radius-sm); cursor: pointer; transition: background 0.2s ease, color 0.2s ease; }
.icon-btn:hover { color: var(--color-heading); background: var(--color-surface-muted); }
.error { color: var(--color-danger-text); }
.small { font-size: 0.9rem; }
.muted { color: var(--color-text-muted); }
</style>
+181 -12
View File
@@ -9,8 +9,9 @@
--font-sans: "Inter", "Inter var", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", sans-serif;
--font-mono: "DM Mono", "JetBrains Mono", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", monospace;
--color-canvas: white;
--color-surface: oklch(0.97 0.005 var(--hue));
--color-surface-subtle: oklch(0.94 0.01 var(--hue));
--color-surface: oklch(0.95 0.03 var(--hue));
--color-surface-subtle: oklch(0.9 0.03 var(--hue));
--color-surface-hover: white;
--color-dialog: white;
--color-border: oklch(0.8 0.02 var(--hue));
--color-border-strong: oklch(0.55 0.15 var(--hue));
@@ -31,30 +32,35 @@
--color-info-text: oklch(0.45 0.15 var(--hue));
--color-info-bg: oklch(0.95 0.02 var(--hue));
--color-danger: oklch(0.55 0.22 0.07turn);
--color-primary: oklch(0.55 0.2 var(--hue));
--color-error: oklch(0.45 0.2 0.07turn);
--color-success: oklch(0.4 0.15 0.4turn);
--color-bg: oklch(0.97 0.005 var(--hue));
--color-accent-soft: oklch(0.95 0.08 var(--hue));
--shadow-soft: 0 0 .2rem black;
--radius-none: 0;
--shadow-xl: 0 10px 40px rgba(0, 0, 0, 0.15);
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 10px;
--space-xxs: 0.25rem;
--space-xs: 0.5rem;
--space-sm: 0.75rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--space-xl: 2.25rem;
--space-xxl: 3.5rem;
--space-3xl: 5rem;
--layout-padding: clamp(1.5rem, 3vw + 1rem, 3.25rem);
--transition-base: 160ms ease;
--focus-ring: 0 0 0 2px var(--color-accent);
}
:root.dark {
--color-canvas: oklch(0.15 0.03 var(--hue));
--color-surface: oklch(0.18 0.03 var(--hue));
--color-surface-subtle: oklch(0.22 0.03 var(--hue));
--color-dialog: oklch(0.22 0.03 var(--hue));
--color-border: oklch(0.3 0.03 var(--hue));
--color-border-strong: oklch(0.4 0.04 var(--hue));
--color-canvas: oklch(0.17 0.05 var(--hue));
--color-surface: oklch(0.22 0.05 var(--hue));
--color-surface-subtle: oklch(0.25 0.05 var(--hue));
--color-surface-hover: oklch(0.28 0.05 var(--hue));
--color-dialog: oklch(0.22 0.05 var(--hue));
--color-border: oklch(0.3 0.05 var(--hue));
--color-border-strong: oklch(0.4 0.05 var(--hue));
--color-heading: white;
--color-text: oklch(0.9 0.01 var(--hue));
--color-text-muted: oklch(0.7 0.02 var(--hue));
@@ -72,7 +78,13 @@
--color-info-text: oklch(0.8 0.1 var(--hue));
--color-info-bg: oklch(0.3 0.05 var(--hue));
--color-danger: oklch(0.7 0.18 0.07turn);
--color-primary: oklch(0.7 0.15 var(--hue));
--color-error: oklch(0.8 0.12 0.07turn);
--color-success: oklch(0.75 0.15 0.4turn);
--color-bg: oklch(0.18 0.03 var(--hue));
--color-accent-soft: oklch(0.25 0.08 var(--hue));
--shadow-soft: 0 0 0 black;
--shadow-xl: 0 10px 40px rgba(0, 0, 0, 0.4);
}
*,
@@ -160,6 +172,25 @@ a:focus-visible {
max-width: 540px;
}
.view-root--profile .view-header-wrapper {
width: 100%;
max-width: calc(1200px - 2 * var(--layout-padding));
margin: 0 auto;
position: relative;
}
.view-root--profile .theme-toggle {
position: absolute;
top: 0;
right: 0;
}
.section-block--constrained {
width: 100%;
max-width: calc(1200px - 2 * var(--layout-padding));
margin: 0 auto;
}
.view-header {
display: flex;
flex-direction: column;
@@ -207,6 +238,7 @@ a:focus-visible {
flex-wrap: nowrap;
gap: 0.75rem;
justify-content: flex-start;
width: 100%;
}
.button-row button {
@@ -340,10 +372,118 @@ th {
text-align: left;
}
/* Permission matrix styles */
.matrix-wrapper {
margin: var(--space-md) 0;
padding: var(--space-lg);
}
.matrix-scroll {
overflow-x: auto;
}
.matrix-hint {
font-size: 0.8rem;
color: var(--color-text-muted);
}
.perm-matrix-grid {
display: inline-grid;
gap: 0.25rem;
align-items: stretch;
}
.perm-matrix-grid > * {
padding: 0.35rem 0.45rem;
font-size: 0.75rem;
}
.perm-matrix-grid .grid-head {
color: var(--color-text-muted);
text-transform: uppercase;
font-weight: 600;
letter-spacing: 0.05em;
}
.perm-matrix-grid .perm-head {
display: flex;
align-items: flex-end;
justify-content: flex-start;
padding: 0.35rem 0.45rem;
font-size: 0.75rem;
}
.perm-matrix-grid .rotated-head {
display: flex;
align-items: flex-end;
justify-content: center;
}
.perm-matrix-grid .rotated-head span {
writing-mode: vertical-rl;
transform: rotate(180deg);
font-size: 0.65rem;
}
.perm-name {
font-weight: 600;
color: var(--color-heading);
padding: 0.35rem 0.45rem;
font-size: 0.75rem;
}
.center {
text-align: center;
}
/* Utility classes */
.muted {
color: var(--color-text-muted);
}
.error {
color: var(--color-danger-text);
}
.small {
font-size: 0.9rem;
}
.icon-btn {
background: none;
border: none;
color: var(--color-text-muted);
padding: 0.2rem;
border-radius: var(--radius-sm);
cursor: pointer;
transition: background 0.2s ease, color 0.2s ease;
}
.icon-btn:hover {
color: var(--color-heading);
background: var(--color-surface-subtle);
}
.delete-icon {
color: var(--color-danger);
}
.delete-icon:hover {
background: var(--color-error-bg);
color: var(--color-error-text);
}
.actions {
display: flex;
flex-wrap: wrap;
gap: var(--space-sm);
align-items: center;
}
.button-row--center {
justify-content: center;
}
.badge {
display: inline-flex;
align-items: center;
@@ -369,6 +509,10 @@ th {
display: none;
}
.global-status.show {
display: block;
}
.global-status .status {
display: flex;
align-items: center;
@@ -742,7 +886,7 @@ th {
.slot-machine {
padding: 0.875rem 1rem;
background: var(--color-surface-hover, rgba(0, 0, 0, 0.03));
background: var(--color-surface-hover);
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
@@ -763,3 +907,28 @@ th {
height: 1.8em;
position: relative;
}
/* Spinner utilities */
.spinner {
border: 3px solid var(--color-border);
border-top-color: var(--color-primary);
border-radius: 50%;
animation: spin 1s linear infinite;
}
.spinner--sm {
width: 16px;
height: 16px;
border-width: 2px;
}
.spinner--md {
width: 40px;
height: 40px;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
+1 -10
View File
@@ -1,5 +1,5 @@
<template>
<section class="view-root host-view" data-view="host-profile">
<section class="view-root view-root--wide host-view" data-view="host-profile">
<header class="view-header">
<h1>{{ headingTitle }}</h1>
<p class="view-lede">{{ subheading }}</p>
@@ -125,12 +125,3 @@ const handleButtonRowKeydown = (event) => {
// Down does nothing (no elements below to navigate to)
}
</script>
<style scoped>
.host-view { padding: 3rem 1.5rem 4rem; }
.host-actions { display: flex; flex-direction: column; gap: 0.75rem; }
.host-actions .button-row { gap: 0.75rem; flex-wrap: wrap; }
.host-actions .button-row button { flex: 1 1 0; }
.note { margin: 0; color: var(--color-text-muted); }
.empty-state { margin: 0; color: var(--color-text-muted); }
</style>
+2 -7
View File
@@ -27,17 +27,12 @@ defineProps({
.loading-spinner {
width: 40px;
height: 40px;
border: 4px solid var(--color-border);
border-top: 4px solid var(--color-primary);
border: 3px solid var(--color-border);
border-top-color: var(--color-primary);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-container p {
color: var(--color-text-muted);
margin: 0;
-8
View File
@@ -84,12 +84,4 @@ function handleCancel() {
flex-direction: column;
gap: var(--space-md);
}
.error {
color: var(--color-danger-text);
}
.small {
font-size: 0.9rem;
}
</style>
+9 -5
View File
@@ -1,5 +1,6 @@
<template>
<section class="view-root" data-view="profile">
<section class="view-root view-root--profile" data-view="profile">
<div class="view-header-wrapper">
<div class="theme-toggle">
<ThemeSelector />
</div>
@@ -8,8 +9,9 @@
<Breadcrumbs ref="breadcrumbs" :entries="breadcrumbEntries" @keydown="handleBreadcrumbKeydown" />
<p class="view-lede">Account dashboard for managing credentials and authenticating with other devices.</p>
</header>
</div>
<section class="section-block" ref="userInfoSection">
<section class="section-block section-block--constrained" ref="userInfoSection">
<UserBasicInfo
v-if="authStore.userInfo?.ctx"
ref="userBasicInfo"
@@ -38,7 +40,7 @@
</UserBasicInfo>
</section>
<section class="section-block">
<section :class="['section-block', { 'section-block--constrained': !useWideLayout }]">
<div class="section-header">
<h2>Your Passkeys</h2>
<p class="section-description">Ideally have at least two passkeys in case you lose one. More than one user can be registered on the same device, giving you a choice at login. <a href="https://bitwarden.com/pricing/" target="_blank" rel="noopener noreferrer">Bitwarden</a> can sync one passkey to all your devices. Other secure options include <b>local passkeys</b>, as well as hardware keys such as <a href="https://www.yubico.com" target="_blank" rel="noopener noreferrer">YubiKey</a>. Cloud sync via Google, Microsoft or iCloud is discouraged.</p>
@@ -70,6 +72,7 @@
:terminating-sessions="terminatingSessions"
:hovered-credential-uuid="hoveredCredentialUuid"
:navigation-disabled="hasActiveModal"
:section-class="useWideLayout ? '' : 'section-block--constrained'"
@terminate="terminateSession"
@session-hover="hoveredSession = $event"
@navigate-out="handleSessionNavigateOut"
@@ -88,7 +91,7 @@
</form>
</Modal>
<section class="section-block">
<section :class="['section-block', { 'section-block--constrained': !useWideLayout }]">
<div class="button-row" ref="logoutButtons">
<button
type="button"
@@ -333,6 +336,8 @@ const isAdmin = computed(() => {
return perms.includes('auth:admin') || perms.includes('auth:org:admin')
})
const hasMultipleSessions = computed(() => sessions.value.length > 1)
const credentials = computed(() => authStore.userInfo?.credentials || [])
const useWideLayout = computed(() => sessions.value.length > 4 || credentials.value.length > 4)
const breadcrumbEntries = computed(() => { const entries = [{ label: 'Auth', href: makeUiHref() }]; if (isAdmin.value) entries.push({ label: 'Admin', href: adminUiPath() }); return entries })
const saveName = async () => {
@@ -350,7 +355,6 @@ const saveName = async () => {
</script>
<style scoped>
.view-lede { margin: 0; color: var(--color-text-muted); font-size: 1rem; }
.section-header { display: flex; flex-direction: column; gap: 0.4rem; }
.empty-state { margin: 0; color: var(--color-text-muted); text-align: center; padding: 1rem 0; }
.logout-note { margin: 0.75rem 0 0; color: var(--color-text-muted); font-size: 0.875rem; }
+13 -10
View File
@@ -55,15 +55,14 @@
<p class="device-permit-text">Permit {{ deviceInfo.action === 'register' ? 'registration' : 'login' }} to <strong>{{ deviceInfo.host }}</strong></p>
<p class="device-meta">{{ deviceInfo.user_agent_pretty || '—' }}</p>
<p v-if="error" class="error-message" style="margin-top: 0.5rem;">{{ error }}</p>
<p v-if="error" class="error-message">{{ error }}</p>
<div class="button-row" style="margin-top: 0.75rem; display: flex; gap: 0.5rem;">
<div class="button-row device-actions">
<button
type="button"
class="btn-secondary"
:disabled="loading"
@click="deny"
style="flex: 1;"
>
Deny
</button>
@@ -72,7 +71,6 @@
type="submit"
:disabled="loading"
class="btn-primary"
style="flex: 1;"
>
{{ loading ? 'Authenticating…' : 'Authorize' }}
</button>
@@ -921,10 +919,6 @@ defineExpose({ reset, deny, code, handleInput, loading, error })
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.device-info {
display: flex;
flex-direction: column;
@@ -945,9 +939,18 @@ defineExpose({ reset, deny, code, handleInput, loading, error })
}
.error-message {
margin: 0;
margin: 0.5rem 0 0;
font-size: 0.875rem;
color: var(--color-error, #ef4444);
margin-bottom: 1rem;
}
.device-actions {
margin-top: 0.75rem;
display: flex;
gap: 0.5rem;
}
.device-actions button {
flex: 1;
}
</style>
@@ -8,7 +8,7 @@
<!-- Error state -->
<div v-else-if="error" class="error-section">
<p class="error-message">{{ error }}</p>
<button class="btn-primary" @click="retry" style="margin-top: 0.75rem;">Try Again</button>
<button class="btn-primary" @click="retry">Try Again</button>
</div>
<!-- Connecting phase -->
@@ -293,10 +293,6 @@ defineExpose({ retry, cancel })
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.auth-display {
display: flex;
flex-direction: column;
@@ -499,6 +495,10 @@ defineExpose({ retry, cancel })
color: var(--color-error, #ef4444);
}
.error-section button {
margin-top: 0.75rem;
}
/* Responsive adjustments */
@media (max-width: 640px) {
.auth-content {
+2 -3
View File
@@ -1,6 +1,6 @@
<template>
<div class="app-shell">
<div v-if="status.show" class="global-status" style="display: block;">
<div v-if="status.show" class="global-status show">
<div :class="['status', status.type]">
{{ status.message }}
</div>
@@ -18,7 +18,7 @@
<div class="section-body center">
<!-- Local passkey authentication view -->
<div v-if="authView === 'local'" class="auth-view">
<div class="button-row center" ref="buttonRow">
<div class="button-row button-row--center" ref="buttonRow">
<slot name="actions"
:loading="loading"
:can-authenticate="canAuthenticate"
@@ -284,7 +284,6 @@ defineExpose({
</script>
<style scoped>
.button-row.center { display: flex; justify-content: center; gap: 0.75rem; flex-wrap: wrap; }
.user-line { margin: 0.5rem 0 0; font-weight: 500; color: var(--color-text); }
main.view-root { min-height: 100vh; align-items: center; justify-content: center; padding: 2rem 1rem; }
.surface.surface--tight {
+2 -1
View File
@@ -1,5 +1,5 @@
<template>
<section class="section-block" data-component="session-list-section">
<section :class="['section-block', sectionClass]" data-component="session-list-section">
<div class="section-header">
<h2>Active Sessions</h2>
<p class="section-description">{{ sectionDescription }}</p>
@@ -75,6 +75,7 @@ const props = defineProps({
terminatingSessions: { type: Object, default: () => ({}) },
hoveredCredentialUuid: { type: String, default: null },
navigationDisabled: { type: Boolean, default: false },
sectionClass: { type: String, default: '' },
})
const emit = defineEmits(['terminate', 'sessionHover', 'navigate-out'])
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div v-if="authStore.status.show" class="global-status" style="display: block;">
<div v-if="authStore.status.show" class="global-status show">
<div :class="['status', authStore.status.type]">
{{ authStore.status.message }}
</div>