Merge feature/fullscreen-ux-phase-2a: smart-input affordances

Phase 2A of the fullscreen UX redesign — 8 form-level smart-input
affordances (URL fill-from-tab + hostname chip, group autocomplete,
password reveal + strength bar, TOTP live preview + QR decode, notes
monospace toggle), shared between popup and fullscreen vault tabs via
the new extension/src/shared/form-affordances/ module set.

CLI parity:
- relicario rate <passphrase> (zxcvbn score / guess estimate)
- relicario completions <SHELL> (bash/zsh/fish via clap_complete)
- --group <TAB> dynamic enumeration via .relicario/groups.cache
  (plaintext leak surface; opt out with RELICARIO_NO_GROUPS_CACHE=1)
- --totp-qr <path> on add login + edit (rqrr decode)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-05-01 22:37:18 -04:00
26 changed files with 5395 additions and 23 deletions

View File

@@ -10,6 +10,7 @@
--bg-page: #0d1117;
--bg-pane: #161b22;
--bg-elevated: #21262d;
--bg-input: #161b22;
--border-subtle: #30363d;
/* Text */
@@ -1362,3 +1363,127 @@ textarea {
.vault-lock-screen__form input {
text-align: center;
}
/* Glyph button used by smart-input affordances. Sits inline with an input. */
.glyph-btn {
min-width: 28px;
height: 28px;
padding: 0 6px;
background: var(--bg-input);
border: 1px solid var(--border-subtle);
border-radius: 3px;
color: var(--text-muted);
font-family: inherit;
font-size: 14px;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
}
.glyph-btn:hover:not(:disabled) {
border-color: var(--accent);
color: var(--accent);
}
.glyph-btn:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
.glyph-btn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.hostname-chip-row {
display: flex;
align-items: center;
gap: 6px;
margin-top: 4px;
font-size: 11px;
color: var(--text-muted);
}
.hostname-chip {
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
border-radius: 3px;
font-size: 10px;
font-weight: 600;
color: #0c1118;
}
.hostname-text {
font-family: ui-monospace, monospace;
}
.strength-bar-row {
margin-top: 6px;
display: flex;
flex-direction: column;
gap: 4px;
}
.strength-bar {
display: flex;
gap: 3px;
height: 4px;
}
.strength-bar > span {
flex: 1;
background: var(--border-subtle);
border-radius: 2px;
}
.strength-bar.s-very-weak > span.lit { background: #c75a4f; }
.strength-bar.s-weak > span.lit { background: #c75a4f; }
.strength-bar.s-fair > span.lit { background: #d49b3a; }
.strength-bar.s-good > span.lit { background: #d49b3a; }
.strength-bar.s-strong > span.lit { background: #6cb37a; }
.strength-label {
font-size: 11px;
color: var(--text-muted);
font-variant-numeric: tabular-nums;
}
.totp-preview {
margin-top: 6px;
padding: 6px 10px;
border: 1px dashed var(--border-subtle);
border-radius: 3px;
display: flex;
justify-content: space-between;
align-items: center;
font-variant-numeric: tabular-nums;
color: var(--text-muted);
}
.totp-code {
font-size: 14px;
font-weight: 600;
letter-spacing: 1px;
color: var(--accent);
}
.totp-countdown {
font-size: 11px;
}
.totp-qr-panel {
margin-top: 6px;
padding: 10px;
border: 1px dashed var(--border-subtle);
border-radius: 3px;
background: var(--bg-input);
}
.totp-qr-panel input[type="file"] {
display: block;
font-family: inherit;
color: var(--text-muted);
}
.totp-qr-error {
margin-top: 6px;
font-size: 11px;
color: var(--danger, #c75a4f);
}
.notes-with-toggle {
display: flex;
align-items: center;
gap: 8px;
}
.f-notes--mono {
font-family: ui-monospace, "JetBrains Mono", "SF Mono", monospace !important;
}