Admin UI: dock the attachment panel right of the dialog (below on narrow screens); related-origin setup moves into it

This commit is contained in:
2026-09-07 18:31:53 +00:00
parent 1718825577
commit 826c5916e0
2 changed files with 33 additions and 18 deletions
+14 -15
View File
@@ -453,8 +453,19 @@ function onRemoveOrigin(i) {
<template>
<Modal v-if="dialog.type" @close="$emit('closeDialog')">
<template #attached>
<div v-if="dialog?.type === 'domain-edit' && hasDiagnostics" class="diag-panel" @click.stop>
<ul class="diag-list">
<div v-if="dialog?.type === 'domain-edit' && (relatedEntries.length || hasDiagnostics)" class="attach-panel" @click.stop>
<template v-if="relatedEntries.length">
<p class="small muted">
Related origins are verified by browsers against
<a :href="wellKnownUrl" target="_blank" rel="noopener noreferrer">{{ wellKnownUrl }}</a>
served automatically when this instance hosts {{ dialog.data.rp_id }}; otherwise publish this document there:
</p>
<div class="wellknown-doc">
<pre>{{ wellKnownJson }}</pre>
<button type="button" class="icon-btn" @click="copyText(wellKnownJson, 'Well-known document')" aria-label="Copy well-known document" title="Copy">📋</button>
</div>
</template>
<ul v-if="hasDiagnostics" class="diag-list">
<li v-if="dialog.data.originValidation.some(v => v === 'invalid')" class="small error">Some entries are invalid check for typos in the hostname; a bare '*' or '**' is not allowed, and wildcards only within the domain.</li>
<li v-if="dialog.data.originValidation.some(v => v === 'unreachable')" class="small">Some sites are unreachable make sure they are routed to this instance.</li>
<li v-else-if="dialog.data.originValidation.some(v => v === 'mismatch')" class="small">Some sites are reachable but do not serve this domain.</li>
@@ -575,18 +586,6 @@ function onRemoveOrigin(i) {
<p class="small muted">
Only the listed sites may sign in with {{ dialog.data.rp_id }} passkeys. Wildcards may be used: <strong>**.{{ dialog.data.rp_id }}</strong> allows the whole domain, <strong>*.{{ dialog.data.rp_id }}</strong> only a single subdomain level.<template v-if="relatedEntries.length"> 🔗 means related host requiring WebAuthn ROR setup.</template><template v-if="dialog.data.auth_host"> 🔑 is the dedicated Paskia host for all account management.</template>
</p>
<template v-if="relatedEntries.length">
<p class="small muted">
Related origins are verified by browsers against
<a :href="wellKnownUrl" target="_blank" rel="noopener noreferrer">{{ wellKnownUrl }}</a>
— served automatically when this instance hosts {{ dialog.data.rp_id }}; otherwise publish this document there:
</p>
<div class="wellknown-doc">
<pre>{{ wellKnownJson }}</pre>
<button type="button" class="icon-btn" @click="copyText(wellKnownJson, 'Well-known document')" aria-label="Copy well-known document" title="Copy">📋</button>
</div>
</template>
</template>
<template v-else-if="dialog.type==='confirm'">
<p>{{ dialog.data.message }}</p>
@@ -630,7 +629,7 @@ function onRemoveOrigin(i) {
.row-menu-popup .delete-menu-icon { filter: saturate(1.4); }
.wellknown-doc { display: flex; align-items: flex-start; gap: var(--space-xs); }
.wellknown-doc pre { flex: 1; margin: 0; padding: var(--space-xs) var(--space-sm); font-size: 0.8rem; background: var(--color-bg-soft, rgba(127,127,127,0.08)); border-radius: 4px; overflow-x: auto; }
.wellknown-doc pre { flex: 1; min-width: 0; margin: 0; padding: var(--space-xs) var(--space-sm); font-size: 0.8rem; background: var(--color-bg-soft, rgba(127,127,127,0.08)); border-radius: 4px; white-space: pre-wrap; overflow-wrap: anywhere; }
.input-error {
border-color: var(--color-error);
+19 -3
View File
@@ -490,9 +490,10 @@ th {
left: 0;
}
/* The diagnostics panel attaches below the dialog, so feedback appearing
or disappearing never shifts the dialog's layout or position */
.diag-panel {
/* Dialog attachment panel (runtime diagnostics, related-origin setup):
docked on the right of the dialog, so appearing or disappearing never
shifts the dialog itself. On narrow screens it hangs below instead. */
.attach-panel {
position: absolute;
top: calc(100% + 0.5rem);
left: 0;
@@ -506,6 +507,21 @@ th {
overflow-y: auto;
}
.attach-panel > * + * {
margin-top: var(--space-md);
}
@media (min-width: 1200px) {
.attach-panel {
top: 0;
left: calc(100% + 0.75rem);
right: auto;
/* Never wider than the space right of the centered 500px dialog */
width: min(340px, calc(50vw - 286px));
max-height: calc(100vh - 3rem);
}
}
.icon-btn {
background: none;
border: none;