From 5efd806e439e87e0084de26b9f9f3012614209dd Mon Sep 17 00:00:00 2001 From: "smx.pusha" <139338836+smxpusha@users.noreply.github.com> Date: Thu, 20 Aug 2026 11:02:44 +0200 Subject: [PATCH] ENH - refine notes header and compose controls --- frontend/src/ui/controls.css | 17 +++++++++++ frontend/src/ui/controls/SkyFab.test.ts | 29 +++++++++++++++++++ frontend/src/ui/controls/SkyFab.vue | 3 +- .../views/apps/NotesApp.menu.contract.test.ts | 23 ++++++++++++--- frontend/src/views/apps/NotesApp.vue | 15 ++++++++-- 5 files changed, 80 insertions(+), 7 deletions(-) diff --git a/frontend/src/ui/controls.css b/frontend/src/ui/controls.css index 26e0b55..af8e65b 100644 --- a/frontend/src/ui/controls.css +++ b/frontend/src/ui/controls.css @@ -2733,6 +2733,9 @@ label.sky-list-item__row { .sky-fab--icon-only { width: var(--sky-touch-target, 44px); + height: var(--sky-touch-target, 44px); + flex: none; + align-self: center; padding: 0; } @@ -2741,6 +2744,16 @@ label.sky-list-item__row { color: var(--sky-text, #000000); } +.sky-glass.sky-fab--glass { + border: 1px solid var(--sky-hairline, rgba(0, 0, 0, 0.2)); + background: var(--sky-glass, rgba(255, 255, 255, 0.75)); + color: var(--sky-text, #000000); + box-shadow: var(--sky-shadow-glass); +} + +.sky-fab--glass .sky-fab__accent-layer, +.sky-fab--glass .sky-fab__dark-accent-layer, +.sky-fab--glass .sky-fab__surface-layer, .sky-fab--neutral .sky-fab__accent-layer, .sky-fab--neutral .sky-fab__dark-accent-layer, .sky-fab--neutral .sky-fab__surface-layer { @@ -2755,6 +2768,10 @@ label.sky-list-item__row { background: var(--sky-glass-solid, rgba(247, 247, 248, 0.96)); } +.sky-glass.sky-fab--glass:active:not(:disabled) { + background: var(--sky-glass, rgba(255, 255, 255, 0.75)); +} + .sky-fab--disabled { cursor: default; opacity: 0.42; diff --git a/frontend/src/ui/controls/SkyFab.test.ts b/frontend/src/ui/controls/SkyFab.test.ts index cc6bf7d..02e47ea 100644 --- a/frontend/src/ui/controls/SkyFab.test.ts +++ b/frontend/src/ui/controls/SkyFab.test.ts @@ -73,4 +73,33 @@ describe('SkyFab', () => { /\.sky-glass\.sky-fab--neutral\s*\{[^}]*background:\s*var\(--sky-glass-solid/s, ) }) + + it('offers a translucent glass variant for adjacent floating controls', async () => { + const html = await renderToString( + createSSRApp({ + render: () => h(SkyFab, { ariaLabel: 'Create', variant: 'glass' }), + }), + ) + + expect(html).toContain('sky-fab--glass') + + const controls = readFileSync( + fileURLToPath(new URL('../controls.css', import.meta.url)), + 'utf8', + ) + expect(controls).toMatch( + /\.sky-glass\.sky-fab--glass\s*\{[^}]*border:\s*1px solid var\(--sky-hairline[^}]*background:\s*var\(--sky-glass[^}]*box-shadow:\s*var\(--sky-shadow-glass\)/s, + ) + }) + + it('keeps icon-only fabs perfectly square inside stretching toolbars', () => { + const controls = readFileSync( + fileURLToPath(new URL('../controls.css', import.meta.url)), + 'utf8', + ) + + expect(controls).toMatch( + /\.sky-fab--icon-only\s*\{[^}]*width:\s*var\(--sky-touch-target, 44px\);[^}]*height:\s*var\(--sky-touch-target, 44px\);[^}]*flex:\s*none;[^}]*align-self:\s*center;/s, + ) + }) }) diff --git a/frontend/src/ui/controls/SkyFab.vue b/frontend/src/ui/controls/SkyFab.vue index 131b901..530cce7 100644 --- a/frontend/src/ui/controls/SkyFab.vue +++ b/frontend/src/ui/controls/SkyFab.vue @@ -14,7 +14,7 @@ const props = withDefaults( text?: string textPosition?: 'after' | 'before' type?: 'button' | 'reset' | 'submit' - variant?: 'neutral' | 'primary' + variant?: 'glass' | 'neutral' | 'primary' }>(), { ariaLabel: '', @@ -72,6 +72,7 @@ function handleClick(event: MouseEvent): void { class="sky-fab" :class="{ 'sky-fab--disabled': disabled, + 'sky-fab--glass': variant === 'glass', 'sky-fab--icon-only': !hasText, 'sky-fab--neutral': variant === 'neutral', 'sky-fab--with-text': hasText, diff --git a/frontend/src/views/apps/NotesApp.menu.contract.test.ts b/frontend/src/views/apps/NotesApp.menu.contract.test.ts index 381d47e..04f62ef 100644 --- a/frontend/src/views/apps/NotesApp.menu.contract.test.ts +++ b/frontend/src/views/apps/NotesApp.menu.contract.test.ts @@ -10,10 +10,11 @@ const menuSource = source.slice( source.indexOf('') + ''.length, ) -const listStart = source.search( - / { it('places the Sky searchbar and create action together at the bottom', () => { @@ -27,7 +28,7 @@ describe('NotesApp list controls', () => { expect(composerSource).toContain(' { }) }) +describe('NotesApp headers', () => { + it('keeps list and editor headers at the shared app height', () => { + expect(source).toContain('class="notes-list-navbar"') + expect(source).toContain( + '.notes-list-navbar.sky-navbar--large.sky-navbar--no-navigation', + ) + expect(source).toContain( + 'padding-top: calc(var(--sky-navbar-safe-area-top) + var(--sky-space-3))', + ) + expect(source).toContain('class="notes-editor-page !pb-0"') + expect(source).not.toContain('notes-editor-page !pt-[44px]') + }) +}) + describe('NotesApp more menu', () => { it('uses the shared Feather-style action sheet', () => { expect(menuSource).toContain( diff --git a/frontend/src/views/apps/NotesApp.vue b/frontend/src/views/apps/NotesApp.vue index 9767ccc..f822edf 100644 --- a/frontend/src/views/apps/NotesApp.vue +++ b/frontend/src/views/apps/NotesApp.vue @@ -206,6 +206,7 @@ function shareNote(): void { :aria-label="phone.t('Apps.notes.name')" >