atproto pds in zig pds.zat.dev
pds atproto
zds docs ui-direction.md
17 kB
Markdown
at main

Resident UI direction #

Research snapshot: 2026-09-06. The reference study and remaining slices are design proposals, not a completed accessibility audit. See the implementation record below.

Use Rally for legibility and physical feedback, bsky38 for strong row hierarchy, plyr.fm for component discipline, and Doodl for personal visual identity. Use Typeahead/pub-search stats for compact information grouping. Keep ZDS's forest/paper palette and familiar account navigation. These references suggest patterns to adapt; they do not require importing their frameworks or themes.

Project Evidence inspected Worth adapting Limits
Rally Live sign-in page and keyboard entry; rally/src/style.css, src/ui/handle-autocomplete.ts Clear hierarchy, 18px body type, Atkinson Hyperlegible font, generous controls, visible focus, help disclosed beside its field, slight button depression Ruled notebook background and large hard shadows are too visually active for every account section. Font choice alone does not establish accessibility.
plyr.fm Live track list and search overlay; frontend/src/lib/components/BottomSheet.svelte, ConfirmDialog.svelte, SearchModal.svelte; design-token documentation Recognizable item identity, separate primary and secondary information, shared surface/type/spacing tokens, modal lifecycle and short transitions Some secondary text is visually subdued. Search focuses its input on opening; this inspection did not establish correct focus return. Do not copy its custom overlays wholesale.
Doodl Live drawing toolbar; doodl/src/ui/slots.ts, src/style.css, index.html Small explicit slot registry, meaningful fallback labels, bounded artwork, approachable controls Its viewport explicitly disables zoom. ZDS must preserve zoom. ZDS should retain visible action labels alongside unfamiliar drawings, and keep its individual-drawing configuration.
Haunt Live home page; local haunt/src/styles/globals.css A distinctive identity mark, generous breathing room, limited atmospheric color Subdued small text and ambient animation are unsuitable models for account tasks. Local checkout is among the user's projects; the live site credits aly.codes. Useful as an atmosphere reference, not an account-layout reference.
Pensieve Live sign-in page; pensieve/src/public/index.html, style.css One clear next step; explicit empty/blocked/ready states in source; labeled progress and status Signed-in progress was inspected in source, not exercised live. Sparse sign-in UI does not demonstrate how well a dense account page works.

Source paths above are relative to each sibling repository under ~/tangled.org/zzstoatzz.io/. The additional references below were reviewed following the initial shortlist.

Rally's concrete details are especially useful: style.css:91 defines a 4px focus outline, :281 begins its large button treatment, and :293 supplies pressed feedback. Its skip link was the first keyboard stop in the live page. Plyr's native confirmation dialog uses showModal(); its bottom sheet contains explicit focus handling and a reduced-motion override. These are implementation references to review independently, not proof of conformance.

Additional references: bsky38 and the stats pages #

  • The race to 38: local checkout is ~/tangled.org/zzstoatzz.io/race38; its live source link names tangled.org/waow.tech/bsky38. This is Nate's companion viewer, distinct from the upstream voting site at bsky38.com, which the initial review mistakenly substituted. The correct live UI combines paper/ink surfaces, crisp framing, blue actions, serif headings, and readable sans-serif controls. The chart and replay controls occupy the primary space; race details and selection editing use disclosure. Portraits connect visual identity to the data. Source reviewed: race38/web/style.css, docs/design-origin.md, and docs/ui-rigor.md. The strongest transferable ideas are stable DOM identity, explicit interaction contracts, bounded visual emphasis, native controls, and feedback tied to accepted events. CSS includes 44px control targets, focus styling, pressed-state selectors, and reduced-motion overrides. These are implementation evidence, not a completed accessibility audit. For ZDS, borrow the clear surface separation, intentional artwork placement, and continuity through updates. Account actions need prompt, accurate confirmation; do not copy the race's delayed animated count arrival into security feedback.
  • Typeahead stats: summary metrics are grouped near their relevant chart, range controls sit beside the content they affect, and the traffic chart is supplemented by named totals and a table. Selecting 24h updated the search count, latency, and chart granularity in place. Source: typeahead/src/pages/stats.ts and theme.ts. Particularly useful: number/unit pairs wrap together, and home/docs/stats share theme tokens. For ZDS, keep summaries short and technical detail close to the task. Do not copy the very small captions. The inspected 24h control was 34px high and exposed its selection through a CSS class without aria-pressed; preserve explicit programmatic selection state when adapting this interaction.
  • pub-search stats and search: the stats page achieves density with aligned rows, whitespace, a compact metric strip, and section-local controls instead of boxing every fact. The search page makes its primary task immediate. Source: pub-search/site/stats.html, dashboard.css, and components.css. ZDS can use this economy for metadata inside expanded app details. The stats CSS has 9–12px labels and very subdued text/border tokens; these need stronger treatment for a friendly account UI. Chart inspection was visual, not a full keyboard or screen-reader test.

This strengthens the recommendation for fewer, better-structured rows rather than a separate decorative card for every piece of metadata. Doodl artwork can occupy the row's identity position while names, state, and controls remain clear.

Anti-slop review #

Adopt an explicit design critique before implementation and again on rendered output: every visual choice should support this account task, hierarchy should survive without decoration, and repeated panels/chips/animations should earn their space. Evaluate real content, awkward lengths, failure states, and generic as well as custom artwork. Accessibility and predictable behavior take priority over stylistic prohibitions or novelty.

The exact named anti-slop skill is pending identification. No matching installed skill was found in the local skill locations searched, and web discovery found several unrelated implementations. Do not claim one is installed or applied until its source and linked guidance have been reviewed. The recommendation is to use it as a critique discipline alongside the existing frontend-design skill, not to introduce another runtime design system or replace the accessibility acceptance baseline.

What ZDS should feel like #

A quiet, well-made account utility with personal illustrations. Clear headings and readable content carry the page; artwork helps people recognize places. Surfaces should have visibly different roles: page background, section surface, editable field, and active control. Borders and spacing should remain useful without shadows or color perception.

Use a small type scale: comfortable body and field text, stronger section headings, and secondary copy that remains readable. Keep monospace for protocol identifiers. Try Atkinson Hyperlegible as a comparison against the system sans before accepting an additional font asset; its name is not a substitute for testing. Avoid making every sentence the same weight or every section a stack of nested boxes.

“Silky” should first mean continuity: stable layout while artwork loads, retained form input after errors, immediate pending feedback, no duplicate submissions, and predictable focus when changing views. Add restrained press/surface feedback after that. A proposed motion budget is 120–180ms for small feedback and at most 200ms for an overlay, with no ornamental looping motion in account views. Under reduced motion, remove spatial movement and keep clear static state changes.

Slottable presentation contract #

Keep the registry and rendering under src/internal/web. Each slot describes a visual purpose and fallback; it does not carry authentication, authorization, navigation, or storage behavior.

  • ZDS owns the semantic element, visible label, accessible name, keyboard behavior, focus ring, state indicator, and target dimensions.
  • Artwork occupies a reserved box with object-fit: contain. A large drawing does not enlarge or shift the form; a small drawing does not shrink the target.
  • Decorative images use empty alt text. If future artwork conveys content, explicitly define a separate content slot with an appropriate text equivalent.
  • An operator can select individual drawings. No iconset membership is required. Unconfigured deployments retain generic defaults.
  • Missing, broken, unusually proportioned, mostly white, mostly black, and transparent artwork must all leave the interface usable. Do not use a blanket white tile to rescue every asset. Preserve the fallback until a replacement loads, and evaluate artwork against both themes.
  • New slots can cover section illustrations, empty-state artwork, or header marks. Introduce them where they aid recognition; do not make arbitrary HTML, CSS, scripts, or control geometry remotely replaceable.
  • Keep the current explicit build-time artwork bundling. No remote resolution on startup or on account requests, and no drawing dependency in auth/storage.

Accessibility acceptance baseline #

Target WCAG 2.2 AA across complete resident flows, with a few deliberate comfort targets beyond the minimum. The W3C's WCAG 2.2 overview specifically covers unobscured focus, target spacing, accessible authentication, and alternatives to dragging. Its AA target-size minimum is 24 CSS pixels with exceptions; use at least 44px targets for ZDS standalone controls as a stronger product target. Focus Appearance is AAA, not an AA requirement; nevertheless use a conspicuous, contrasting focus indicator.

Use the full WCAG 2.2 standard as the audit basis:

  • Keyboard-only completion, logical focus order, a skip link, current-page indication, meaningful headings, and focus that is not hidden by sticky UI.
  • Text contrast of at least 4.5:1 for normal text and 3:1 for qualifying large text; sufficient non-text contrast for required control/state information. Never communicate active, revoked, error, or danger by color alone.
  • Text resize to 200%, reflow at 320 CSS pixels, browser zoom, and text-spacing overrides without losing information or controls. Long DIDs/scopes must wrap.
  • Labels and instructions connected to inputs; specific errors near the field; preserve entered values and explain recovery. Allow password managers and paste. Avoid repeated entry when the value is already available.
  • Announce concise results and pending state, not an entire refreshed account page. Keep critical feedback present long enough to find and act on.
  • Test light/dark, forced colors, reduced motion, keyboard, touch, and a screen reader. Automated checks supplement manual flow tests; they do not certify it.

For confirmations, prefer native dialog semantics and follow the WAI modal-dialog interaction guidance: intentional initial focus, contained keyboard navigation, an accessible name, and sensible focus restoration. Use dialogs only when the decision warrants an interruption; ordinary help and technical details fit native disclosure better.

Successive implementation slices #

  1. Shared foundation. Consolidate presentation tokens and control states inside the web layer. Improve section hierarchy, target sizing, readable secondary text, and focus styling across existing pages. Compare a real account fixture with generic and instance artwork in both themes.
  2. Navigation and feedback. Give view changes appropriate page titles and focus behavior. Narrow live announcements. Add local pending/error/success handling without losing input or rebuilding focused controls unnecessarily. Current account.html marks the whole resident section live, and showView changes classes/current navigation without updating focus or title.
  3. Account actions. Polish field groups and credential rows. Replace ad hoc prompts/confirmations only where a well-tested inline form or native dialog improves the task. Test cancellation, failures, retries, and duplicate clicks.
  4. Additional artwork slots. Add a few useful section/empty-state slots after the surrounding layout and semantic contract are stable. Expand fixtures for asset failure and unusual drawings before broadening configurability.

Keep each runtime slice separately reviewable and deployable. Use browser request/response evidence for reported failures, existing required tests/smokes, and a small consistent manual flow matrix. Before/after startup benchmarks and asset-size checks should show whether presentation work adds cost; deploy once per verified slice, avoiding restarts for research documents alone. This review does not add account-management surfaces or alter the planned lifetime work.

The original research changed no runtime files or sibling projects. Live inspection covered public desktop surfaces and limited keyboard interactions, not a full mobile or assistive-technology audit.

Implementation: first resident UI slice (2026-09-07) #

The first release implements distinct account-section surfaces, a consolidated identity summary, a larger type hierarchy, 44px controls, 48px fields, and mobile navigation that wraps into two columns. Existing drawing slots retain their labels and reserved sizes. Layout and palette changes stay in the web assets; there are no additional fonts, packages, remote requests, or account surfaces.

View navigation now updates the document title and focuses its heading. Modified link clicks retain browser behavior. The whole resident region is no longer a live announcement; the existing status element is an atomic polite status region. Hover/press feedback respects pointer and motion preferences. Session lifetimes and endpoint behavior are unchanged. Remaining action feedback/dialog work is still a subsequent slice.

Validation: existing test suite, endpoint smoke, permissioned smoke, diff check, and Zig Zen completed successfully. Browser checks covered sign-in, reload persistence, active navigation/focus, custom artwork, desktop, 390px and 320px reflow, and the light palette through a local preview proxy. This is not a full assistive-technology audit. Startup probe: five warm-cache samples per scenario, ReleaseSafe, 10,000 history entries. Before/after median readiness was 16.19/20.96ms fresh, 9.02/8.79ms restart, and 9.68/9.57ms with history. Fresh database creation varied; restart results show no observed regression. These exclude VM boot and proxy routing.

Implementation: homepage continuity (2026-09-07) #

Account now sits inside the homepage navigation with the same glass control material and icon scale. Resident pages carry the homepage's ambient light, monospace headings, inset highlights, and layered surfaces into the existing account views. Identity metrics take a compact desktop row; empty states use quiet rules instead of additional boxes. Fields retain opaque, readable interiors.

The replaceable account-appearance.css and account-appearance.js assets are embedded at compile time. They share the homepage's saved theme and decorative accent hue without adding account preferences, remote requests, fonts, animation, or startup I/O. Authentication and protocol modules are unchanged.

Validation: test suite, endpoint smoke, permissioned smoke, JavaScript syntax, diff check, and Zig Zen passed. In-app browser inspection covered homepage, account management, app access, dark/light themes, cross-tab theme changes, and signed-in reload persistence. The browser's viewport override did not actually change its 1280px layout width in this run, so new mobile visual verification remains incomplete; responsive rules were reviewed in code.