Contributing
Quick Reference
| Action | Command |
|---|---|
| Clone the repo | git clone https://github.com/operatoronline/standard.git |
| Install dependencies | npm install |
| Build the site | npm run build |
| Preview locally | Open dist/index.html in a browser |
| Run tests | npx playwright test |
Project Structure
standard/
├── content/ # Markdown source for all pages
│ ├── index.md # Homepage
│ ├── getting-started.md
│ ├── changelog.md
│ ├── contributing.md # This page
│ ├── tokens/ # Token documentation
│ ├── components/ # Component documentation (32 pages)
│ └── patterns/ # Layout pattern documentation
├── styles/
│ ├── docs.css # All component + token styles (~5,300 lines)
│ ├── critical.css # Inline-injected critical path CSS
│ └── 404.css # 404 page styles
├── scripts/
│ ├── build.mjs # Static site generator
│ ├── docs.js # Client-side JS (search, theme, a11y)
│ ├── 404.js # 404 page search
│ └── generate-favicons.mjs
├── templates/
│ └── page.html # HTML template with placeholders
├── assets/
│ └── fonts/ # Self-hosted woff2 fonts
├── vendor/ # Vendored dependencies (Phosphor, Fuse, Prism, normalize)
└── dist/ # Built output (do not edit directly)
Development Workflow
1. Fork and Clone
git clone https://github.com/operatoronline/standard.git
cd standard
npm install
2. Make Your Changes
Edit files in content/, styles/, scripts/, or templates/. Never edit files in dist/ — they’re generated by the build.
3. Build and Preview
npm run build
Open dist/index.html in your browser. For nested pages, use a local server:
npx serve dist
4. Verify
Before committing, check:
- Both themes: Toggle between light and dark mode
- Mobile: Resize to 375px and 600px breakpoints
- Print: Use Cmd/Ctrl+P to preview print output
- Accessibility: Tab through interactive elements, check focus rings
5. Commit and Push
git add -A
git commit -m 'component: add Sidebar variant'
git push origin your-branch
Then open a pull request.
Commit Message Format
Use lowercase, imperative mood. Prefix with the area of change:
| Prefix | When to use | Example |
|---|---|---|
component: |
New or modified component | component: add Sidebar responsive variant |
token: |
Token additions or changes | token: add --space-9 and --space-10 |
pattern: |
Layout pattern changes | pattern: add Holy Grail layout |
docs: |
Documentation-only changes | docs: fix typo in Button API table |
a11y: |
Accessibility improvements | a11y: add aria-live to Toast container |
fix: |
Bug fixes | fix: dark mode Card border invisible |
build: |
Build pipeline changes | build: add webp image optimization |
perf: |
Performance improvements | perf: subset Phosphor icons to used glyphs |
improvement: |
General quality improvements | improvement: comprehensive dark mode audit |
Writing Component Documentation
Every component page follows a consistent structure. Use existing pages (like Buttons or Cards) as reference.
Page Structure
# Component Name
Brief description of what the component is and when to use it.
---
## Usage
Show the default/basic usage with a Preview block.
## Variants
Show each visual variant (e.g., sizes, colors, states).
## States
Interactive states — hover, focus, disabled, loading.
## Examples
Common real-world compositions.
## Best Practices
Do/Don't guidance with examples.
## API Reference
CSS class table with descriptions.
## CSS Reference
Custom properties the component uses.
Preview Blocks
Use the <Preview> component to show live examples with toggleable source code:
<Preview title="Primary Button">
<button class="Button Button--primary">Save Changes</button>
<button class="Button Button--secondary">Cancel</button>
</Preview>
The build script automatically generates:
- A live preview pane with theme toggle (light/dark/checkered)
- A responsive viewport switcher (desktop/tablet/mobile)
- A code pane with syntax highlighting and copy button
API Reference Tables
Use this format for documenting CSS classes:
| Class | Description |
|-------|-------------|
| `.Component` | Base class. Required. |
| `.Component--variant` | Modifier for visual variant. |
| `.Component-element` | Child element within the component. |
CSS Conventions
Class Naming
Standard uses a BEM-inspired naming convention:
| Pattern | Example | Usage |
|---|---|---|
.Block |
.Button |
Component root element |
.Block--modifier |
.Button--primary |
Visual or behavioral variant |
.Block-element |
.Alert-icon |
Child element of a component |
Rules
- Use design tokens. Never hardcode colors, spacing, font sizes, or shadows. Use
var(--token). - Stay on the 4px grid. All spacing values should map to
--space-1through--space-8. - Use the type scale. Font sizes use
--fs-3xsthrough--fs-hero. No magic numbers. - OKLCH only. All colors defined in OKLCH color space. No hex, no rgb, no hsl.
- Transition specific properties. Never
transition: all. Always list exact properties:transition: color, background var(--dur-n) var(--ease). - Dark mode everything. Every component needs
[data-theme="dark"]overrides AND matching@media (prefers-color-scheme: dark)rules insidehtml:not([data-theme="light"]). - Respect reduced motion. The global
prefers-reduced-motionrule handles most cases. If you add@keyframes, verify they’re covered. - Print considerations. If your component has interactive states, color fills, or shadows — add print overrides in the
@media printsection.
File Organization
All styles live in a single docs.css file, organized in sections:
/* ========= TOKENS ========= */
/* ========= BASE =========== */
/* ========= LAYOUT ========= */
/* ========= COMPONENTS ===== */
/* ========= DARK MODE ====== */
/* ========= PRINT ========== */
Find your component’s section and add rules there. Keep dark mode overrides in the dark mode section, print overrides in the print section.
Adding a New Component
Step 1: Create the Documentation
Create content/components/your-component.md following the page structure above.
Step 2: Add the Styles
Add CSS to styles/docs.css in the Components section. Include:
- Base styles
- All variants
- All states (hover, focus, disabled, active)
- Dark mode overrides
- Print overrides
- Responsive adjustments for mobile (
< 600px)
Step 3: Add to the Index
Add your component to content/index.md under the appropriate category.
Step 4: Build and Verify
npm run build
The build script automatically:
- Generates the HTML page from your markdown
- Adds it to the search index
- Includes it in the sitemap
- Creates the TOC sidebar (if ≥4 h2 headings)
Design Principles
When making decisions, these guide the system:
1. Zero Dependencies at Runtime
No JavaScript frameworks, no CSS preprocessors required. The built output is pure HTML + CSS + vanilla JS. Vendor libraries (Fuse.js, Prism.js, Phosphor Icons) are self-hosted and bundled.
2. Tokens First
Every visual decision flows through tokens. Components consume tokens, never raw values. This makes theming, dark mode, and consistency automatic.
3. Progressive Enhancement
Components work without JavaScript. JS adds enhancements (search, theme toggle, copy buttons, transitions) but nothing breaks without it.
4. Accessibility by Default
WCAG 2.1 AA is the baseline, not a goal. Contrast ratios, focus management, screen reader support, reduced motion — these are built in, not bolted on.
5. Performance is a Feature
Self-hosted fonts, minified assets, content-hash caching, lazy loading, vendored dependencies. Every decision favors fast page loads.
Browser Support
| Browser | Minimum Version | Reason |
|---|---|---|
| Chrome | 111+ | OKLCH, View Transitions API |
| Edge | 111+ | Chromium-based, same as Chrome |
| Safari | 17+ | OKLCH support |
| Firefox | 121+ | OKLCH support |
OKLCH is the hard floor. We don’t polyfill or fallback to older color spaces.
Accessibility Checklist
Before submitting a component PR, verify:
- [ ] Color contrast passes 4.5:1 for text, 3:1 for UI elements (use
--*-texttokens for status colors) - [ ] All interactive elements have visible
:focus-visiblestyles - [ ]
aria-labelor visible text on every button and link - [ ] Decorative icons have
aria-hidden="true" - [ ] Component works with keyboard only (Tab, Enter, Escape, Arrow keys as appropriate)
- [ ]
prefers-reduced-motiondisables animations - [ ] Dark mode doesn’t break contrast or visibility
- [ ] Screen reader announces state changes (use the
announceToScreenReader()utility)
Icon Usage
Standard uses Phosphor Icons with a deliberate weight hierarchy:
| Weight | Class | Usage |
|---|---|---|
| Bold | ph-bold |
Navigation chrome (nav links, theme toggle, search) |
| Regular | ph |
UI controls and content icons (alerts, buttons, preview toolbar) |
| Fill | ph-fill |
Active/selected states (filled stars in Rating) |
| Duotone | ph-duotone |
Decorative/showcase contexts |
Don’t mix weights arbitrarily. Follow the hierarchy.
Getting Help
- Site: standard.operator.onl
- Issues: GitHub Issues
- Source: GitHub Repository
License
Standard is released under the MIT License. Contributions are made under the same license.