From d710d552c7e65e15a1031d0bfe0acabafbbf7040 Mon Sep 17 00:00:00 2001 From: Nicholas Petrasek Date: Thu, 1 Oct 2026 10:07:36 +0200 Subject: [PATCH] feat: add homepage project support links --- test/browser/website.spec.ts | 70 +++++++++++++++++++++++++++++++++++- website/index.html | 21 +++++++++++ website/styles.css | 26 ++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/test/browser/website.spec.ts b/test/browser/website.spec.ts index d043d0e..137d7af 100644 --- a/test/browser/website.spec.ts +++ b/test/browser/website.spec.ts @@ -1,5 +1,64 @@ import { expect, test } from '@playwright/test'; +for (const width of [1280, 390, 320]) { + test(`homepage support links remain usable at ${width}px`, async ({ + page, + browserName, + }) => { + await page.setViewportSize({ width, height: 900 }); + await page.goto(websiteOrigin + '/'); + const support = page.getByRole('region', { + name: 'Useful in your project?', + }); + await expect(support).toBeVisible(); + expect( + await support.evaluate((node) => node.previousElementSibling?.id), + ).toBe('use-cases'); + const star = support.getByRole('link', { + name: 'Star on GitHub', + exact: true, + }); + const explore = support.getByRole('link', { + name: 'Explore NIPE Open Source', + exact: true, + }); + await expect(star).toHaveAttribute( + 'href', + 'https://github.com/NIPE-Solutions/readonly-view', + ); + await expect(explore).toHaveAttribute( + 'href', + 'https://opensource.nipesolutions.com', + ); + for (const link of [star, explore]) { + const bounds = await link.boundingBox(); + expect(bounds!.height).toBeGreaterThanOrEqual(44); + expect(bounds!.width).toBeGreaterThanOrEqual(44); + expect(bounds!.x).toBeGreaterThanOrEqual(0); + expect(bounds!.x + bounds!.width).toBeLessThanOrEqual(width); + expect(await link.evaluate((node) => node.tagName)).toBe('A'); + } + await star.focus(); + // macOS Safari navigates native links with Option+Tab. + const tab = + browserName === 'webkit' && process.platform === 'darwin' + ? 'Alt+Tab' + : 'Tab'; + await page.keyboard.press(tab); + await expect(explore).toBeFocused(); + await page.keyboard.press(`Shift+${tab}`); + await expect(star).toBeFocused(); + expect( + await star.evaluate((node) => getComputedStyle(node).outlineStyle), + ).not.toBe('none'); + if (process.env.CTA_SCREENSHOT_DIR) { + await support.screenshot({ + path: `${process.env.CTA_SCREENSHOT_DIR}/${test.info().project.name}-${width}.png`, + }); + } + }); +} + const websiteOrigin = 'http://127.0.0.1:42873'; test('documentation navigation and live demo work', async ({ page }) => { @@ -86,6 +145,7 @@ test('documentation has no narrow-screen overflow', async ({ page }) => { test('sticky documentation navigation keeps keyboard focus visible in a short viewport', async ({ page, + browserName, }) => { await page.setViewportSize({ width: 800, height: 600 }); await page.emulateMedia({ reducedMotion: 'reduce' }); @@ -98,10 +158,15 @@ test('sticky documentation navigation keeps keyboard focus visible in a short vi const firstLink = links.first(); const lastLink = links.last(); const linkCount = await links.count(); + // macOS Safari navigates native links with Option+Tab. + const tab = + browserName === 'webkit' && process.platform === 'darwin' + ? 'Alt+Tab' + : 'Tab'; await firstLink.focus(); for (let index = 1; index < linkCount; index += 1) { - await page.keyboard.press('Tab'); + await page.keyboard.press(tab); } await expect(lastLink).toBeFocused(); @@ -140,6 +205,9 @@ for (const [route, heading, language] of legalRoutes) { }); await page.setViewportSize({ width, height: 844 }); await page.goto(websiteOrigin + route); + await expect( + page.getByRole('region', { name: 'Useful in your project?' }), + ).toHaveCount(0); await expect( page.getByRole('heading', { level: 1, name: heading }), ).toBeVisible(); diff --git a/website/index.html b/website/index.html index 67bfe0d..feb825e 100644 --- a/website/index.html +++ b/website/index.html @@ -234,6 +234,27 @@

Plugin context

>.

+
+

Useful in your project?

+

+ If ReadonlyView helps you share live data safely, a + GitHub star helps other developers discover it. + Explore more tools from NIPE Open Source for your + next project. +

+ +

Choose the right tool

diff --git a/website/styles.css b/website/styles.css index aec7e3f..af67833 100644 --- a/website/styles.css +++ b/website/styles.css @@ -221,6 +221,32 @@ code { color: var(--blue); border-bottom-color: var(--blue); } +.support-actions { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 12px 20px; + margin-top: 28px; +} +.support-actions a { + display: inline-flex; + align-items: center; + min-height: 44px; + padding: 12px 16px; + border: 1px solid var(--rule); + border-radius: 6px; + font-size: 14px; + font-weight: 650; +} +.support-actions a:first-child { + background: var(--blue); + border-color: var(--blue); + color: white; +} +.support-actions a:hover { + text-decoration: underline; + text-underline-offset: 3px; +} .docs-layout { max-width: 1440px; margin: auto;