Improve global.css as scaffolding template (#403)

Update `global.css` in all `basic-server-*` examples (and `integration-server`
for consistency) to better serve as templates for AI coding agents scaffolding
new MCP Apps.

Changes:
- Use CSS custom properties (`--font-sans`, `--color-text-primary`, etc.) with
  sensible fallbacks, enabling host design system integration
- Add `color-scheme: light dark` and `light-dark()` fallbacks for theme support
- Include comprehensive typography: h1-h6, body text, `code`/`pre`/`kbd`, `b`/`strong`
- Move `#server-time` styles from global CSS to component stylesheets (classes
  instead of IDs for better CSS practices)

Updates E2E test selectors in `DYNAMIC_MASKS` to match the new class-based
selectors.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jonathan Hefner 2026-01-29 16:55:24 -06:00 • committed by GitHub
commit 6905aa8edc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 315 additions and 56 deletions

View file

@ -1,18 +1,49 @@
:root {
color-scheme: light dark;
}
* {
box-sizing: border-box;
}
html, body {
font-family: system-ui, -apple-system, sans-serif;
font-size: 1rem;
font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji');
font-size: var(--font-text-md-size, 1rem);
font-weight: var(--font-weight-normal, 400);
line-height: var(--font-text-md-line-height, 1.5);
color: var(--color-text-primary, light-dark(#1f2937, #f3f4f6));
}
code {
h1 {
font-size: var(--font-heading-3xl-size, 2.25rem);
line-height: var(--font-heading-3xl-line-height, 1.1);
}
h2 {
font-size: var(--font-heading-2xl-size, 1.875rem);
line-height: var(--font-heading-2xl-line-height, 1.2);
}
h3 {
font-size: var(--font-heading-xl-size, 1.5rem);
line-height: var(--font-heading-xl-line-height, 1.25);
}
h4 {
font-size: var(--font-heading-lg-size, 1.25rem);
line-height: var(--font-heading-lg-line-height, 1.3);
}
h5 {
font-size: var(--font-heading-md-size, 1rem);
line-height: var(--font-heading-md-line-height, 1.4);
}
h6 {
font-size: var(--font-heading-sm-size, 0.875rem);
line-height: var(--font-heading-sm-line-height, 1.4);
}
code, pre, kbd {
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace);
font-size: 1em;
}
/* Server time fills remaining width for consistent E2E screenshot masking */
#server-time {
flex: 1;
min-width: 0;
b, strong {
font-weight: var(--font-weight-bold, 700);
}

View file

@ -70,3 +70,9 @@
font-style: normal;
}
}
/* Server time fills remaining width for consistent E2E screenshot masking */
.serverTime {
flex: 1;
min-width: 0;
}

View file

@ -144,7 +144,7 @@ function GetTimeAppInner({ app, toolResult, hostContext }: GetTimeAppInnerProps)
<div className={styles.action}>
<p>
<strong>Server Time:</strong> <code id="server-time">{serverTime}</code>
<strong>Server Time:</strong> <code className={styles.serverTime}>{serverTime}</code>
</p>
<button onClick={handleGetTime}>Get Server Time</button>
</div>

View file

@ -1,18 +1,49 @@
:root {
color-scheme: light dark;
}
* {
box-sizing: border-box;
}
html, body {
font-family: system-ui, -apple-system, sans-serif;
font-size: 1rem;
font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji');
font-size: var(--font-text-md-size, 1rem);
font-weight: var(--font-weight-normal, 400);
line-height: var(--font-text-md-line-height, 1.5);
color: var(--color-text-primary, light-dark(#1f2937, #f3f4f6));
}
code {
h1 {
font-size: var(--font-heading-3xl-size, 2.25rem);
line-height: var(--font-heading-3xl-line-height, 1.1);
}
h2 {
font-size: var(--font-heading-2xl-size, 1.875rem);
line-height: var(--font-heading-2xl-line-height, 1.2);
}
h3 {
font-size: var(--font-heading-xl-size, 1.5rem);
line-height: var(--font-heading-xl-line-height, 1.25);
}
h4 {
font-size: var(--font-heading-lg-size, 1.25rem);
line-height: var(--font-heading-lg-line-height, 1.3);
}
h5 {
font-size: var(--font-heading-md-size, 1rem);
line-height: var(--font-heading-md-line-height, 1.4);
}
h6 {
font-size: var(--font-heading-sm-size, 0.875rem);
line-height: var(--font-heading-sm-line-height, 1.4);
}
code, pre, kbd {
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace);
font-size: 1em;
}
/* Server time fills remaining width for consistent E2E screenshot masking */
#server-time {
flex: 1;
min-width: 0;
b, strong {
font-weight: var(--font-weight-bold, 700);
}

View file

@ -70,3 +70,9 @@
font-style: normal;
}
}
/* Server time fills remaining width for consistent E2E screenshot masking */
.serverTime {
flex: 1;
min-width: 0;
}

View file

@ -131,7 +131,7 @@ function GetTimeAppInner({ app, toolResult, hostContext }: GetTimeAppInnerProps)
<div className={styles.action}>
<p>
<strong>Server Time:</strong> <code id="server-time">{serverTime}</code>
<strong>Server Time:</strong> <code className={styles.serverTime}>{serverTime}</code>
</p>
<button onClick={handleGetTime}>Get Server Time</button>
</div>

View file

@ -1,18 +1,49 @@
:root {
color-scheme: light dark;
}
* {
box-sizing: border-box;
}
html, body {
font-family: system-ui, -apple-system, sans-serif;
font-size: 1rem;
font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji');
font-size: var(--font-text-md-size, 1rem);
font-weight: var(--font-weight-normal, 400);
line-height: var(--font-text-md-line-height, 1.5);
color: var(--color-text-primary, light-dark(#1f2937, #f3f4f6));
}
code {
h1 {
font-size: var(--font-heading-3xl-size, 2.25rem);
line-height: var(--font-heading-3xl-line-height, 1.1);
}
h2 {
font-size: var(--font-heading-2xl-size, 1.875rem);
line-height: var(--font-heading-2xl-line-height, 1.2);
}
h3 {
font-size: var(--font-heading-xl-size, 1.5rem);
line-height: var(--font-heading-xl-line-height, 1.25);
}
h4 {
font-size: var(--font-heading-lg-size, 1.25rem);
line-height: var(--font-heading-lg-line-height, 1.3);
}
h5 {
font-size: var(--font-heading-md-size, 1rem);
line-height: var(--font-heading-md-line-height, 1.4);
}
h6 {
font-size: var(--font-heading-sm-size, 0.875rem);
line-height: var(--font-heading-sm-line-height, 1.4);
}
code, pre, kbd {
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace);
font-size: 1em;
}
/* Server time fills remaining width for consistent E2E screenshot masking */
#server-time {
flex: 1;
min-width: 0;
b, strong {
font-weight: var(--font-weight-bold, 700);
}

View file

@ -70,3 +70,9 @@
font-style: normal;
}
}
/* Server time fills remaining width for consistent E2E screenshot masking */
.serverTime {
flex: 1;
min-width: 0;
}

View file

@ -149,7 +149,7 @@ function GetTimeAppInner(props: GetTimeAppInnerProps) {
<div class={styles.action}>
<p>
<strong>Server Time:</strong> <code id="server-time">{serverTime()}</code>
<strong>Server Time:</strong> <code class={styles.serverTime}>{serverTime()}</code>
</p>
<button onClick={handleGetTime}>Get Server Time</button>
</div>

View file

@ -111,7 +111,7 @@ async function handleOpenLink() {
<p class="notice">Watch activity in the DevTools console!</p>
<div class="action">
<p><strong>Server Time:</strong> <code id="server-time">{serverTime}</code></p>
<p><strong>Server Time:</strong> <code class="server-time">{serverTime}</code></p>
<button onclick={handleGetTime}>Get Server Time</button>
</div>
@ -205,7 +205,7 @@ async function handleOpenLink() {
}
/* Server time fills remaining width for consistent E2E screenshot masking */
:global(#server-time) {
.server-time {
flex: 1;
min-width: 0;
}

View file

@ -1,12 +1,49 @@
:root {
color-scheme: light dark;
}
* {
box-sizing: border-box;
}
html, body {
font-family: system-ui, -apple-system, sans-serif;
font-size: 1rem;
font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji');
font-size: var(--font-text-md-size, 1rem);
font-weight: var(--font-weight-normal, 400);
line-height: var(--font-text-md-line-height, 1.5);
color: var(--color-text-primary, light-dark(#1f2937, #f3f4f6));
}
code {
h1 {
font-size: var(--font-heading-3xl-size, 2.25rem);
line-height: var(--font-heading-3xl-line-height, 1.1);
}
h2 {
font-size: var(--font-heading-2xl-size, 1.875rem);
line-height: var(--font-heading-2xl-line-height, 1.2);
}
h3 {
font-size: var(--font-heading-xl-size, 1.5rem);
line-height: var(--font-heading-xl-line-height, 1.25);
}
h4 {
font-size: var(--font-heading-lg-size, 1.25rem);
line-height: var(--font-heading-lg-line-height, 1.3);
}
h5 {
font-size: var(--font-heading-md-size, 1rem);
line-height: var(--font-heading-md-line-height, 1.4);
}
h6 {
font-size: var(--font-heading-sm-size, 0.875rem);
line-height: var(--font-heading-sm-line-height, 1.4);
}
code, pre, kbd {
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace);
font-size: 1em;
}
b, strong {
font-weight: var(--font-weight-bold, 700);
}

View file

@ -1,18 +1,49 @@
:root {
color-scheme: light dark;
}
* {
box-sizing: border-box;
}
html, body {
font-family: system-ui, -apple-system, sans-serif;
font-size: 1rem;
font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji');
font-size: var(--font-text-md-size, 1rem);
font-weight: var(--font-weight-normal, 400);
line-height: var(--font-text-md-line-height, 1.5);
color: var(--color-text-primary, light-dark(#1f2937, #f3f4f6));
}
code {
h1 {
font-size: var(--font-heading-3xl-size, 2.25rem);
line-height: var(--font-heading-3xl-line-height, 1.1);
}
h2 {
font-size: var(--font-heading-2xl-size, 1.875rem);
line-height: var(--font-heading-2xl-line-height, 1.2);
}
h3 {
font-size: var(--font-heading-xl-size, 1.5rem);
line-height: var(--font-heading-xl-line-height, 1.25);
}
h4 {
font-size: var(--font-heading-lg-size, 1.25rem);
line-height: var(--font-heading-lg-line-height, 1.3);
}
h5 {
font-size: var(--font-heading-md-size, 1rem);
line-height: var(--font-heading-md-line-height, 1.4);
}
h6 {
font-size: var(--font-heading-sm-size, 0.875rem);
line-height: var(--font-heading-sm-line-height, 1.4);
}
code, pre, kbd {
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace);
font-size: 1em;
}
/* Server time fills remaining width for consistent E2E screenshot masking */
#server-time {
flex: 1;
min-width: 0;
b, strong {
font-weight: var(--font-weight-bold, 700);
}

View file

@ -70,3 +70,9 @@
font-style: normal;
}
}
/* Server time fills remaining width for consistent E2E screenshot masking */
#server-time {
flex: 1;
min-width: 0;
}

View file

@ -118,7 +118,7 @@ async function handleOpenLink() {
<p class="notice">Watch activity in the DevTools console!</p>
<div class="action">
<p><strong>Server Time:</strong> <code id="server-time">{{ serverTime }}</code></p>
<p><strong>Server Time:</strong> <code class="server-time">{{ serverTime }}</code></p>
<button @click="handleGetTime">Get Server Time</button>
</div>
@ -213,7 +213,7 @@ async function handleOpenLink() {
}
/* Server time fills remaining width for consistent E2E screenshot masking */
:deep(#server-time) {
.server-time {
flex: 1;
min-width: 0;
}

View file

@ -1,12 +1,49 @@
:root {
color-scheme: light dark;
}
* {
box-sizing: border-box;
}
html, body {
font-family: system-ui, -apple-system, sans-serif;
font-size: 1rem;
font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji');
font-size: var(--font-text-md-size, 1rem);
font-weight: var(--font-weight-normal, 400);
line-height: var(--font-text-md-line-height, 1.5);
color: var(--color-text-primary, light-dark(#1f2937, #f3f4f6));
}
code {
h1 {
font-size: var(--font-heading-3xl-size, 2.25rem);
line-height: var(--font-heading-3xl-line-height, 1.1);
}
h2 {
font-size: var(--font-heading-2xl-size, 1.875rem);
line-height: var(--font-heading-2xl-line-height, 1.2);
}
h3 {
font-size: var(--font-heading-xl-size, 1.5rem);
line-height: var(--font-heading-xl-line-height, 1.25);
}
h4 {
font-size: var(--font-heading-lg-size, 1.25rem);
line-height: var(--font-heading-lg-line-height, 1.3);
}
h5 {
font-size: var(--font-heading-md-size, 1rem);
line-height: var(--font-heading-md-line-height, 1.4);
}
h6 {
font-size: var(--font-heading-sm-size, 0.875rem);
line-height: var(--font-heading-sm-line-height, 1.4);
}
code, pre, kbd {
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace);
font-size: 1em;
}
b, strong {
font-weight: var(--font-weight-bold, 700);
}

View file

@ -1,18 +1,49 @@
:root {
color-scheme: light dark;
}
* {
box-sizing: border-box;
}
html, body {
font-family: system-ui, -apple-system, sans-serif;
font-size: 1rem;
font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji');
font-size: var(--font-text-md-size, 1rem);
font-weight: var(--font-weight-normal, 400);
line-height: var(--font-text-md-line-height, 1.5);
color: var(--color-text-primary, light-dark(#1f2937, #f3f4f6));
}
code {
h1 {
font-size: var(--font-heading-3xl-size, 2.25rem);
line-height: var(--font-heading-3xl-line-height, 1.1);
}
h2 {
font-size: var(--font-heading-2xl-size, 1.875rem);
line-height: var(--font-heading-2xl-line-height, 1.2);
}
h3 {
font-size: var(--font-heading-xl-size, 1.5rem);
line-height: var(--font-heading-xl-line-height, 1.25);
}
h4 {
font-size: var(--font-heading-lg-size, 1.25rem);
line-height: var(--font-heading-lg-line-height, 1.3);
}
h5 {
font-size: var(--font-heading-md-size, 1rem);
line-height: var(--font-heading-md-line-height, 1.4);
}
h6 {
font-size: var(--font-heading-sm-size, 0.875rem);
line-height: var(--font-heading-sm-line-height, 1.4);
}
code, pre, kbd {
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace);
font-size: 1em;
}
/* Server time fills remaining width for consistent E2E screenshot masking */
#server-time {
flex: 1;
min-width: 0;
b, strong {
font-weight: var(--font-weight-bold, 700);
}

View file

@ -70,3 +70,9 @@
font-style: normal;
}
}
/* Server time fills remaining width for consistent E2E screenshot masking */
.serverTime {
flex: 1;
min-width: 0;
}

View file

@ -152,7 +152,7 @@ function GetTimeAppInner({
<div className={styles.action}>
<p>
<strong>Server Time:</strong>{" "}
<code id="server-time">{serverTime}</code>
<code className={styles.serverTime}>{serverTime}</code>
</p>
<button onClick={handleGetTime}>Get Server Time</button>
</div>

View file

@ -7,14 +7,14 @@ import { test, expect, type Page, type ConsoleMessage } from "@playwright/test";
//
// Note: map-server uses SLOW_SERVERS timeout instead of masking to wait for tiles
const DYNAMIC_MASKS: Record<string, string[]> = {
integration: ["#server-time"], // Server time display
"basic-preact": ["#server-time"], // Server time display
"basic-react": ["#server-time"], // Server time display
"basic-solid": ["#server-time"], // Server time display
"basic-svelte": ["#server-time"], // Server time display
integration: ['[class*="serverTime"]'], // Server time display [CSS module]
"basic-preact": ['[class*="serverTime"]'], // Server time display [CSS module]
"basic-react": ['[class*="serverTime"]'], // Server time display [CSS module]
"basic-solid": ['[class*="serverTime"]'], // Server time display [CSS module]
"basic-svelte": [".server-time"], // Server time display (component-scoped)
"basic-vanillajs": ["#server-time"], // Server time display
"basic-vue": ["#server-time"], // Server time display
"cohort-heatmap": ['[class*="heatmapWrapper"]'], // Heatmap grid (random data)
"basic-vue": [".server-time"], // Server time display (scoped styles)
"cohort-heatmap": ['[class*="heatmapWrapper"]'], // Heatmap grid (random data) [CSS module]
"customer-segmentation": [".chart-container"], // Scatter plot (random data)
"debug-server": ["#event-log", "#callback-table-body"], // Event log and callback counts (dynamic)
quickstart: ["#server-time"], // Server time display

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Before After
Before After

Some files were not shown because too many files have changed in this diff Show more