diff --git a/ROADMAP.md b/ROADMAP.md index 32de872..4cd4ca8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,11 +1,15 @@ # Roadmap +- [Completed](#completed) +- [TODO](#to-do) +- [Examples (Planned)](#examples) + | Version | State | Milestone | Summary | | ------- | ----- | ---------------------------------------------------------- | ------------------------------------------------------------------------ | | | ✓ | [Foundations](#foundations) | Initial project setup, tooling, and reactive signal prototype. | -| | ✓ | [Reactivity & Bindings](#reactivity--bindings) | Core DOM bindings (`data-x-*`) and declarative updates. | +| | ✓ | [Reactivity & Bindings](#reactivity--bindings) | Core DOM bindings (`dava-volt-*`) and declarative updates. | | | ✓ | [Actions & Effects](#actions--effects) | Event system and derived reactivity primitives. | -| | | [Plugins Framework](#plugins-framework) | Modular plugin system and first built-in plugin set. | +| | ✓ | [Plugins Framework](#plugins-framework) | Modular plugin system and first built-in plugin set. | | | | [Streaming & Patch Engine](#streaming--patch-engine) | SSE/WebSocket JSON patch streaming. | | | | [Persistence & Offline](#persistence--offline) | State persistence, storage sync, and fallback behaviors. | | v0.1.0 | ✓ | [Markup Based Reactivity](#markup-based-reactivity) | Allow users to write apps without any bundled JS | @@ -15,7 +19,7 @@ | v0.5.0 | | PWA Capabilities | TODO | | v1.0.0 | | [Release](#stable-release) | Public API freeze, plugin registry, and versioned documentation. | -## Details +## Completed _NOTE_: `data-x-*` is now `data-volt-*` @@ -44,7 +48,7 @@ _NOTE_: `data-x-*` is now `data-volt-*` **Goal:** Add event-driven behavior and derived reactivity. **Outcome:** Fully functional reactive UI layer with event bindings and computed updates. **Deliverables:** - - ✓ Event binding system (`data-x-on-*`) + - ✓ Event binding system (`dava-volt-on-*`) - ✓ `$el` and `$event` scoped references - ✓ Derived signals (`computed`, `effect`) - ✓ Async effects (e.g., fetch triggers) @@ -57,28 +61,52 @@ _NOTE_: `data-x-*` is now `data-volt-*` - ✓ `registerPlugin(name, fn)` API - ✓ Context and lifecycle hooks - ✓ Built-ins: - - ✓ `data-x-persist` - - ✓ `data-x-scroll` - - ✓ `data-x-url` - - ✓ Tests & registry - - ✓ Setup test coverage with generous thresholds (~50%) - - Example in docs/examples/plugins.md - - End-to-end examples (counter, form, live field updates) - - `docs/examples/reactivity.md` - - `actions`, `effects`, `signals` + - ✓ `dava-volt-persist` + - ✓ `dava-volt-scroll` + - ✓ `dava-volt-url` + - ✓ Registry + +## To-Do + +### Markup Based Reactivity + +**Goal:** Allow Volt apps to declare state, bindings, and behavior entirely in HTML markup +**Outcome:** Authors can ship examples without companion JavaScript bundles +**Deliverables:** + - ✓ Auto-bootstrapping loader (`volt.min.js`) that detects `data-volt` roots and hydrates one scope per root. + - ✓ Declarative state primitives (`data-volt-state`, `data-volt-computed:*`) aligned with `docs/reactivity-spec.md`. + - ✓ Binding directives for text, attributes, classes, styles, and two-way form controls (`data-volt-[bind|text|model|class:*]`). + - ✓ Control-flow directives (`data-volt-for`, `data-volt-if`, `data-volt-else`) with lifecycle-safe teardown. + - ✓ Declarative event system (`data-volt-on:*`) with helper surface for list mutations and plugin hooks. + - Sandboxed expression evaluator + - SSR compatibility helpers + +### Backend Integration & HTTP Actions + +**Goal:** Provide backend integration with declarative HTTP requests and responses. +**Outcome:** Volt.js can make backend requests and update the DOM +**Deliverables:** + - HTTP action system (`data-volt-get`, `data-volt-post`, `data-volt-put`, `data-volt-patch`, `data-volt-delete`) + - Request configuration (`data-volt-trigger`, `data-volt-target`, `data-volt-swap`) + - Swap strategies (innerHTML, outerHTML, beforebegin, afterbegin, beforeend, afterend, delete, none) + - Loading states and indicators (`data-volt-indicator`) + - Error handling and retry logic + - See [svelte](https://svelte.dev/docs/svelte/await-expressions) for inspiration for loading & errors (`#await`) + - Form serialization and submission + - Request/response headers customization ### Streaming & Patch Engine -**Goal:** Enable real-time updates via SSE/WebSocket streaming. +**Goal:** Enable real-time updates via SSE/WebSocket streaming with intelligent DOM patching. **Outcome:** Volt.js can receive and apply live updates from the server **Deliverables:** - - JSON Patch parser and DOM applier - - `data-volt-stream` attribute - - Reconnection/backoff logic - - Raise test coverage threshold to 60% - - Integration test with mock SSE server - - Benchmarks for patch vs re-render - - Performance test suite + - Server-Sent Events (SSE) integration + - `data-volt-stream` attribute for SSE endpoints + - Signal patching from backend (`data-signals-*` merge system) + - Backend action system with `$$action()` syntax (TBD on final syntax decision) + - JSON Patch parser and DOM morphing engine + - WebSocket as alternative to SSE + - `data-volt-ignore-morph` for selective patch exclusion ### Persistence & Offline @@ -86,21 +114,103 @@ _NOTE_: `data-x-*` is now `data-volt-*` **Outcome:** Resilient state persistence and offline replay built into Volt.js. **Deliverables:** - ✓ Persistent signals (localStorage, sessionStorage, indexedDb) - - ✓ Storage plugin (`data-x-persist`) - - Offline queue for deferred stream events - - Sync strategy API (merge, overwrite, patch) - - Example apps: note editor ([golang](#examples)), counter with persistence ([spa](#examples)) + - ✓ Storage plugin (`data-volt-persist`) + - Storage modifiers on signals: + - `.local` modifier for localStorage persistence + - `.session` modifier for sessionStorage persistence + - `.ifmissing` modifier for conditional initialization + - Offline queue for deferred stream events and HTTP requests + - Sync strategy API (merge, overwrite, patch) for conflict resolution + - Service Worker integration for offline-first apps + - Background sync for deferred requests + - Cache invalidation strategies + - Cross-tab synchronization via `BroadcastChannel` + +### Reactive Attributes & Event Modifiers + +**Goal:** Extend Volt.js with expressive attribute patterns and event options for fine-grained control. +**Outcome:** Volt.js supports rich declarative behaviors and event semantics built entirely on standard DOM APIs. +**Deliverables:** + - `data-x-show` — toggles element visibility via CSS rather than DOM removal (complements `data-x-if`) + - `data-x-style` — binds inline styles to reactive expressions + - `data-x-skip` — marks elements or subtrees to exclude from Volt’s reactive parsing + - `data-x-cloak` — hides content until the Volt runtime initializes + - Event options for `data-x-on-*` attributes: + - `.prevent` — calls `preventDefault()` on the event + - `.stop` — stops propagation + - `.self` — triggers only when the event target is the bound element + - `.window` — attaches the listener to `window` + - `.document` — attaches the listener to `document` + - `.once` — runs the handler a single time + - `.debounce` — defers handler execution (optional milliseconds) + - `.throttle` — limits handler frequency (optional milliseconds) + - `.passive` — adds a passive event listener for scroll/touch performance + - Input options for `data-x-bind` and `data-x-model`: + - `.number` — coerces values to numbers + - `.trim` — removes surrounding whitespace + - `.lazy` — syncs only on `change` instead of `input` + - `.debounce` — delays updates to reduce jitter + +### Global State + +**Goal:** Implement store/context pattern +**Outcome:** Volt.js provides intuitive global state management +**Deliverables:** + - `$refs` - Scoped element references via dava-volt-ref="name". Provides an object mapping ref names to DOM nodes. + - Example: `dava-volt-on-click="$refs.username.focus()"` + - `$next()` - Defers execution to the next microtask tick after DOM updates. + - Example: `dava-volt-on-click="$count++; $next(() => console.log('updated'))"` + - `$watch(expr, fn)` - Imperatively observes a reactive signal or expression within the current scope. + - Example: `dava-volt-init="$watch('count', v => console.log(v))"` + - `$emit(event, detail?)` - Dispatches a native CustomEvent from the current element. + - Example: `dava-volt-on-click="$emit('user:save', { id })"` + - `$store` - Accesses global reactive state registered with Volt’s global store. + - Example: `dava-volt-text="$store.theme"` + - `$uid(name?)` - Generates a unique, deterministic ID string within the current scope. + - Example: `dava-volt-id="$uid('field')"` + - `$root` - Reference to the root element of the active reactive scope. + - `$scope` - Reference to the current reactive scope object (signals + context). ### Animation & Transitions -**Goal:** Add animation primitives for smooth UI transitions. +**Goal:** Add animation primitives for smooth UI transitions with Alpine/Datastar parity. **Outcome:** Volt.js enables declarative animations and view transitions alongside reactivity. **Deliverables:** - - `data-volt-animate` plugin - - View Transition API support (when available) + - `data-volt-transition` directive with enter/leave transitions + - Transition modifiers (duration, delay, opacity, scale, etc.) + - View Transitions API integration (when available) - CSS-based transition helpers - - Timing utilities (`transition`, `raf`) - - Plugin tests and performance profiling + - `data-volt-animate` plugin for keyframe animations + - Timing utilities and easing functions + - Integration with `data-volt-if` and `data-volt-show` for automatic transitions + +### Background Requests & Reactive Polling + +**Goal:** Enable declarative background data fetching and periodic updates within the Volt.js runtime. +**Outcome:** Volt.js elements can fetch or refresh data automatically based on time, visibility, or reactive conditions. +**Deliverables:** + - `dava-volt-fetch` attribute for declarative background requests + - Configurable polling intervals, delays, and signal-based triggers + - `dava-volt-visible` for fetching when an element enters the viewport (`IntersectionObserver`) + - Background task scheduler with priority management + - Automatic cancellation of requests when elements are unmounted + - Conditional execution tied to reactive signals + - Integration hooks for loading and pending states + +### Navigation & History Management + +**Goal:** Introduce seamless client-side navigation and stateful history control using web standards. +**Outcome:** Volt.js provides enhanced navigation behavior with minimal overhead and full accessibility support. +**Deliverables:** + - `dava-volt-navigate` for intercepting link and form actions + - Integration with the History API (`pushState`, `replaceState`, `popState`) + - Reactive synchronization of route and signal state + - Smooth page and fragment transitions coordinated with Volt’s signal system + - Native back/forward button support + - Scroll position persistence and restoration + - Optional preloading of linked resources on hover or idle + - `dava-volt-url` for declarative history updates + - Optional View Transition API integration for animated route changes ### Inspector & Developer Tools @@ -110,8 +220,11 @@ _NOTE_: `data-x-*` is now `data-volt-*` - Developer overlay for inspecting signals, subscriptions, and effects - Dev logging toggle (`Volt.debug = true`) - Browser console integration (`window.$volt.inspect()`) - - Visualization plugin for dependency graph - - Testing coverage for dev mode + - Signal dependency graph visualization + - Performance profiling tools + - Request/response debugging (HTTP actions, SSE streams) + - Time-travel debugging for signal history + - Browser DevTools extension ### Documentation & Stability Pass @@ -120,15 +233,14 @@ _NOTE_: `data-x-*` is now `data-volt-*` **Deliverables:** - ✓ Documentation site (VitePress) - Full API reference with examples - - Migration and versioning guide - Performance benchmarks (vs htmx, Alpine) - Browser matrix tests (Chromium, Gecko, WebKit) - - Accessibility audits (ARIA reactivity) + - Accessibility audits (ARIA) - Freeze API surface for 1.0 ### Stable Release -**Goal:** Ship the first stable version of Volt.js. +**Goal:** Ship the first stable version of Volt.js **Outcome:** Volt.js 1.0 is released as a mature, fully documented, type-safe, reactive web framework **Deliverables:** - Finalized plugin registry and CLI (`volt plugins list/init`) @@ -136,31 +248,50 @@ _NOTE_: `data-x-*` is now `data-volt-*` - Announcement post and release notes - Community contribution guide & governance doc -### Markup Based Reactivity +## Examples -**Goal:** Allow Volt apps to declare state, bindings, and behavior entirely in HTML markup -**Outcome:** Authors can ship examples without companion JavaScript bundles -**Deliverables:** - - ✓ Auto-bootstrapping loader (`volt.min.js`) that detects `data-volt` roots and hydrates one scope per root. - - ✓ Declarative state primitives (`data-volt-state`, `data-volt-computed:*`) aligned with `docs/reactivity-spec.md`. - - ✓ Binding directives for text, attributes, classes, styles, and two-way form controls (`data-volt-[bind|text|model|class:*]`). - - ✓ Control-flow directives (`data-volt-for`, `data-volt-if`, `data-volt-else`) with lifecycle-safe teardown. - - ✓ Declarative event system (`data-volt-on:*`) with helper surface for list mutations and plugin hooks. - - SSR compatibility helpers and sandboxed expression evaluator +Many of these are ideas, not planned to be implemented -## Examples +### Components + +- Modal Dialog - Conditional rendering, focus trapping, backdrop, keyboard escape +- Tabs & Accordion - Conditional rendering, active state management, keyboard navigation +- Form Validation - Model binding, computed validation, conditional messages, error states + +### Client-Side (SPA/Static) + +- ✓ Counter - Basic signals, computed, event handling +- ✓ TodoMVC - List rendering, persistence, filtering, CRUD operations +- Search with Autocomplete - Async effects, debouncing, API integration, keyboard navigation +- Calculator - Event handling, computed expressions, button grid, operation state +- Image Gallery - For loops, filtering, lightbox, category selection + +- Multi-Step Wizard - Form state across steps, validation per step, progress tracking, navigation +- Note-Taking App - Rich CRUD, categories/tags, search/filter, localStorage persistence, markdown preview +- Expense Tracker - Date handling, categories, computed totals/charts, filtering by date range, CSV export +- Kanban Board - Drag-and-drop (via events), column management, task editing, state persistence +- Timer/Stopwatch - Async effects, intervals, lap times, pause/resume, localStorage for history + +- Real-time Chat - SSE for messages, typing indicators, user presence, message history +- Live Dashboard - SSE for metrics, charts updating in real-time, WebSocket fallback +- Collaborative Editor - Operational transforms, SSE for changes, conflict resolution, cursor positions +- Infinite Scroll Feed - Polling for new items, intersection observer, virtualized rendering +- Admin Panel/CMS - CRUD operations, data tables, filters, pagination, bulk actions + +### Server-Side Rendered (SSR) + +These will live in an example repo. + +- Authentication Flows - Login, signup, password reset, email verification (Go, Python, Rust, Node) +- File Upload with Progress - Chunked uploads, progress bars, validation (Go, Python, Rust, Node) +- Search with Server-Side Filtering - Debounced search, paginated results (Go, Python,Rust, Node) + +### Desktop Apps -- SSR - - Django (separate repo) - - FastAPI + jinja2 (separate repo) - - Golang + templ (separate repo) - - Fastify (separate repo) - - Express - - Golang -- SPA - - Web - - Tauri - - Wails +- Note Editor - Local file system, syntax highlighting, multi-tab, settings persistence +- System Monitor - CPU/memory graphs, process list, real-time updates +- Database Client - Table browser, query editor, result grid, export +- Media Player - File browser, playlists, controls, metadata display ## Docs @@ -168,4 +299,4 @@ _NOTE_: `data-x-*` is now `data-volt-*` - [ ] Add async effect guide covering abort signals, debounce/throttle, retries, and `onError` handling. - [ ] Write lifecycle instrumentation docs for `registerGlobalHook`, `registerElementHook`, `getElementBindings`, and plugin `context.lifecycle` callbacks. - [ ] Explain `data-volt-bind:*` semantics, especially boolean attribute handling and dependency subscription behavior. -- [ ] Refresh README and overview content to use `data-volt-*` naming and reflect the current module layout. +- [ ] Refresh README and overview content to reflect the current module layout. diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index d2fedcf..396f42a 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,4 +1,5 @@ import { defineConfig } from "vitepress"; +import { u } from "./utils"; // https://vitepress.dev/reference/site-config export default defineConfig({ @@ -10,20 +11,17 @@ export default defineConfig({ { text: "Home", link: "/" }, { text: "Overview", link: "/overview" }, { text: "CSS", link: "/css/volt-css" }, - { text: "API", link: "/api-examples" }, + { text: "API", link: "/api" }, ], sidebar: [ - { - text: "Getting Started", - items: [{ text: "Introduction", link: "/" }, { text: "Overview", link: "/overview" }], - }, + { text: "Getting Started", items: [{ text: "Overview", link: "/overview" }] }, { text: "CSS", collapsed: false, - items: [{ text: "Volt CSS", link: "/css/volt-css" }, { text: "CSS Reference", link: "/css/semantics" }], + items: [{ text: "Volt CSS", link: "/css/volt-css" }, { text: "Reference", link: "/css/semantics" }], }, - { text: "API Reference", collapsed: false, items: [{ text: "Runtime API", link: "/api-examples" }] }, - { text: "Plugin System", collapsed: false, items: [{ text: "Plugin Spec", link: "/plugin-spec" }] }, + { text: "Specs", collapsed: true, items: u.scanDir("spec", "/spec") }, + { text: "API Reference", collapsed: true, items: u.scanDir("api", "/api") }, ], socialLinks: [{ icon: "github", link: "https://github.com/stormlightlabs/volt" }], }, diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css index 7c1835b..520917e 100644 --- a/docs/.vitepress/theme/style.css +++ b/docs/.vitepress/theme/style.css @@ -15,25 +15,25 @@ --vp-c-sonics-green-1: #2a6b5d; --vp-c-sonics-green-2: #1f5248; --vp-c-sonics-green-3: #173F35; - --vp-c-sonics-green-soft: rgba(23, 63, 53, 0.14); + --vp-c-sonics-green-soft: #c5dbd7; /* SuperSonics Yellow - Secondary/Warning */ --vp-c-sonics-yellow-1: #ffbb33; --vp-c-sonics-yellow-2: #ffad1a; --vp-c-sonics-yellow-3: #FFA300; - --vp-c-sonics-yellow-soft: rgba(255, 163, 0, 0.14); + --vp-c-sonics-yellow-soft: #ffefc2; /* SuperSonics Red - Danger */ --vp-c-sonics-red-1: #c24348; --vp-c-sonics-red-2: #b03338; --vp-c-sonics-red-3: #9E2A2F; - --vp-c-sonics-red-soft: rgba(158, 42, 47, 0.14); + --vp-c-sonics-red-soft: #edd5d7; /* SuperSonics Bronze - Accent */ --vp-c-sonics-bronze-1: #a3836b; --vp-c-sonics-bronze-2: #97735a; --vp-c-sonics-bronze-3: #8B634B; - --vp-c-sonics-bronze-soft: rgba(139, 99, 75, 0.14); + --vp-c-sonics-bronze-soft: #e8ddd3; } /** @@ -45,25 +45,21 @@ --vp-c-default-3: var(--vp-c-gray-3); --vp-c-default-soft: var(--vp-c-gray-soft); - /* Use Emerald Green as primary brand color */ --vp-c-brand-1: var(--vp-c-sonics-green-1); --vp-c-brand-2: var(--vp-c-sonics-green-2); --vp-c-brand-3: var(--vp-c-sonics-green-3); --vp-c-brand-soft: var(--vp-c-sonics-green-soft); - /* Tips use Bronze accent */ --vp-c-tip-1: var(--vp-c-sonics-bronze-1); --vp-c-tip-2: var(--vp-c-sonics-bronze-2); --vp-c-tip-3: var(--vp-c-sonics-bronze-3); --vp-c-tip-soft: var(--vp-c-sonics-bronze-soft); - /* Warnings use Yellow */ --vp-c-warning-1: var(--vp-c-sonics-yellow-1); --vp-c-warning-2: var(--vp-c-sonics-yellow-2); --vp-c-warning-3: var(--vp-c-sonics-yellow-3); --vp-c-warning-soft: var(--vp-c-sonics-yellow-soft); - /* Danger uses Red */ --vp-c-danger-1: var(--vp-c-sonics-red-1); --vp-c-danger-2: var(--vp-c-sonics-red-2); --vp-c-danger-3: var(--vp-c-sonics-red-3); @@ -71,10 +67,10 @@ } .dark { - /* Enhance dark mode background */ - --vp-c-bg: #0d1117; - --vp-c-bg-soft: #161b22; - --vp-c-bg-mute: #1c2128; + --vp-c-bg: #1a1a1a; + --vp-c-bg-soft: #242424; + --vp-c-bg-mute: #2e2e2e; + --vp-c-bg-alt: #202020; } /** @@ -92,9 +88,7 @@ --vp-button-brand-active-bg: var(--vp-c-brand-1); } -/** - * Home - **/ + :root { --vp-home-hero-name-color: transparent; --vp-home-hero-name-background: -webkit-linear-gradient( @@ -123,9 +117,7 @@ } } -/** - * Custom Block - **/ + :root { --vp-custom-block-tip-border: transparent; --vp-custom-block-tip-text: var(--vp-c-text-1); diff --git a/docs/.vitepress/utils.ts b/docs/.vitepress/utils.ts new file mode 100644 index 0000000..61bac84 --- /dev/null +++ b/docs/.vitepress/utils.ts @@ -0,0 +1,62 @@ +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { DefaultTheme } from "vitepress"; + +type SidebarItem = DefaultTheme.SidebarItem; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +export const u = { + scanDir(dir: string, baseUrl = ""): SidebarItem[] { + const items: SidebarItem[] = []; + + try { + const resolvedDir = path.resolve(__dirname, "..", dir); + const files = fs.readdirSync(resolvedDir); + + for (const file of files) { + const fullPath = path.join(resolvedDir, file); + const stat = fs.statSync(fullPath); + + if (stat.isDirectory()) { + continue; + } + + if (!file.endsWith(".md")) { + continue; + } + + if (file === "index.md") { + continue; + } + + const content = fs.readFileSync(fullPath, "utf-8"); + const title = this.extractTitle(content, file); + const link = `${baseUrl}/${path.parse(file).name}`; + + items.push({ text: title, link }); + } + } catch (error) { + console.error(`Error scanning directory ${dir}:`, error); + } + + return items.toSorted((a, b) => a.text && b.text ? a.text.localeCompare(b.text) : 0); + }, + extractTitle(content: string, filename: string): string { + const frontmatter = content.match(/^---\s*\n([\s\S]*?)\n---/); + if (frontmatter) { + const title = frontmatter[1].match(/title:\s*(.+)/); + if (title) { + return title[1].replace(/['"]/g, "").trim(); + } + } + + const heading = content.match(/^#\s+(.+)/m); + if (heading) { + return heading[1].trim(); + } + + return path.parse(filename).name.split("-").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" "); + }, +}; diff --git a/docs/api-examples.md b/docs/api-examples.md deleted file mode 100644 index 6bd8bb5..0000000 --- a/docs/api-examples.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -outline: deep ---- - -# Runtime API Examples - -This page demonstrates usage of some of the runtime APIs provided by VitePress. - -The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files: - -```md - - -## Results - -### Theme Data -
{{ theme }}
-
-### Page Data
-{{ page }}
-
-### Page Frontmatter
-{{ frontmatter }}
-```
-
-
-
-## Results
-
-### Theme Data
-{{ theme }}
-
-### Page Data
-{{ page }}
-
-### Page Frontmatter
-{{ frontmatter }}
-
-## More
-
-Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).
diff --git a/docs/css/volt-css.md b/docs/css/volt-css.md
index 286f379..b974340 100644
--- a/docs/css/volt-css.md
+++ b/docs/css/volt-css.md
@@ -9,10 +9,11 @@ Volt CSS embraces semantic HTML5 and lets the content structure define the prese
### Core Principles
- **Classless**: Style semantic HTML elements directly.
-- Optimized line lengths, modular type scale, and generous whitespace optimized for reading
-- Automatic light and dark modes via `prefers-color-scheme` to respect user preferences with carefully calibrated color palettes for both modes.
-- **Accessibility**: WCAG AA contrast ratios, keyboard navigation support, and semantic HTML patterns
-- Mobile-first (ish) design that adapts gracefully from phones to wide desktop monitors without compromising readability.
+- **Accessible**: WCAG AA contrast ratios, keyboard navigation support, and semantic HTML patterns
+
+- Optimized line lengths, modular type scale, and whitespace optimized for reading
+- Automatic light and dark modes via `prefers-color-scheme`
+- Mobile-first (ish) design that doesn't compromise readability
## Inspiration
@@ -38,7 +39,7 @@ All semantic HTML5 elements are styled out of the box:
### Tufte-Style Sidenotes
-Inspired by Edward Tufte's beautiful book design, margin notes can be added using simple `` elements within paragraphs.
+Inspired by Edward Tufte's design principles, margin notes can be added using simple `` elements within paragraphs.
**Desktop**: Notes appear in the right margin
**Mobile**: Notes appear inline with subtle styling
@@ -79,8 +80,6 @@ The stylesheet automatically switches to dark mode when the user's system prefer
}
```
-Both themes use carefully selected colors with proper contrast ratios for accessibility.
-
## Usage
### Basic Setup
@@ -124,8 +123,12 @@ Include the stylesheet in your HTML ``:
Author Name
- // Code blocks use monospace fonts
-const example = "syntax highlighting not included";
+
+
+ // Code blocks use monospace fonts
+ const example = "syntax highlighting not included";
+
+