diff --git a/frontend/src/ui/controls.css b/frontend/src/ui/controls.css index af8e65b..53954fd 100644 --- a/frontend/src/ui/controls.css +++ b/frontend/src/ui/controls.css @@ -111,6 +111,18 @@ color: var(--sky-text, #111827); } +.sky-glass.sky-button--glass { + border-color: 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-glass.sky-button--glass:active:not(:disabled) { + background: var(--sky-glass, rgba(255, 255, 255, 0.75)); + filter: brightness(0.94); +} + .sky-button--danger { background: var(--sky-danger, #dc2626); } diff --git a/frontend/src/ui/controls/SkyButton.test.ts b/frontend/src/ui/controls/SkyButton.test.ts index 276bb59..36e0275 100644 --- a/frontend/src/ui/controls/SkyButton.test.ts +++ b/frontend/src/ui/controls/SkyButton.test.ts @@ -28,6 +28,27 @@ describe('SkyButton', () => { expect(html).toContain('Continue') }) + it('renders interactive liquid glass buttons through the shared glass surface', async () => { + const html = await renderToString( + createSSRApp({ + render: () => + h(SkyButton, { glass: true, rounded: true }, () => 'Edit'), + }), + ) + + expect(html).toContain('sky-button--glass') + expect(html).toContain('sky-glass') + expect(html).toContain('sky-glass--interactive') + + const controls = readFileSync( + fileURLToPath(new URL('../controls.css', import.meta.url)), + 'utf8', + ) + expect(controls).toMatch( + /\.sky-glass\.sky-button--glass\s*\{[^}]*background:\s*var\(--sky-glass[^}]*box-shadow:\s*var\(--sky-shadow-glass\)/s, + ) + }) + it('keeps focus and pressed feedback on the contextual accent', () => { const uiDirectory = fileURLToPath(new URL('..', import.meta.url)) const controls = readFileSync(`${uiDirectory}/controls.css`, 'utf8') diff --git a/frontend/src/ui/controls/SkyButton.vue b/frontend/src/ui/controls/SkyButton.vue index fd070f7..58f4eb0 100644 --- a/frontend/src/ui/controls/SkyButton.vue +++ b/frontend/src/ui/controls/SkyButton.vue @@ -1,6 +1,8 @@ + + + diff --git a/frontend/src/views/apps/PhoneApp.contract.test.ts b/frontend/src/views/apps/PhoneApp.contract.test.ts index c5a4332..e169be7 100644 --- a/frontend/src/views/apps/PhoneApp.contract.test.ts +++ b/frontend/src/views/apps/PhoneApp.contract.test.ts @@ -16,7 +16,45 @@ describe('PhoneApp EasyShare contract', () => { it('uses the shared full-width Sky tab bar for phone sections', () => { expect(source).toContain(' { + expect(source).toMatch( + /') + ''.length, + ) + expect(recentsFilter).toContain('class="phone-recents-filter"') + expect(recentsFilter).toContain('navigation') + expect(recentsFilter).toContain('strong') + expect(recentsFilter.match(/ { diff --git a/frontend/src/views/apps/PhoneApp.vue b/frontend/src/views/apps/PhoneApp.vue index d6816b3..e325f04 100644 --- a/frontend/src/views/apps/PhoneApp.vue +++ b/frontend/src/views/apps/PhoneApp.vue @@ -8,6 +8,8 @@ import { SkyList, SkyField, SkyAppPage, + SkySegmented, + SkySegmentedButton, SkySheet, SkyTabBar, SkyTabButton, @@ -764,18 +766,20 @@ onBeforeUnmount(() => { class="phone-in-call-keypad" > - {{ key.digit }} {{ key.letters }} - +