Complete guide to SaladUI's JavaScript component system documentation.
Quick Start
New to SaladUI JavaScript components? Start here:
- Architecture Overview - Understand the big picture
- Simple Component Guide - Build your first component
- Complex Component Guide - Add interactivity
- Component Patterns - Learn best practices
Documentation Structure
Core Concepts
JavaScript Architecture Overview
Comprehensive overview of the JavaScript architecture and how it integrates with Phoenix LiveView.
Topics:
- Architecture overview and diagrams
- Core system components (Component, StateMachine, Registry, Hook)
- Data flow patterns (server-to-client, client-to-server, client-to-client)
- Component lifecycle (initialization, updates, destruction)
- Integration with Phoenix LiveView
- Best practices and advanced topics
Read this if:
- You're new to SaladUI's JavaScript architecture
- You want to understand how components work under the hood
- You need to debug component behavior
- You're designing new components
Component Lifecycle
The authoritative reference for Component's mount → transition → update →
destroy lifecycle, and the extension-hook contract subclasses must follow.
Topics:
- Mount phase (construction,
setupEvents(),afterMount()) - Runtime state transitions (pointer to State Machine Flow)
- Update flow (LiveView patch destroys and recreates the instance)
- Destroy flow (
beforeDestroy(),removeAllEvents(),teardownComponentEvents()) - Extension hook reference table
- Rules — and the real bug each one prevents
- Worked
DialogComponentexample - Common pitfalls (a leaked
documentlistener, explained end-to-end)
Read this if:
- You're overriding
setupComponentEvents(),afterMount(), orbeforeDestroy() - You're adding a listener or utility (monitor, trap, observer) that outlives a single event
- You're debugging a listener/memory leak
- You want to know exactly when a given hook runs and what's safe to assume at that point
State Machine Flow
Visual diagrams showing state transition execution flow with and without animations.
Topics:
- Transition flow without animation
- Transition flow with animation
- Timing of visibility updates
Read this if:
- You need to understand transition timing
- You're implementing animations
- You're debugging state transition issues
Implementation Guides
Simple Component Guide
Quick guide for creating simple, non-interactive components.
Topics:
- 4-step component creation process
- Elixir component setup
- JavaScript component basics
- Chart component example
- Key requirements checklist
Read this if:
- You're creating a new simple component
- You need a quick reference
- You're wrapping a third-party library (Chart.js example)
Complex Component Guide
Guide for creating complex components with multiple parts, states, and interactions.
Topics:
- Multi-part component structure
- State machine patterns
- Event handling (mouse, keyboard)
- Visibility control
- ARIA configuration
- Common complex patterns (dialogs, dropdowns, tabs, accordions)
Read this if:
- You're building an interactive component
- You need multiple states and transitions
- You need keyboard navigation
- You need accessibility features
Component Configuration Guide
Complete reference for the configuration object returned by getComponentConfig().
Topics:
- State machine configuration structure
- Events configuration (mouseMap, keyMap)
- Hidden configuration for visibility control
- ARIA configuration for accessibility
- Complete examples
Read this if:
- You need detailed config reference
- You're defining state machines
- You're setting up event handlers
- You're configuring ARIA attributes
Best Practices
Component Patterns
Collection of common patterns, best practices, and solutions for building components.
Topics:
- Component structure patterns
- State management patterns (binary, multi-state, conditional)
- Event handling patterns (mouse, keyboard, debouncing)
- Accessibility patterns (dialog, menu, select, tabs)
- Integration patterns (commands, events, options)
- Common component types (toggle, overlay, collection)
Read this if:
- You're looking for proven solutions
- You need patterns for specific scenarios
- You want to improve component quality
- You're implementing accessibility features
Communication
Component Communications Guide
Explains how communication works between different parts of the system.
Topics:
- Client → Server communication (events)
- Server → Client communication (commands)
- Client → Client communication (direct commands)
- Event mapping configuration
- Phoenix.LiveView.JS usage
- When to use each pattern
Read this if:
- You need to send data to the server
- You need to control components from LiveView
- You need component-to-component communication
- You're confused about communication patterns
Reference
Component Reference
Quick reference for all JavaScript components and their APIs.
Topics:
- Core classes (Component, StateMachine, Registry, Hook)
- All interactive components with:
- States
- Options
- Events
- Parts
- Keyboard shortcuts
- ARIA roles
- Special features
- Utility classes (FocusTrap, ClickOutsideMonitor)
- Common patterns and code snippets
- Testing and debugging
- Performance tips
Read this if:
- You need a quick API reference
- You're looking for specific component details
- You need keyboard shortcut reference
- You need debugging tips
Learning Paths
Path 1: Beginner (Creating Your First Component)
- Read: Architecture Overview - Sections: "Architecture Overview" and "Core System Components"
- Read: Simple Component Guide
- Build: Create a simple display component (chart, badge, avatar)
- Read: Component Communications Guide
- Practice: Add server communication to your component
Path 2: Intermediate (Building Interactive Components)
- Read: Architecture Overview - Complete
- Read: Complex Component Guide
- Read: Component Configuration Guide
- Build: Create a toggle, dropdown, or accordion
- Read: Component Patterns - State and Event sections
- Practice: Add keyboard navigation and ARIA
Path 3: Advanced (Mastering Component Development)
- Read: Component Patterns - Complete
- Study: Existing component implementations in
assets/salad_ui/components/ - Read: State Machine Flow
- Build: Complex component with animations (dialog, sheet, popover)
- Read: Component Reference - Testing and Performance sections
- Practice: Optimize and test your components
Path 4: Debugging and Troubleshooting
- Read: Component Lifecycle - Complete
- Read: Component Reference - "Testing" and "Common Pitfalls" sections
- Review: Component Communications Guide
- Check: Component Configuration Guide for config issues
Common Questions
How do I...?
Create a new component?
→ See Simple Component Guide or Complex Component Guide
Send data to the server?
→ See Component Communications Guide - "Client → Server Communication"
Control a component from LiveView?
→ See Component Communications Guide - "Server → Client Communication"
Add keyboard navigation?
→ See Component Patterns - "Keyboard Navigation Pattern"
Make my component accessible?
→ See Component Patterns - "Accessibility Patterns"
Handle state transitions?
→ See Component Configuration Guide - "State Machine Configuration"
Debug component issues?
→ See Component Reference - "Testing Components"
Clean up resources?
→ See Component Patterns - "Component with External Dependencies"
Add animations?
→ See Architecture Overview - "Animation Integration"
Handle multiple instances?
→ See Architecture Overview - "Multi-Instance Components"
Code Examples
Minimal Component
import Component from "../core/component";
import SaladUI from "../index";
class MinimalComponent extends Component {
getComponentConfig() {
return {
stateMachine: {
idle: { transitions: {} }
}
};
}
}
SaladUI.register("minimal", MinimalComponent);Toggle Component
class ToggleComponent extends Component {
constructor(el, hookContext) {
super(el, { hookContext, initialState: "off" });
}
getComponentConfig() {
return {
stateMachine: {
off: {
enter: "onOffEnter",
transitions: { toggle: "on" }
},
on: {
enter: "onOnEnter",
transitions: { toggle: "off" }
}
},
events: {
_all: {
mouseMap: {
root: { click: "toggle" }
},
keyMap: {
" ": "toggle"
}
}
},
ariaConfig: {
root: {
all: { role: "switch" },
on: { checked: "true" },
off: { checked: "false" }
}
}
};
}
onOnEnter() {
this.pushEvent("toggled", { value: true });
}
onOffEnter() {
this.pushEvent("toggled", { value: false });
}
}Dialog Component
import FocusTrap from "../core/focus-trap";
class DialogComponent extends Component {
constructor(el, hookContext) {
super(el, { hookContext, initialState: "closed" });
this.contentPanel = this.getPart("content-panel");
this.config.preventDefaultKeys = ["Escape"];
}
getComponentConfig() {
return {
stateMachine: {
closed: {
enter: "onClosedEnter",
transitions: { open: "open" }
},
open: {
enter: "onOpenEnter",
transitions: { close: "closed" }
}
},
events: {
closed: {
mouseMap: {
trigger: { click: "open" }
}
},
open: {
keyMap: { Escape: "close" }
}
},
hiddenConfig: {
closed: { content: true },
open: { content: false }
},
ariaConfig: {
trigger: {
all: { haspopup: "dialog" },
open: { expanded: "true" },
closed: { expanded: "false" }
},
content: {
all: { role: "dialog", modal: "true" }
}
}
};
}
onOpenEnter() {
if (!this.focusTrap) {
this.focusTrap = new FocusTrap(this.contentPanel);
}
this.focusTrap.activate();
this.pushEvent("open");
}
onClosedEnter() {
this.focusTrap?.deactivate();
this.pushEvent("close");
}
beforeDestroy() {
this.focusTrap?.destroy();
}
}File Locations
assets/salad_ui/
├── index.js # Main export
├── core/ # See core/README.md for the full file-by-file breakdown
│ ├── README.md # Core module overview
│ ├── component.js # Base Component class
│ ├── state-machine.js # State machine
│ ├── hook.js # LiveView hook
│ ├── factory.js # Registry & factory
│ ├── utils.js # Animation/class/DOM utilities
│ ├── collection.js # Selectable/focusable item collection
│ ├── focus-trap.js # Focus trap utility
│ ├── click-outside.js # Click outside monitor
│ ├── portal.js # DOM re-parenting utility
│ ├── positioner.js # Floating-element position math
│ ├── positioned-element.js # Popover/select/tooltip positioning
│ └── scroll-manager.js # Scroll/resize repositioning
└── components/
├── accordion.js
├── chart.js
├── collapsible.js
├── command.js
├── dialog.js
├── dropdown_menu.js
├── hover-card.js
├── menu.js
├── popover.js
├── radio_group.js
├── select.js
├── slider.js
├── switch.js
├── tabs.js
└── tooltip.js
docs/
├── js_documentation_index.md # This file
├── js_architecture_overview.md # Architecture guide
├── component_lifecycle.md # Component lifecycle reference
├── js_component_patterns.md # Patterns & best practices
├── js_component_reference.md # API reference
├── js_state_transition_flow.md # State transition diagrams
├── implement_simple_component.md # Simple component guide
├── complex_component_guide.md # Complex component guide
├── component_config_guide.md # Config reference
└── component_communications_explain.md # Communication guideContributing
When adding new components or patterns, please:
- Add component to Component Reference
- Document new patterns in Component Patterns
- Add examples to relevant guides
- Update this index if adding new documentation files
Getting Help
- Search this documentation for your specific question
- Review component implementations in
assets/salad_ui/components/ - Check the Common Pitfalls section
- Use the storybook app to test components:
cd storybook && mix phx.server - Open an issue on GitHub with your question
Related Documentation
- CLAUDE.md - Overview for AI assistants
- README.md - Project overview and installation
- Elixir Component Docs - Server-side component documentation
- Phoenix LiveView Hooks Documentation
Last Updated: November 2024 Version: 1.0.0-beta.3