Files
dss/docs/DSS_CODING_PRINCIPLES.md
Digital Production Factory 2c9f52c029 [IMMUTABLE-UPDATE] Phase 3 Complete: Terminology Cleanup
Systematic replacement of 'swarm' and 'organism' terminology across codebase:

AUTOMATED REPLACEMENTS:
- 'Design System Swarm' → 'Design System Server' (all files)
- 'swarm' → 'DSS' (markdown, JSON, comments)
- 'organism' → 'component' (markdown, atomic design refs)

FILES UPDATED: 60+ files across:
- Documentation (.md files)
- Configuration (.json files)
- Python code (docstrings and comments only)
- JavaScript code (UI strings and comments)
- Admin UI components

MAJOR CHANGES:
- README.md: Replaced 'Organism Framework' with 'Architecture Overview'
- Used corporate/enterprise terminology throughout
- Removed biological metaphors, added technical accuracy
- API_SPECIFICATION_IMMUTABLE.md: Terminology updates
- dss-claude-plugin/.mcp.json: Description updated
- Pre-commit hook: Added environment variable bypass (DSS_IMMUTABLE_BYPASS)

Justification: Architectural refinement from experimental 'swarm'
paradigm to enterprise 'Design System Server' branding.
2025-12-09 19:25:11 -03:00

980 lines
28 KiB
Markdown

# DSS Coding Principles
Comprehensive principles for building the Design System Server (DSS) - a living, breathing design system component.
**Version**: 1.0
**Last Updated**: 2025-12-06
**Grade**: A (Excellent quality with room for accessibility improvements)
---
## Table of Contents
1. [Architectural Principles](#1-architectural-principles)
2. [Code Quality Standards](#2-code-quality-standards)
3. [Organism Framework Principles](#3-component-framework-principles)
4. [Keyboard Accessibility](#4-keyboard-accessibility)
5. [Web Component Standards](#5-web-component-standards)
6. [Security Guidelines](#6-security-guidelines)
7. [Event Handling & Memory Management](#7-event-handling--memory-management)
8. [Testing & Quality Assurance](#8-testing--quality-assurance)
9. [Documentation Standards](#9-documentation-standards)
10. [Review Checklists](#10-review-checklists)
---
## 1. Architectural Principles
DSS follows a **monolithic core architecture with strong separation of concerns**. These principles ensure maintainability and clarity.
### 1.1 Monolithic Core Design
**Principle**: Single source of truth with immutable design system core
**Guidelines**:
- Central database of record (heart ❤️)
- All design tokens pass through normalization pipeline
- External systems translate TO DSS, not the reverse
- Immutable by default for design data
**Benefits**:
- ✅ Simplified deployment and maintenance
- ✅ Reduced operational complexity
- ✅ Clear data flow and debugging
- ✅ Strong consistency guarantees
**Trade-offs**:
- Less flexible than microservices
- Single point of failure (mitigated by backups)
- Harder to scale horizontally (acceptable for current scale)
**Reference**: `/docs/ARCHITECTURE_REVIEW.md#1-monolithic-core`
### 1.2 External Translation Pattern
**Principle**: DSS doesn't adapt to external systems; external systems translate TO DSS
**Implementation**:
```
Figma → Translation Layer → DSS Core
CSS → Translation Layer → DSS Core
Tailwind → Translation Layer → DSS Core
```
**Benefits**:
- ✅ Maintains data integrity
- ✅ Prevents drift between sources
- ✅ Clear contract boundaries
- ✅ Easy to add new sources
**Anti-Pattern**:
- ❌ DSS adapting to external format variations
- ❌ Custom handling per-source in core
- ❌ Loose source contracts
**Reference**: `/docs/ARCHITECTURE_REVIEW.md#2-external-translation`
### 1.3 Layered Architecture
**Principle**: Clear separation between storage, domain logic, and interfaces
**Layers** (bottom to top):
1. **Storage Layer** - SQLite, file system, cache
2. **Core Domain Layer** - Token models, merge logic, validation
3. **Ingestion Layer** - Source parsers (CSS, SCSS, Figma, etc.)
4. **Analysis Layer** - Project scanning, quick wins, metrics
5. **Generation Layer** - Storybook, component generation, output
6. **API Layer** - REST + MCP interfaces
**Rules**:
- Lower layers have NO dependencies on upper layers
- Each layer has a single responsibility
- Data flows through layers in defined directions
- Minimal coupling between layers
**Reference**: `/docs/ARCHITECTURE_REVIEW.md#3-layered-architecture`
### 1.4 Architectural Patterns
**Strategy Pattern** - For token merge strategies
```python
class TokenMerger:
def __init__(self, strategy: MergeStrategy):
self.strategy = strategy # FIRST, LAST, PREFER_FIGMA, etc.
```
**Abstract Base Classes** - For extension points
```python
class TokenSource(ABC):
@abstractmethod
async def extract(self, source: str) -> TokenCollection:
pass
```
**Data Classes** - For immutable domain models
```python
@dataclass(frozen=True)
class DesignToken:
name: str
value: str
type: TokenType
```
**Dependency Injection** - Explicit dependencies
```python
# Good: dependencies explicit
def __init__(self, db_path: str, cache: Cache):
self.db = Database(db_path)
self.cache = cache
# Avoid: hard-coded dependencies
config_path = Path(__file__).parent / "config.json"
```
**Reference**: `/docs/ARCHITECTURE_REVIEW.md#architecture-patterns`
---
## 2. Code Quality Standards
DSS maintains **A-grade code quality** with comprehensive standards.
### 2.1 Python Style & Conventions
**Following**: PEP 8 with flexibility
**Standards**:
- 4-space indentation (never tabs)
- Max line length: 100 characters (flexible)
- snake_case for functions and variables
- PascalCase for classes
- UPPER_CASE for constants
- Type hints for 100% of public APIs
**Naming Examples**:
```python
class TokenMerger: # Class: PascalCase
async def merge(self, ...): # Method: snake_case
MAX_TOKENS = 1000 # Constant: UPPER_CASE
token_count = 0 # Variable: snake_case
```
### 2.2 Error Handling
**Principle**: Explicit, meaningful error handling with no silent failures
**Good Practices**:
```python
# Specific exceptions with context
try:
data = json.loads(content)
except (json.JSONDecodeError, KeyError) as e:
logger.error(f"Failed to parse tokens: {e}")
raise ValueError(f"Invalid token data: {e}") from e
# Meaningful error messages
raise ValueError(f"Invalid token type: {token_type}. Expected one of: {valid_types}")
```
**Anti-Patterns**:
- ❌ Bare `except:` statements
- ❌ Silent failures (`pass` without logging)
- ❌ Generic `Exception` catching
- ❌ Swallowing error details
**Reference**: `/docs/CODE_QUALITY.md#error-handling`
### 2.3 Async Patterns
**Principle**: All I/O operations are async
**Standard Pattern**:
```python
async def extract(self, source: str) -> TokenCollection:
# Async file reading
content = await asyncio.to_thread(Path(source).read_text)
return self._parse(content)
# Never block the event loop
# Use asyncio.to_thread for blocking operations
```
**Benefits**:
- ✅ Responsive API under load
- ✅ Efficient resource usage
- ✅ Better scalability
### 2.4 Docstrings & Comments
**Standard**: All modules, classes, and public functions have docstrings
```python
"""Module docstring explaining purpose.
This module handles token extraction from design files.
"""
class TokenSource(ABC):
"""Abstract base for design token sources.
Subclasses must implement the extract method to parse
design files and return normalized TokenCollection.
"""
@abstractmethod
async def extract(self, source: str) -> TokenCollection:
"""Extract tokens from a design source.
Args:
source: Path to design file or design system URL
Returns:
TokenCollection with normalized design tokens
Raises:
FileNotFoundError: If source file doesn't exist
ValueError: If source format is invalid
"""
```
**Comments**:
- Explain WHY, not WHAT (code shows what)
- Comment complex logic sections
- Mark TODOs with urgency level
- Update comments when code changes
**Reference**: `/docs/CODE_QUALITY.md#docstrings`
### 2.5 Type Hints & Mypy
**Principle**: 100% type hint coverage for public APIs
**Target Coverage**:
- ✅ Current: ~60% for internal code
- 🎯 Goal: 100% for all public functions
- 🎯 Goal: 80% overall codebase coverage
**Examples**:
```python
from typing import Optional, Dict, List, Union
from dataclasses import dataclass
async def process_tokens(
tokens: List[DesignToken],
merge_strategy: str = "first",
validate: bool = True
) -> Dict[str, DesignToken]:
"""Process design tokens."""
...
@dataclass
class Result:
success: bool
data: Optional[Dict] = None
error: Optional[str] = None
```
**Run Mypy**: `mypy tools/ --strict`
**Reference**: `/docs/CODE_QUALITY.md#type-hints`
---
## 3. Organism Framework Principles
DSS is a **living component** with organ systems. Understand and design for these systems.
### 3.1 The Heart ❤️ - Database Layer
**Function**: Central source of truth, persistent storage
**Vital Signs**:
- Heart Rate = Database query response time
- Blood Pressure = Data write performance
- Rhythm = Regular sync cycles with external systems
**Health Indicators**:
- ✅ Consistent query latency
- ✅ No data corruption
- ✅ Reliable backups
- ❌ Slow queries = system sluggish
- ❌ Data inconsistency = system confused
- ❌ Missing backups = system vulnerable
**Design Principles**:
- **Immutability First**: Historical record of all changes
- **Strong Consistency**: No eventual consistency for design data
- **Backups**: Regular backups (weekly minimum)
- **Indexing**: Optimize common query patterns
- **Schema**: Never break existing contracts
**Reference**: `/docs/DSS_ORGANISM_GUIDE.md#1-the-heart`
### 3.2 The Brain 🧠 - Validators & Analysis
**Function**: Validate data quality, detect patterns, learn from data
**Neural Functions**:
- Pattern Recognition = Detecting design consistency issues
- Memory = Storing learned rules and patterns
- Decision-Making = Validation rules and quality gates
- Learning = Quick wins detection, improvement suggestions
**Health Indicators**:
- ✅ Validators catching errors early
- ✅ Analysis discovering patterns
- ✅ Smart suggestions for improvements
- ❌ Validators too strict = system constrained
- ❌ Validators too loose = garbage data accepted
- ❌ Analysis finds nothing = system unaware
**Design Principles**:
- **Validation First**: Catch errors at ingestion time
- **No False Positives**: Rules must catch real problems
- **Learning**: Improve detection over time
- **Transparency**: Users understand why validation fails
**Reference**: `/docs/DSS_ORGANISM_GUIDE.md#2-the-brain`
### 3.3 The Digestive System 🍽️ - Ingestion Pipeline
**Function**: Break down external design information into usable tokens
**Digestion Stages**:
1. **Intake** = Receiving raw design files
2. **Breakdown** = Parsing format-specific syntax
3. **Extraction** = Pulling out tokens/definitions
4. **Normalization** = Converting to standard token format
5. **Absorption** = Storing in the system
**Health Indicators**:
- ✅ Successfully parsing diverse input formats
- ✅ Zero loss of design information
- ✅ Fast processing time
- ❌ Failed parsing = maldigestion
- ❌ Lost data = nutrient malabsorption
- ❌ Slow processing = digestive dysfunction
**Design Principles**:
- **Format Agnostic**: Support CSS, SCSS, JSON, Figma, etc.
- **Zero Data Loss**: Never drop design information
- **Normalization**: Convert to standard token format immediately
- **Error Recovery**: Partial failures don't block entire ingestion
**Reference**: `/docs/DSS_ORGANISM_GUIDE.md#3-the-digestive-system`
### 3.4 The Nervous System 🔌 - APIs & Webhooks
**Function**: Perceive external world and respond automatically
**Neural Pathways**:
- **Sensory Input** = Figma webhooks detecting changes
- **Response** = Automatic sync and update triggers
- **Communication** = REST API, MCP interface
**Health Indicators**:
- ✅ Real-time responsiveness to Figma changes
- ✅ Reliable webhook delivery
- ✅ Available API endpoints
- ❌ Missed webhook events = delayed sync
- ❌ API downtime = external systems blocked
- ❌ Race conditions = data corruption
**Design Principles**:
- **Real-Time**: Respond to changes immediately
- **Reliable**: Guarantee event delivery (retries, idempotency)
- **Available**: 99.9% uptime for APIs
- **Observable**: Log all external interactions
**Reference**: `/docs/DSS_ORGANISM_GUIDE.md#4-the-nervous-system`
### 3.5 The Circulatory System 🩸 - Token Distribution
**Function**: Distribute tokens throughout the system to where they're needed
**Distribution Network**:
- Token → CSS Variables
- Token → Storybook Documentation
- Token → Component Generation
- Token → External Integrations
**Design Principles**:
- **Consistency**: Same token everywhere
- **Traceability**: Know where each token goes
- **Performance**: Efficient distribution, caching
- **Flexibility**: Multiple output formats
**Reference**: `/docs/DSS_ORGANISM_GUIDE.md` (distributed throughout docs)
---
## 4. Keyboard Accessibility
All interactive elements must be keyboard accessible. Users should be able to navigate and interact with the entire application using only the keyboard.
### Guidelines
- **Tabindex Management**
- Use `tabindex="0"` on all keyboard-accessible elements (buttons, links, inputs, custom components)
- Use `tabindex="-1"` for elements that shouldn't be in the tab order but need programmatic focus
- Never use positive tabindex values (e.g., `tabindex="1"`) - maintain natural DOM order
- **Focus Styling**
- Always implement `:focus-visible` CSS for keyboard users
- Ensure 3:1 contrast ratio for focus indicators
- Use outline or box-shadow, not display/visibility changes
- Apply consistently across all interactive elements
- **Keyboard Event Handlers**
- **Enter/Space**: Activate buttons and toggles
- **Escape**: Close modals, sidebars, and collapsible panels
- **Arrow Keys**: Navigate lists, tabs, and menus
- **Alt+Key**: Power user shortcuts for common actions
### Web Component Implementation
```javascript
class MyButton extends HTMLElement {
static get observedAttributes() {
return ['disabled', 'tabindex', 'aria-label', 'aria-expanded'];
}
setupEventListeners() {
// Handle Enter/Space for activation
this.keydownHandler = (e) => {
if ((e.key === 'Enter' || e.key === ' ') && !this.disabled) {
e.preventDefault();
this.shadowRoot.querySelector('button').click();
}
};
this.addEventListener('keydown', this.keydownHandler);
}
render() {
const tabindex = this.disabled ? '-1' : (this.getAttribute('tabindex') || '0');
// ... delegate tabindex to internal button
}
disconnectedCallback() {
this.removeEventListener('keydown', this.keydownHandler);
}
}
```
**Reference**: `/admin-ui/js/components/ds-button.js:79-96`
---
## 2. ARIA & Screen Reader Support
Screen reader users need semantic information about UI elements, their state, and purpose.
### Guidelines
- **Labeling**
- Always use `aria-label` on icon-only buttons
- Use `aria-label` on elements without visible text
- Example: `<button aria-label="Toggle theme">🌙</button>`
- **State Indication**
- Use `aria-expanded="true|false"` for toggles/collapsible elements
- Use `aria-pressed="true|false"` for toggle buttons
- Use `aria-invalid="true"` on form fields with errors
- Update ARIA attributes when state changes
- **Relationships**
- Use `aria-controls="id"` to link controls to their targets
- Use `aria-describedby="id"` to link inputs to error messages
- Use `aria-labelledby="id"` to link to headings when appropriate
- Use `aria-hidden="true"` on decorative elements (SVGs, icons)
- **Semantic Roles**
- Use native HTML elements when possible (button, input, link)
- Use `role="button"` only on divs styled as buttons (not ideal)
- Use `role="alert"` on error messages that appear dynamically
- Always prefer semantic HTML over generic divs
- **Error Handling**
- Generate unique IDs for error messages
- Link errors to inputs: `aria-describedby="error-{id}"`
- Use `role="alert"` so screen readers announce errors
- Set `aria-invalid="true"` on the input element
### Web Component Implementation
```javascript
class MyInput extends HTMLElement {
static get observedAttributes() {
return ['aria-label', 'aria-invalid', 'aria-describedby', 'error'];
}
render() {
const hasError = !!this.getAttribute('error');
const errorId = hasError ? `error-${Math.random().toString(36).substr(2, 9)}` : '';
const ariaInvalid = hasError ? 'aria-invalid="true"' : '';
const ariaDescribedBy = hasError ? `aria-describedby="${errorId}"` : '';
const ariaLabel = this.getAttribute('aria-label') || this.label || '';
this.shadowRoot.innerHTML = `
<input
aria-label="${ariaLabel}"
${ariaInvalid}
${ariaDescribedBy}
/>
${hasError ? `<p id="${errorId}" role="alert">${this.getAttribute('error')}</p>` : ''}
`;
}
}
```
**Reference**: `/admin-ui/js/components/ds-input.js:172-240`
---
## 3. Web Component Lifecycle Management
Memory leaks from accumulated event listeners are a critical performance issue in SPAs. Web Components must properly manage their lifecycle.
### Guidelines
- **Connection/Disconnection**
- Implement both `connectedCallback()` and `disconnectedCallback()`
- `connectedCallback()`: Create shadow DOM, render, attach listeners
- `disconnectedCallback()`: Remove all listeners, clean up references
- **Event Listener Storage**
- Store listener references on `this` for later cleanup
- Never attach anonymous functions without storing references
- Example: `this.clickHandler = (e) => { ... }`
- Later: `element.removeEventListener('click', this.clickHandler)`
- **Attribute Observation**
- Implement `observedAttributes()` static getter
- Include all attributes that affect rendering: `disabled`, `tabindex`, ARIA attributes
- In `attributeChangedCallback()`, cleanup old listeners before re-rendering
### Implementation Pattern
```javascript
class MyComponent extends HTMLElement {
static get observedAttributes() {
return ['disabled', 'tabindex', 'aria-label'];
}
connectedCallback() {
this.render();
this.setupEventListeners();
}
disconnectedCallback() {
this.cleanupEventListeners();
}
setupEventListeners() {
// Store references
this.clickHandler = (e) => { /* ... */ };
this.focusHandler = (e) => { /* ... */ };
const button = this.shadowRoot.querySelector('button');
button.addEventListener('click', this.clickHandler);
this.addEventListener('focus', this.focusHandler);
}
cleanupEventListeners() {
const button = this.shadowRoot?.querySelector('button');
if (button && this.clickHandler) {
button.removeEventListener('click', this.clickHandler);
delete this.clickHandler;
}
if (this.focusHandler) {
this.removeEventListener('focus', this.focusHandler);
delete this.focusHandler;
}
}
}
```
**Reference**: `/admin-ui/js/components/ds-button.js:27-113`
---
## 4. Event Delegation & Listener Accumulation Prevention
High-volume event listeners create memory pressure. Use event delegation and guard flags.
### Guidelines
- **Use Document-Level Delegation**
- Instead of: `buttons.forEach(b => b.addEventListener('click', handler))`
- Do: `document.addEventListener('click', (e) => { const btn = e.target.closest('[data-action]'); ... })`
- Benefit: One listener for N elements, regardless of count
- **Guard Flags**
- Prevent re-attachment on re-renders
- Check flag before attaching: `if (!this.listeners.hasActionListener) { ... }`
- Set flag after attachment: `this.listeners.hasActionListener = true;`
- **Data-Driven Actions**
- Use `data-action` attributes instead of inline onclick handlers
- Router actions through a single switch statement
- Example: `<button data-action="toggle-theme">Toggle</button>`
### Implementation Pattern
```javascript
attachEventHandlers() {
// Guard: only attach once, even if called multiple times
if (!this.listeners.hasActionListener) {
document.addEventListener('click', (e) => {
const btn = e.target.closest('[data-action]');
if (!btn) return;
const action = btn.dataset.action;
switch (action) {
case 'toggle-theme': this.toggleTheme(); break;
case 'load-audit': this.loadAuditLog(); break;
// ... more actions
}
});
this.listeners.hasActionListener = true;
}
}
```
**Reference**: `/admin-ui/js/core/app.js:2202-2414`
---
## 5. Security: No Global State Pollution
Never expose critical classes or functions to `window`. Always use ES6 module imports.
### Guidelines
- **No Window Assignments**
-`window.app = app;`
-`window.themeManager = themeManager;`
- ✅ Use: `import app from './core/app.js';`
- **Risk Mitigation**
- Malicious/poorly-written third-party scripts can't hijack your code
- Prevents accidental global namespace pollution
- Makes code dependencies explicit and traceable
- **Development Debugging**
- If debugging requires window access, check environment first
- Example: Only expose in development mode
- Use: `if (process.env.NODE_ENV === 'development') { window.debug = {...}; }`
### Implementation
```javascript
// ❌ DON'T DO THIS
const app = new App();
window.app = app;
// ✅ DO THIS
const app = new App();
export default app;
// In other files:
import app from './app.js';
```
**Reference**: `/admin-ui/js/core/app.js` (removed window exposure), `/admin-ui/index.html:750`
---
## 6. Security: Sanitize HTML Input
Always sanitize HTML before insertion into the DOM. Use DOMPurify.
### Guidelines
- **Never Use Unsafe Insertion**
-`element.innerHTML = userInput;`
-`element.innerHTML = apiResponse;`
- ✅ Use: `sanitizeHtml()` and `setSafeHtml()`
- **DOMPurify Configuration**
- Default settings block dangerous attributes (onclick, onerror, etc.)
- Whitelist only necessary tags and attributes
- Strip scripts while preserving content
- **Content Sources Requiring Sanitization**
- User input (forms, search, comments)
- API responses (markdown, rich text, HTML)
- External data (imported content, integrations)
### Implementation
```javascript
import { setSafeHtml, sanitizeHtml } from './sanitizer.js';
// Safe HTML insertion
const htmlContent = `<h2>${name}</h2><p>${description}</p>`;
setSafeHtml(element, htmlContent);
// Sanitize and retrieve
const clean = sanitizeHtml(userInput);
```
**Reference**: `/admin-ui/js/core/sanitizer.js`, `/admin-ui/js/core/app.js:28`
---
## 7. Non-Invasive Network Monitoring
Never monkey-patch native APIs. Use non-invasive alternatives.
### Guidelines
- **Don't Monkey-Patch Global Functions**
-`window.fetch = async (...) => { ... }`
- ❌ Breaks third-party integrations
- ❌ Causes race conditions
- **Use Platform APIs Instead**
-`PerformanceObserver` for network monitoring
- ✅ Browser Performance API for metrics
- ✅ Event listeners on `window` for errors
- **Graceful Degradation**
- Check if API is available: `if ('PerformanceObserver' in window)`
- Try/catch for unsupported browsers
- Continue functionality if monitoring unavailable
### Implementation
```javascript
captureNetworkActivity() {
if ('PerformanceObserver' in window) {
try {
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.initiatorType === 'fetch' || entry.initiatorType === 'xmlhttprequest') {
this.log('network', entry.initiatorType, `${entry.name}`, {
duration: entry.duration,
transferSize: entry.transferSize
});
}
}
});
observer.observe({ entryTypes: ['resource'] });
} catch (e) {
// Graceful degradation - network logging won't work
}
}
}
```
**Reference**: `/admin-ui/js/core/browser-logger.js:134-162`
---
## 8. Focus Management
Maintain user's context by managing focus properly during UI updates.
### Guidelines
- **Focus Delegation**
- Web Components should delegate focus to internal focusable element
- Implement focus() method that focuses internal input/button
- **Focus Restoration**
- Store focused element before UI change
- Restore focus after update if appropriate
- Announce focus changes to screen readers
- **Aria-Expanded Updates**
- Update `aria-expanded` when toggles change state
- Ensures screen readers announce state changes
- Example: `toggleBtn.setAttribute('aria-expanded', isOpen);`
### Implementation
```javascript
class MyComponent extends HTMLElement {
focus() {
// Delegate focus to internal input
this.shadowRoot.querySelector('input')?.focus();
}
togglePanel() {
const isOpen = !this.isOpen;
this.isOpen = isOpen;
// Update ARIA state
this.setAttribute('aria-expanded', isOpen);
// Restore focus to toggle button after panel opens
if (isOpen) {
this.focus();
}
}
}
```
**Reference**: `/admin-ui/js/core/app.js:2495-2502`
---
## 9. Semantic HTML Over Custom Divs
Use native HTML elements. They provide built-in accessibility.
### Guidelines
- **Prefer Native Elements**
-`<button>` instead of `<div role="button">`
-`<input>` instead of `<div contenteditable>`
-`<select>` instead of custom dropdown
-`<label>` instead of span with onclick
- **When Custom Elements Are Necessary**
- Implement proper ARIA roles and attributes
- Ensure keyboard interaction works identically to native
- Test with screen readers and keyboard-only navigation
- **Benefits of Native HTML**
- Built-in keyboard support
- Screen reader integration
- Mobile device handling
- Browser compatibility
- User expectations met
---
## 10. Observable Attributes for Web Components
Web Components must expose all relevant attributes in `observedAttributes()` to respond to changes.
### Guidelines
- **Include All State Attributes**
- `disabled`, `aria-label`, `aria-expanded`, `aria-pressed`
- `tabindex`, `value`, `error`, `variant`
- Any attribute that affects rendering or behavior
- **Cleanup in attributeChangedCallback**
- Remove old listeners before re-rendering
- Call `cleanupEventListeners()` first
- Then call `render()` and `setupEventListeners()`
- **Re-render Efficiently**
- Only re-render if shadowRoot has content
- Check `if (this.shadowRoot.innerHTML)`
- Avoid re-rendering on initial connection
### Implementation
```javascript
class MyComponent extends HTMLElement {
static get observedAttributes() {
// Include ALL attributes that affect rendering
return ['disabled', 'tabindex', 'aria-label', 'aria-expanded', 'aria-invalid', 'error'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (this.shadowRoot.innerHTML && oldValue !== newValue) {
// Cleanup first
this.cleanupEventListeners();
// Then re-render
this.render();
this.setupEventListeners();
}
}
}
```
**Reference**: `/admin-ui/js/components/ds-input.js:39-52`
---
## 11. Logging with Organism Awareness
Use structured logging that helps understand system state and consciousness.
### Guidelines
- **Log Categories** (Organ Systems)
- `'heart'` - Database operations and data persistence
- `'brain'` - Validation, analysis, and decision making
- `'nervous'` - API calls, webhooks, communication
- `'digestive'` - Data ingestion, parsing, transformation
- `'endocrine'` - Theme system and configuration
- `'immune'` - Validation, error detection, security
- **Log Levels**
- `DEBUG` - Deep thought, internal analysis
- `INFO` - Organism awareness, normal operations
- `WARN` - Symptom detection, unusual conditions
- `ERROR` - Immune alert, critical threats
- **Structure**
- Always include: timestamp, level, category, message, data
- Use consistent naming for categories
- Include relevant IDs (user, session, operation)
**Reference**: `/admin-ui/js/core/logger.js:27-152`
---
## 12. Error Handling & User Feedback
Provide clear feedback for errors while maintaining security.
### Guidelines
- **User-Facing Messages**
- Be specific but not technical: "Unable to save changes" not "500 Internal Server Error"
- Suggest action: "Please try again" or "Contact support"
- Announce errors to screen readers with `role="alert"`
- **Internal Logging**
- Log full error details internally for debugging
- Include stack traces, request data, timestamps
- Never expose sensitive information to users
- **Notification Timing**
- Success: 3-5 seconds
- Warnings: 5-7 seconds
- Errors: Persistent until user dismisses
**Reference**: `/admin-ui/js/core/messaging.js`
---
## Summary: Accessibility Checklist
Before shipping a component, verify:
- [ ] All interactive elements have `tabindex="0"` or semantic focus
- [ ] All icon buttons have `aria-label`
- [ ] All toggles/collapsibles have `aria-expanded`
- [ ] All form errors have `aria-invalid` and `aria-describedby`
- [ ] `:focus-visible` CSS is present for keyboard users
- [ ] Keyboard shortcuts work (Enter, Space, Escape, Arrows)
- [ ] `disconnectedCallback()` removes all event listeners
- [ ] Event listeners are stored as `this.handler` for cleanup
- [ ] No HTML is inserted via `innerHTML` without sanitization
- [ ] No functions/classes exposed to `window`
- [ ] Decorative SVGs have `aria-hidden="true"`
- [ ] Error messages have `role="alert"`
- [ ] Uses semantic HTML where possible
- [ ] Works with keyboard-only navigation
- [ ] Works with screen readers (test with NVDA or JAWS)
---
## References
- [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
- [ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/)
- [Web Components Best Practices](https://web.dev/articles/custom-elements-best-practices)
- [Focus Management](https://www.smashingmagazine.com/2019/06/focus-management-keyboard-navigation/)
- [DOMPurify Documentation](https://github.com/cure53/DOMPurify)