feat(ext/popup): polish unlock view with logo lockup + glass card

Restructures the unlock screen so the form sits in a glass card with
a primary 'unlock vault' button. Logo, brand, and tagline are grouped
as a lockup. Open-vault and settings are demoted to secondary buttons.
Body gets the .surface-backdrop wrapper.
This commit is contained in:
adlee-was-taken
2026-05-02 14:21:04 -04:00
parent 308ef2c974
commit 7371eff0bb
4 changed files with 98 additions and 40 deletions

View File

@@ -0,0 +1,45 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { renderUnlock } from '../unlock';
vi.mock('../../../shared/state', () => ({
getState: () => ({ loading: false, error: null }),
setState: vi.fn(),
sendMessage: vi.fn(),
navigate: vi.fn(),
escapeHtml: (s: string) => s,
openVaultTab: vi.fn(),
}));
describe('renderUnlock', () => {
let app: HTMLElement;
beforeEach(() => {
document.body.innerHTML = '<div id="app"></div>';
app = document.getElementById('app')!;
});
it('renders the logo lockup (logo + brand + tagline)', () => {
renderUnlock(app);
expect(app.querySelector('.brand-logo')).toBeTruthy();
expect(app.querySelector('.brand')?.textContent).toBe('Relicario');
expect(app.querySelector('.tagline')?.textContent).toContain('two-factor');
});
it('renders the unlock form inside a .glass card', () => {
renderUnlock(app);
const glass = app.querySelector('.glass');
expect(glass).toBeTruthy();
expect(glass!.querySelector('#passphrase-input')).toBeTruthy();
expect(glass!.querySelector('.btn-primary')).toBeTruthy();
});
it('renders open-vault and settings as secondary buttons outside the card', () => {
renderUnlock(app);
const vaultBtn = app.querySelector('#vault-btn');
const settingsBtn = app.querySelector('#settings-btn');
expect(vaultBtn?.classList.contains('btn-secondary')).toBe(true);
expect(settingsBtn?.classList.contains('btn-secondary')).toBe(true);
// They should NOT be inside the .glass card
const glass = app.querySelector('.glass');
expect(glass!.contains(vaultBtn!)).toBe(false);
});
});