Skip to main content

changing-demo-ui

Change the Blazor WebAssembly demo site under csharp/PhoneNumbers.Demo — a Razor page, layout, CSS, or its bUnit tests — and verify the result in the browser. Use when editing anything in PhoneNumbers.Demo or PhoneNumbers.Demo.Tests, when asked to run or screenshot the demo, or when a demo test run reports zero tests. Covers the BEM/no-inline-style CSS rules, the SVG-icons-as-components rule (Components/Icons/), WCAG AA accessibility checks, what a demo test should and should not assert, and the preview-verification loop.

インストールへ移動

ソース情報

リポジトリ
twcclegg/libphonenumber-csharp
ソースの最終更新活動
2026年9月17日 03:26
検出された SKILL.md の言語
英語
スター
922
フォーク
157

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
changing-demo-ui
description
Change the Blazor WebAssembly demo site under csharp/PhoneNumbers.Demo — a Razor page, layout, CSS, or its bUnit tests — and verify the result in the browser. Use when editing anything in PhoneNumbers.Demo or PhoneNumbers.Demo.Tests, when asked to run or screenshot the demo, or when a demo test run reports zero tests. Covers the BEM/no-inline-style CSS rules, the SVG-icons-as-components rule (Components/Icons/), WCAG AA accessibility checks, what a demo test should and should not assert, and the preview-verification loop.
# Changing the demo UI The demo is a static Blazor WASM app served from GitHub Pages (`deploy-demo.yml`). Pages live in `Pages/*.razor` (one `@page` route each, self-contained `@code` block, `@inject NavigationManager` for URL state via `UrlState.cs`), the shell in `Layout/MainLayout.razor`, SVG icons as components in `Components/Icons/`, styles in `wwwroot/css/` linked from `wwwroot/index.html`. ``` Demo change: - [ ] 1. Make the change (Razor + CSS rules below) - [ ] 2. Add or update a bUnit test in PhoneNumbers.Demo.Tests (Pages/, Layout/ or Components/) - [ ] 3. dotnet test csharp/PhoneNumbers.Demo.Tests — confirm a non-zero test count - [ ] 4. Run the "demo" preview and verify visually, at desktop and mobile width - [ ] 5. Accessibility pass (contrast, keyboard, labels, reduced motion) ``` ## 1. Styling rules - **No `style="…"` attributes** in `.razor` or `.html`. A one-off variant is a BEM modifier class defined in CSS. The only exception is markup Blazor itself generates. - **BEM everywhere**: `block__element--modifier`. One block per component (`hero`, `card`, `result-grid`); no bare element selectors (`h2`, `p`) in component files; modifiers stack on the base class (`class="badge badge--success"`); no descendant selectors across blocks — if `.foo .bar` is tempting, it is `.foo__bar`; never deeper than block > element > modifier. - **Custom properties** on `:root` in `wwwroot/css/app.css` hold every themable value (`--primary`, `--text`, `--border`, `--radius`, …). Never hard-code a colour or size. - **One CSS file per component** in `wwwroot/css/` (`card.css`, `sidebar.css`, …), added to `index.html`. `app.css` holds only the reset, custom properties, base typography and utilities; `layout.css` the sidebar + main scaffold. Page-only styles may use `Pages/Name.razor.css`. - Layout is sidebar + main; at `max-width: 860px` the sidebar collapses behind a toggle and the grids (`input-row`, `result-grid`, `feature-grid`) go single-column. - Light theme only today. If adding dark mode: light defaults in custom properties, overrides under `[data-theme="dark"]`, contrast verified in both. ### SVG icons are components, never inline markup - **No `<svg>` in a page or layout `.razor` file**, and no SVG strings in `@code` or `AddMarkupContent`. Every glyph is a component in `Components/Icons/` named `<Glyph>Icon.razor` (`SearchIcon`, `GlobeIcon`, `ArrowRightIcon`, …), used as `<SearchIcon />`. `_Imports.razor` already brings the namespace in. The only exceptions are the data-URI in `form.css` (a CSS background, not markup) and anything Blazor itself generates. - Before adding an icon, check the folder: the same glyph reused at a different size or colour is the *same* component — size, stroke and fill come from the enclosing block's CSS (`.sidebar__link-icon svg { … }`, `.empty-state__icon svg { … }`), never from attributes on the `<svg>`. Add a new component only for a new shape. - A new icon is two lines, and inherits the `aria-hidden`/`focusable="false"`/`viewBox` wrapper from `Icon.razor` plus attribute forwarding from `IconBase`: ```razor @inherits IconBase <Icon @attributes="AdditionalAttributes"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></Icon> ``` Keep the 24×24 viewBox (feather-style, stroke-based, `currentColor`), so any icon can sit in any block. If a stateful spot needs different glyphs, switch components (`_theme == "dark" ? @<SunIcon /> : @<MoonIcon />`), don't branch inside one. - Icons are decorative: the accessible name lives on the enclosing `<button>`/`<a>` (`aria-label`) or the adjacent text, never on the SVG. `Components/IconTests.cs` renders every `IconBase` subclass and asserts a single `aria-hidden`, `focusable="false"` `<svg>`, so a new icon is covered automatically. ## 2. Tests: what to assert bUnit, xUnit, classes derive from `BunitContext`. The test tree mirrors the demo: one file per page in `csharp/PhoneNumbers.Demo.Tests/Pages/`, layout tests in `Layout/`, component tests in `Components/`. Test names in snake_case describing behaviour (`shows_valid_badge_for_prepopulated_us_number`). Arrange-Act-Assert; one concept per test. **Do test**: rendered text and results, badges/labels, list contents and order; what happens after input changes, clicks, select changes; every conditional branch the user can see (error message, empty state, valid/invalid); edge inputs (empty, whitespace, unparseable, unknown region, number with no geocoding data); initial state (the default number parses on load). **Don't test**: class names, CSS or layout; internal method calls, state shape, lifecycle hooks or render counts; that Blazor re-renders or routes; libphonenumber correctness — the library has its own suite, the demo tests only that it *uses* the library and displays the result. No snapshots. A test is worth adding when it covers a branch, interaction or regression not already covered; name a regression test after the symptom. ## 3. Run the tests — and check the count ```bash dotnet test csharp/PhoneNumbers.Demo.Tests ``` **Never add `-p:TargetFrameworks=net10.0` here.** The demo projects set `TargetFramework` (singular); overriding the plural property from the command line stops the `xunit.runner.visualstudio` build assets from being applied, the xunit discoverer never reaches the output directory, and `dotnet test` exits 0 having run nothing. Output ending in `No test is available in …` is a failure, not a pass — the same project reports dozens of tests without the switch. ## 4. Verify in the browser Start the dev server and open the URL the SDK prints (add `--urls http://localhost:<port>` to pin one): ```bash dotnet run --project csharp/PhoneNumbers.Demo ``` Then: 1. Reload the page and read the console for errors. 2. Exercise the changed flow — type a number, change the region select, click the button — and read the resulting DOM rather than trusting a glance. 3. Resize to the mobile preset: sidebar toggle appears below 860px, grids collapse. 4. Screenshot the result for the user. The library reference is a project reference, so library changes appear on the next build with no package step. Publishing (`dotnet publish csharp/PhoneNumbers.Demo -c Release`) runs the trimmer; if a library change trips it, that is a library bug (see `changing-public-api`), not a demo one. ## 5. Accessibility (WCAG 2.1 AA — required) - Contrast ≥ 4.5:1 for text, ≥ 3:1 for large text and UI components, in every theme. - Meaning never by colour alone — pair with text or an icon (valid/invalid uses colour *and* badge text). - Semantic HTML: `<nav>`, `<main>`, `<section>`, heading hierarchy, `<button>` for actions, `<a>` for navigation. Every input has a `<label>` or `aria-label`; decorative icons get `aria-hidden="true"`. - Keyboard: everything focusable and operable with Enter/Space, focus always visible (no `outline: none` without a replacement), touch targets ≥ 44×44px. - Non-essential animation inside `@media (prefers-reduced-motion: no-preference)`. - Run an axe or Lighthouse audit before calling a UI change done; check that dynamic results are announced. ## Don'ts - No heavyweight JS interop; no server-side dependencies — it must stay a static site. - No inline `<svg>` in pages or layouts — see *SVG icons are components* above. - Don't hand-edit `resources/`. - Don't construct `PhoneNumberUtil`; use `GetInstance()`. Wrap `Parse` in `try/catch (NumberParseException)` and render the message inline with `.error-message`.
GitHubで見る