From 863b040c07283659b40f44812478176de815579a Mon Sep 17 00:00:00 2001 From: Kevin Longe <273747162+kvlonge@users.noreply.github.com> Date: Sat, 7 Nov 2026 07:45:55 +0000 Subject: [PATCH] feat: list SQLQuack and SQLLoad as products SQLLoad joins Transform and SQLQuack joins Check, each with a full product card: icon, a description taken from its own site, and Website and GitHub links. The On the horizon section and its Coming soon badge styles are removed now that it is empty. The tests check both cards' sections, descriptions and links. --- index.html | 36 +++++++++++++++++------------------- styles.css | 16 ---------------- tests/website.spec.mjs | 14 ++++++++------ 3 files changed, 25 insertions(+), 41 deletions(-) diff --git a/index.html b/index.html index ad2fb2e..fe80006 100644 --- a/index.html +++ b/index.html @@ -88,6 +88,17 @@

SQLTide

+
+ +
+

SQLLoad

+

Load data into your warehouse. See how before anything changes.

+ +
+
@@ -122,28 +133,15 @@

Fensu

- - - -
-
-

03 / On the horizon

-

More to come.

-

Exploring what’s next
for data engineers.

-
-
-
+

SQLQuack

- Coming soon -
-
-
- -
-

SQLLoad

- Coming soon +

Run Snowflake SQL locally. Verified results, or a clear no.

+
diff --git a/styles.css b/styles.css index 7291e1b..809bb9a 100644 --- a/styles.css +++ b/styles.css @@ -23,10 +23,6 @@ --background: #ffffff; --panel: #ffffff; --focus: #1768ba; - --gold-ink: #765600; - --gold-bg: #fff3cb; - --pink-ink: #a52138; - --pink-bg: #ffe5e9; --gutter: clamp(20px, 4.35vw, 68px); font-family: Inter, sans-serif; color: var(--ink); @@ -43,10 +39,6 @@ --background: #0d0f12; --panel: #171a1f; --focus: #75b5ff; - --gold-ink: #ffe07a; - --gold-bg: #352b12; - --pink-ink: #ffacba; - --pink-bg: #3e2028; } * { box-sizing: border-box; } @@ -107,11 +99,6 @@ h3 { margin: 0; font-family: "Space Grotesk", sans-serif; font-size: 24.94308px; .fensu { --accent: #ff6b00; } .sqlquack { --accent: #ffe000; } .sqlload { --accent: #ff5268; } -.upcoming .product { min-height: 128px; align-items: center; padding-block: 22px; } -.upcoming .product-icon { margin-top: 0; } -.upcoming-name { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; } -.badge { display: inline-block; padding: 6px 10px; border-radius: 4px; font-size: 12px; line-height: 16px; color: var(--gold-ink); background: var(--gold-bg); white-space: nowrap; } -.sqlload .badge { color: var(--pink-ink); background: var(--pink-bg); } .site-footer { display: flex; justify-content: space-between; gap: 16px; padding: 12px 0 24px; border-top: 1px solid var(--line); font-size: 12px; line-height: 1.5; } .site-footer span:last-child { color: var(--muted); } #tools { scroll-margin-top: 20px; } @@ -139,8 +126,5 @@ h3 { margin: 0; font-family: "Space Grotesk", sans-serif; font-size: 24.94308px; .category > p:last-child { margin-top: 8px; } .product { gap: 20px; padding: 22px 18px 18px; } .product-links a { min-height: 32px; } - .upcoming .product { min-height: 116px; } - .upcoming-name { gap: 8px; } - .badge { padding-inline: 8px; } .site-footer { flex-wrap: wrap; } } diff --git a/tests/website.spec.mjs b/tests/website.spec.mjs index 743ee84..4d30a70 100644 --- a/tests/website.spec.mjs +++ b/tests/website.spec.mjs @@ -43,7 +43,7 @@ test('theme control remains usable when browser storage is blocked', async ({ pa }); test('approved products, sharing assets and responsive navigation work in both themes', async ({ page, request }) => { - const names = ['SQLBuild', 'SQLTide', 'SQLClean', 'Fensu', 'SQLQuack', 'SQLLoad']; + const names = ['SQLBuild', 'SQLTide', 'SQLLoad', 'SQLClean', 'Fensu', 'SQLQuack']; for (const theme of ['light', 'dark']) { await page.emulateMedia({ colorScheme: theme }); await page.goto('/'); @@ -55,7 +55,7 @@ test('approved products, sharing assets and responsive navigation work in both t await expect(wordmark).toHaveCSS(property, value); } await expect(page.getByRole('link', { name: 'SQLStack on GitHub', exact: true })).toHaveAttribute('href', 'https://github.com/sqlstack-io'); - for (const [name, website] of [['SQLBuild', 'https://sqlbuild.com'], ['SQLTide', 'https://sqltide.io/'], ['SQLClean', 'https://sqlclean.io'], ['Fensu', 'https://fensu.io/']]) { + for (const [name, website] of [['SQLBuild', 'https://sqlbuild.com'], ['SQLTide', 'https://sqltide.io/'], ['SQLClean', 'https://sqlclean.io'], ['Fensu', 'https://fensu.io/'], ['SQLLoad', 'https://sqlload.io'], ['SQLQuack', 'https://sqlquack.io']]) { const card = page.getByRole('article', { name, exact: true }); await expect(card.getByRole('link', { name: `${name} website`, exact: true })).toHaveAttribute('href', website); await expect(card.getByRole('link', { name: `${name} on GitHub`, exact: true })).toHaveAttribute('href', `https://github.com/sqlstack-io/${name.toLowerCase()}`); @@ -72,11 +72,13 @@ test('approved products, sharing assets and responsive navigation work in both t await expect(sqlclean.locator('p')).toHaveText('SQL linting and formatting. Lint 10,000 files in under a second.'); await expect(sqlclean.getByRole('link', { name: 'under a second.', exact: true })).toHaveAttribute('href', 'https://sqlclean.io/docs/benchmarks/'); await expect(page.getByText('Published benchmark:', { exact: false })).toHaveCount(0); - for (const name of names.slice(4)) { - const card = page.getByRole('article', { name, exact: true }); - await expect(card.getByText('Coming soon', { exact: true })).toBeVisible(); - await expect(card.getByRole('link')).toHaveCount(0); + for (const [section, products] of [['Build your data.', ['SQLBuild', 'SQLTide', 'SQLLoad']], ['Keep it sound.', ['SQLClean', 'Fensu', 'SQLQuack']]]) { + const row = page.getByRole('region', { name: section, exact: true }); + await expect(row.getByRole('heading', { level: 3 })).toHaveText(products); } + await expect(page.getByRole('article', { name: 'SQLLoad', exact: true }).locator('p')).toHaveText('Load data into your warehouse. See how before anything changes.'); + await expect(page.getByRole('article', { name: 'SQLQuack', exact: true }).locator('p')).toHaveText('Run Snowflake SQL locally. Verified results, or a clear no.'); + await expect(page.getByText(/coming soon|on the horizon/i)).toHaveCount(0); await expect(page.getByRole('article', { name: 'Fensu', exact: true })).not.toContainText(/pre-release|coming soon/i); for (const width of [320, 390, 768, 1536]) { await page.setViewportSize({ width, height: 900 });