fix hydration mismatch: sync html data-scheme default to dark and suppress body attribute warnings
This commit is contained in:
parent
e1250120b1
commit
ef9d44f7d3
6 changed files with 15 additions and 10 deletions
|
|
@ -72,7 +72,7 @@ more.
|
||||||
- **Fonts:** the web theme uses the system sans stack; Monocraft (self-hosted in `public/`) is
|
- **Fonts:** the web theme uses the system sans stack; Monocraft (self-hosted in `public/`) is
|
||||||
used by the desktop theme's SMP menu and the in-desktop terminal.
|
used by the desktop theme's SMP menu and the in-desktop terminal.
|
||||||
- **Images:** `next/image`
|
- **Images:** `next/image`
|
||||||
- **Version:** `2.2.7` (see `package.json`)
|
- **Version:** `2.2.8` (see `package.json`)
|
||||||
- **Dependencies:** `npm audit` reports **0 vulnerabilities**. `next` is kept at a patched
|
- **Dependencies:** `npm audit` reports **0 vulnerabilities**. `next` is kept at a patched
|
||||||
release (`>=16.3.6`) for the `next/og` RCE, and `brace-expansion` is force-upgraded via
|
release (`>=16.3.6`) for the `next/og` RCE, and `brace-expansion` is force-upgraded via
|
||||||
`overrides`. `braces` (a transitive ESLint/`fast-glob` dependency) has **no upstream fix**,
|
`overrides`. `braces` (a transitive ESLint/`fast-glob` dependency) has **no upstream fix**,
|
||||||
|
|
|
||||||
11
agents.md
11
agents.md
|
|
@ -34,7 +34,7 @@ When in doubt, prefer updating. A stale README **or** agents.md is treated as a
|
||||||
## Bump the version on EVERY prompt — also do this every time
|
## Bump the version on EVERY prompt — also do this every time
|
||||||
|
|
||||||
Another standing requirement: increment the **patch** version (`x.x.+1`, so
|
Another standing requirement: increment the **patch** version (`x.x.+1`, so
|
||||||
`2.2.6` → `2.2.7` → …) as part of every task, even the small ones. Keep all of
|
`2.2.7` → `2.2.8` → …) as part of every task, even the small ones. Keep all of
|
||||||
these in sync:
|
these in sync:
|
||||||
|
|
||||||
- `package.json` → `"version"`
|
- `package.json` → `"version"`
|
||||||
|
|
@ -56,7 +56,7 @@ frosted-glass **web** site, and an alternate KDE/Plasma **desktop simulation**
|
||||||
utilities in the components (Tailwind is present via PostCSS but the look is
|
utilities in the components (Tailwind is present via PostCSS but the look is
|
||||||
hand-written CSS).
|
hand-written CSS).
|
||||||
- Path alias: `@/*` → `src/*`.
|
- Path alias: `@/*` → `src/*`.
|
||||||
- Version: `2.2.7` (see `package.json`).
|
- Version: `2.2.8` (see `package.json`).
|
||||||
|
|
||||||
### Scripts
|
### Scripts
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -124,6 +124,11 @@ scripts/
|
||||||
`localStorage.scheme` and sets `data-scheme` (`light` | `dark`), defaulting to
|
`localStorage.scheme` and sets `data-scheme` (`light` | `dark`), defaulting to
|
||||||
`dark` (only an explicit stored `light` overrides it). There is no device
|
`dark` (only an explicit stored `light` overrides it). There is no device
|
||||||
sniff anymore.
|
sniff anymore.
|
||||||
|
**Keep `layout.tsx`'s server-rendered `<html>` defaults in sync** (`data-theme="web"`,
|
||||||
|
`data-scheme="dark"`) with this script's defaults, or React 19 logs a hydration
|
||||||
|
attribute mismatch ("A tree hydrated but some attributes… didn't match"). `<html>`
|
||||||
|
and `<body>` both carry `suppressHydrationWarning` (the theme script mutates `<html>`
|
||||||
|
before hydration, and browser extensions mutate `<body>`).
|
||||||
2. `useTheme()` (in `useTheme.ts`) reads `data-theme` via `useSyncExternalStore`
|
2. `useTheme()` (in `useTheme.ts`) reads `data-theme` via `useSyncExternalStore`
|
||||||
and dispatches a `theme-change` event on toggle. `useColorScheme()` does the
|
and dispatches a `theme-change` event on toggle. `useColorScheme()` does the
|
||||||
same for `data-scheme` via a `scheme-change` event.
|
same for `data-scheme` via a `scheme-change` event.
|
||||||
|
|
@ -454,7 +459,7 @@ knows about icon ids, via `APP_BY_ID`.
|
||||||
- There is **no test suite**. Verification is `tsc --noEmit`, `eslint`, and
|
- There is **no test suite**. Verification is `tsc --noEmit`, `eslint`, and
|
||||||
`next build`.
|
`next build`.
|
||||||
- The default shell is the web theme: `curl -s http://localhost:3000/` should
|
- The default shell is the web theme: `curl -s http://localhost:3000/` should
|
||||||
contain `data-theme="web"` / `data-scheme="light"` and the `.web-root` markup.
|
contain `data-theme="web"` / `data-scheme="dark"` and the `.web-root` markup.
|
||||||
Theme + scheme are read pre-paint from `localStorage.theme` / `.scheme`, so a
|
Theme + scheme are read pre-paint from `localStorage.theme` / `.scheme`, so a
|
||||||
quick check is to set those in devtools and reload.
|
quick check is to set those in devtools and reload.
|
||||||
- `next/image` is lazy by default, so a headless full-page screenshot shows the
|
- `next/image` is lazy by default, so a headless full-page screenshot shows the
|
||||||
|
|
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "dvorakmortonxd",
|
"name": "dvorakmortonxd",
|
||||||
"version": "2.2.7",
|
"version": "2.2.8",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "dvorakmortonxd",
|
"name": "dvorakmortonxd",
|
||||||
"version": "2.2.7",
|
"version": "2.2.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "^16.3.8",
|
"next": "^16.3.8",
|
||||||
"react": "^19.3.0",
|
"react": "^19.3.0",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "dvorakmortonxd",
|
"name": "dvorakmortonxd",
|
||||||
"version": "2.2.7",
|
"version": "2.2.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node scripts/dev-server.mjs",
|
"dev": "node scripts/dev-server.mjs",
|
||||||
|
|
|
||||||
|
|
@ -345,7 +345,7 @@ export default function WebLayout() {
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<footer className="web-footer glass">
|
<footer className="web-footer glass">
|
||||||
<span className="web-footer-label">v2.2.7</span>
|
<span className="web-footer-label">v2.2.8</span>
|
||||||
© 2025-2026 Martin Dvořák. All rights reserved (not really I dont care, just
|
© 2025-2026 Martin Dvořák. All rights reserved (not really I dont care, just
|
||||||
follow the GPL3.0 License)
|
follow the GPL3.0 License)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ export default function RootLayout({
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" data-theme="web" data-scheme="light" suppressHydrationWarning>
|
<html lang="en" data-theme="web" data-scheme="dark" suppressHydrationWarning>
|
||||||
<body className="antialiased">
|
<body className="antialiased" suppressHydrationWarning>
|
||||||
<ThemeScript />
|
<ThemeScript />
|
||||||
{children}
|
{children}
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue