From 8dff6a5ad0e11c41f539a7f672c5ccbe40081b57 Mon Sep 17 00:00:00 2001 From: Jeffrey Hales Date: Sun, 1 Nov 2026 14:12:29 -0700 Subject: [PATCH] style(portal): refine resource links, list markers and focus styling Remove forced link underlines and suppress bullets and numbering only on staff lists whose items contain resource buttons. Keep the responsive Management Templates grid while allowing its buttons to use their natural size instead of stretching to fill each cell. Remove the outline around the unlocked content container while preserving programmatic focus and visible keyboard focus on inputs and resource links. Update the presentation regression assertions for these styling choices. Validation: Astro build (128 pages), link audit (zero broken links), and 10 focused service/portal tests pass. --- www/src/components/pages/EmployeePortal.astro | 26 ++++++++++++------- www/src/scripts/employee-portal.ts | 13 ++++++++++ www/tools/service-portal.test.mjs | 8 +++++- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/www/src/components/pages/EmployeePortal.astro b/www/src/components/pages/EmployeePortal.astro index e95f709..8d5ce4c 100644 --- a/www/src/components/pages/EmployeePortal.astro +++ b/www/src/components/pages/EmployeePortal.astro @@ -31,9 +31,10 @@ const serialized = payload ? JSON.stringify(payload).replaceAll('<', '\\u003c') .employee-portal { padding-block: 3rem; overflow-wrap: anywhere; } .employee-portal__access { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; } input { background: #fcf9f5; border: 1px solid #edeef3; border-radius: 4px; font: inherit; padding: .65rem; max-width: 100%; min-width: 0; } - input:focus-visible, .employee-portal__content:focus-visible { outline: 3px solid var(--color-focus, #115bbd); outline-offset: 3px; } + input:focus-visible { outline: 3px solid var(--color-focus, #115bbd); outline-offset: 3px; } + .employee-portal__content:focus { outline: none; } [hidden] { display: none; } - .employee-portal__content :global(a) { color: var(--color-primary); text-decoration: underline; } + .employee-portal__content :global(a) { color: var(--color-primary); } .employee-portal__content :global(a:focus-visible) { outline: 3px solid var(--color-focus, #115bbd); outline-offset: 3px; } .employee-portal__content { line-height: 1.65; } .employee-portal__content :global(:is(h1, h2, h3, h4, h5, h6)) { @@ -63,14 +64,19 @@ const serialized = payload ? JSON.stringify(payload).replaceAll('<', '\\u003c') min-width: 0; } .employee-portal__content :global(ul.portal-template-grid > li p) { margin: 0; } - .employee-portal__content :global(ul.portal-template-grid a.portal-resource-button) { - align-items: center; - box-sizing: border-box; - display: flex; - height: 100%; - min-height: 2.75rem; - overflow-wrap: anywhere; - width: 100%; + + /* Staff resource-button lists do not display bullets or numbers. */ + .employee-portal__content :global(.portal-resource-list) { + list-style: none; + padding-inline-start: 0; + } + + .employee-portal__content :global(.portal-resource-list > li) { + list-style: none; + } + + .employee-portal__content :global(.portal-resource-list > li::marker) { + content: none; } .employee-portal__content :global(:is(section, article) + :is(section, article)) { margin-block-start: 2.5rem; } diff --git a/www/src/scripts/employee-portal.ts b/www/src/scripts/employee-portal.ts index 59d8fb0..3d9832a 100644 --- a/www/src/scripts/employee-portal.ts +++ b/www/src/scripts/employee-portal.ts @@ -76,6 +76,19 @@ function enhanceStaffPortalPresentation(fragment: DocumentFragment): void { } if (!templatesList) templatesList = templatesHeading.closest('section, article')?.querySelector('ul') ?? null; templatesList?.classList.add('portal-template-grid'); + // Remove markers only from staff lists containing resource buttons. + for (const list of fragment.querySelectorAll('ul, ol')) { + const items = [...list.children].filter( + (child) => child.tagName === 'LI' + ); + + if ( + items.length > 0 && + items.every((item) => item.querySelector('a.portal-resource-button')) + ) { + list.classList.add('portal-resource-list'); + } + } } function initialize() { const root = document.querySelector('[data-employee-portal]'); diff --git a/www/tools/service-portal.test.mjs b/www/tools/service-portal.test.mjs index 45c912f..4a67607 100644 --- a/www/tools/service-portal.test.mjs +++ b/www/tools/service-portal.test.mjs @@ -54,7 +54,13 @@ test('staff template presentation follows sanitized headings, not original HubSp assert.match(renderer, /templatesList\?\.classList\.add\('portal-template-grid'\)/); assert.match(css, /grid-template-columns: repeat\(2, minmax\(0, 1fr\)\)/); assert.match(css, /@media \(max-width: 767px\)/); - assert.match(css, /ul\.portal-template-grid a\.portal-resource-button/); + assert.doesNotMatch(css, /ul\.portal-template-grid a\.portal-resource-button/); + assert.match(renderer, /items\.every\(\(item\) => item\.querySelector\('a\.portal-resource-button'\)\)/); + assert.match(renderer, /list\.classList\.add\('portal-resource-list'\)/); + assert.match(css, /\.portal-resource-list > li::marker\)\s*\{\s*content: none;/); + assert.match(css, /\.employee-portal__content:focus\s*\{ outline: none;/); + assert.match(css, /input:focus-visible\s*\{ outline: 3px solid/); + assert.match(css, /:global\(a:focus-visible\)\s*\{ outline: 3px solid/); }); test('global preference validates expiry, corrupted values and clock anomalies', () => {