Skip to content

Commit 5951d6c

Browse files
authored
Merge pull request #3: transparent favicons and simpler hero
Preserve transparent favicons and remove redundant hero CTA
2 parents 2c33ed7 + 26051e5 commit 5951d6c

9 files changed

Lines changed: 41 additions & 19 deletions

File tree

‎README.md‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ light/dark preference in the browser. Without JavaScript, the page remains usabl
2121
## Checks
2222

2323
Browser tests cover theme selection and persistence, keyboard navigation, responsive layouts,
24-
product statuses, sharing metadata and image dimensions. They require Node.js and Python 3:
24+
product statuses, sharing metadata, image dimensions and favicon transparency. They require Node.js and Python 3:
2525

2626
```sh
2727
npm ci
@@ -35,13 +35,15 @@ publishing or deployment step.
3535

3636
## Sharing assets
3737

38-
`favicon.ico` contains 16px, 32px and 48px icons. PNG favicons and a 180px Apple touch icon use the
39-
original SQLStack mark on white backing for legibility in light and dark browser chrome.
38+
`favicon.ico` contains transparent 16px, 32px and 48px icons. The PNG favicons preserve the same
39+
original SQLStack mark without its former white backing. The existing theme script selects a white
40+
variant for dark browser chrome using the system preference, independently of the page's theme
41+
override. The 180px Apple home-screen icon retains its opaque background.
4042
`assets/og-sqlstack-dark.png` is an opaque 1200 × 630 sharing card using the original SQLStack
4143
wordmark and the site's Inter typography on a near-black background. Its branding and text fit
4244
inside the central 630px square so small thumbnail crops retain the complete message. The previous
43-
`assets/og-sqlstack.png` remains available for cached metadata. These are raster derivatives, not
44-
replacement logos or SVG originals.
45+
`assets/og-sqlstack.png` remains available for cached metadata. These use the original raster artwork,
46+
not replacement logos or SVG originals.
4547

4648
Canonical and Open Graph/Twitter URLs target `https://sqlstack.io/`. Local previews can verify the
4749
metadata and assets, but public social-crawler validation requires a separately authorized deployment.

‎assets/favicon-16.png‎

-214 Bytes
Loading

‎assets/favicon-32.png‎

-498 Bytes
Loading

‎assets/favicon-dark-32.png‎

903 Bytes
Loading

‎favicon.ico‎

-1.86 KB
Binary file not shown.

‎index.html‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@
2222
<meta name="twitter:description" content="Rust-backed SQL and Python tools for data engineers. Compile-time checks, tested behaviour and enforceable architecture.">
2323
<meta name="twitter:image" content="https://sqlstack.io/assets/og-sqlstack-dark.png">
2424
<meta name="twitter:image:alt" content="SQLStack. Your data stack. Engineered to change. Rust-backed SQL and Python tools for data engineers.">
25-
<link rel="icon" href="favicon.ico" type="image/vnd.microsoft.icon" sizes="16x16 32x32 48x48">
26-
<link rel="icon" href="assets/favicon-16.png" type="image/png" sizes="16x16">
27-
<link rel="icon" href="assets/favicon-32.png" type="image/png" sizes="32x32">
25+
<link rel="icon" href="assets/favicon-32.png?v=2" type="image/png" sizes="32x32" data-favicon>
2826
<link rel="apple-touch-icon" href="assets/apple-touch-icon.png" sizes="180x180">
2927
<link rel="preload" href="assets/fonts/inter-latin.woff2" as="font" type="font/woff2" crossorigin>
3028
<link rel="preload" href="assets/fonts/space-grotesk-bold.woff2" as="font" type="font/woff2" crossorigin>
@@ -58,7 +56,6 @@ <h1 id="headline"><span>Your data stack.</span> <span>Engineered to change.</spa
5856
<p class="lede">Rust-backed SQL and Python tools for data engineers.</p>
5957
<p class="principles">Compile-time checks, tested behaviour and enforceable architecture.</p>
6058
<div class="hero-actions">
61-
<a class="button primary" href="#tools">Find a tool <span aria-hidden="true">↓</span></a>
6259
<a class="button" href="https://github.com/sqlstack-io/sqlstack">View on GitHub <span aria-hidden="true">↗</span></a>
6360
</div>
6461
</section>

‎styles.css‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525
--focus: #1768ba;
2626
--button-border: #bdc9da;
2727
--button-hover: #f3f6fa;
28-
--primary: #0866db;
29-
--primary-ink: #ffffff;
30-
--primary-hover: #0755b7;
3128
--gold-ink: #765600;
3229
--gold-bg: #fff3cb;
3330
--pink-ink: #a52138;
@@ -50,9 +47,6 @@
5047
--focus: #75b5ff;
5148
--button-border: #626a76;
5249
--button-hover: #171a1f;
53-
--primary: #3788e8;
54-
--primary-ink: #0d0f12;
55-
--primary-hover: #66a6f0;
5650
--gold-ink: #ffe07a;
5751
--gold-bg: #352b12;
5852
--pink-ink: #ffacba;
@@ -99,8 +93,6 @@ h1 span { display: block; }
9993
.hero-actions { display: flex; justify-content: center; flex-wrap: wrap; gap: 12px; margin-top: 20px; }
10094
.button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 14px 20px; min-height: 48px; border: 1px solid var(--button-border); border-radius: 2px; color: var(--ink); font-size: 14px; line-height: 20px; text-decoration: none; }
10195
.button:hover { background: var(--button-hover); text-decoration: none; }
102-
.button.primary { color: var(--primary-ink); background: var(--primary); border-color: var(--primary); }
103-
.button.primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); }
10496
.tool-row { display: grid; grid-template-columns: 304px minmax(0, 1fr); gap: 24px; border-top: 1px solid var(--line); padding: 18px 0 16px; }
10597
.category { padding-top: 8px; }
10698
.category .eyebrow { margin: 0 0 8px; color: var(--muted); font-size: 14px; line-height: 20px; text-transform: uppercase; }

‎tests/website.spec.mjs‎

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ for (const system of ['light', 'dark']) {
88
const toggle = page.getByRole('button', { name: 'Dark mode', exact: true });
99
await expect(page.locator('html')).toHaveCSS('color-scheme', system);
1010
await expect(toggle).toHaveAttribute('aria-pressed', String(system === 'dark'));
11+
await expect(page.locator('[data-favicon]')).toHaveAttribute('href', `assets/favicon${system === 'dark' ? '-dark' : ''}-32.png?v=2`);
1112

1213
await page.emulateMedia({ colorScheme: other });
1314
await expect(page.locator('html')).toHaveCSS('color-scheme', other);
15+
await expect(page.locator('[data-favicon]')).toHaveAttribute('href', `assets/favicon${other === 'dark' ? '-dark' : ''}-32.png?v=2`);
1416
await page.emulateMedia({ colorScheme: system });
1517
await expect(page.locator('html')).toHaveCSS('color-scheme', system);
1618

@@ -24,6 +26,7 @@ for (const system of ['light', 'dark']) {
2426
await page.emulateMedia({ colorScheme: system });
2527
await expect(page.locator('html')).toHaveCSS('color-scheme', other);
2628
await expect(page.locator('meta[name="theme-color"]')).toHaveAttribute('content', other === 'dark' ? '#0d0f12' : '#ffffff');
29+
await expect(page.locator('[data-favicon]')).toHaveAttribute('href', `assets/favicon${system === 'dark' ? '-dark' : ''}-32.png?v=2`);
2730
});
2831
}
2932

@@ -59,7 +62,11 @@ test('approved products, sharing assets and responsive navigation work in both t
5962
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true);
6063
await expect(page.getByRole('button', { name: 'Dark mode', exact: true })).toBeInViewport();
6164
}
62-
await page.getByRole('link', { name: 'Find a tool', exact: false }).click();
65+
await expect(page.locator('.hero').getByRole('link')).toHaveCount(1);
66+
await expect(page.locator('.hero').getByRole('link')).toHaveAccessibleName('View on GitHub');
67+
await expect(page.locator('.hero').getByRole('link')).toHaveAttribute('href', 'https://github.com/sqlstack-io/sqlstack');
68+
await page.getByRole('link', { name: 'Skip to tools', exact: true }).focus();
69+
await page.keyboard.press('Enter');
6370
await expect(page).toHaveURL(/#tools$/);
6471
await page.keyboard.press('Tab');
6572
await expect(page.getByRole('link', { name: 'SQLBuild website', exact: true })).toBeFocused();
@@ -75,6 +82,7 @@ test('approved products, sharing assets and responsive navigation work in both t
7582
['/assets/og-sqlstack-dark.png', 1200, 630],
7683
['/assets/favicon-16.png', 16, 16],
7784
['/assets/favicon-32.png', 32, 32],
85+
['/assets/favicon-dark-32.png', 32, 32],
7886
['/assets/apple-touch-icon.png', 180, 180],
7987
]) {
8088
const response = await request.get(path);
@@ -90,4 +98,25 @@ test('approved products, sharing assets and responsive navigation work in both t
9098
expect(ico.readUInt16LE(2)).toBe(1);
9199
expect(ico.readUInt16LE(4)).toBe(3);
92100
expect([ico[6], ico[22], ico[38]]).toEqual([16, 32, 48]);
101+
102+
for (const path of ['/assets/favicon-16.png', '/assets/favicon-32.png', '/assets/favicon-dark-32.png', '/favicon.ico']) {
103+
const pixels = await page.evaluate(async (src) => {
104+
const image = new Image();
105+
image.src = src;
106+
await image.decode();
107+
const canvas = document.createElement('canvas');
108+
canvas.width = image.naturalWidth;
109+
canvas.height = image.naturalHeight;
110+
const context = canvas.getContext('2d');
111+
context.drawImage(image, 0, 0);
112+
const data = context.getImageData(0, 0, canvas.width, canvas.height).data;
113+
const corners = [0, canvas.width - 1, canvas.width * (canvas.height - 1), canvas.width * canvas.height - 1];
114+
return {
115+
corners: corners.map((pixel) => data[pixel * 4 + 3]),
116+
opaquePixels: Array.from(data).filter((value, index) => index % 4 === 3 && value === 255).length,
117+
};
118+
}, path);
119+
expect(pixels.corners, path).toEqual([0, 0, 0, 0]);
120+
expect(pixels.opaquePixels, path).toBeGreaterThan(0);
121+
}
93122
});

‎theme.js‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
function apply(theme) {
1414
root.dataset.theme = theme;
1515
document.querySelector('meta[name="theme-color"]').content = theme === 'dark' ? '#0d0f12' : '#ffffff';
16+
// Match browser chrome, even when the page theme is explicitly overridden.
17+
document.querySelector('[data-favicon]').href = system.matches ? 'assets/favicon-dark-32.png?v=2' : 'assets/favicon-32.png?v=2';
1618
const toggle = document.querySelector('[data-theme-toggle]');
1719
if (toggle) {
1820
toggle.setAttribute('aria-pressed', String(theme === 'dark'));
@@ -23,7 +25,7 @@
2325
apply(preference || (system.matches ? 'dark' : 'light'));
2426

2527
system.addEventListener('change', () => {
26-
if (!preference) apply(system.matches ? 'dark' : 'light');
28+
apply(preference || (system.matches ? 'dark' : 'light'));
2729
});
2830

2931
document.addEventListener('DOMContentLoaded', () => {

0 commit comments

Comments
 (0)