Components Overview
Inglorious Web comes with several built-in, entity-based components for common UI patterns. Each is fully customizable and testable.
Philosophy
Unlike framework components that hide internals and force props, Inglorious Web components are entity types with customizable behavior.
This means:
- Transparent — You can see exactly how they work
- Customizable — Override any method or behavior
- Composable — Mix with other types through type composition
- Testable — Test with simple
trigger()calls, no special setup
#title: Components Overview description: Introduction to built-in components and integration options
Built-in Components
Router
Client-side routing that integrates directly with your store.
- Hash-based or path-based routing
- URL sync with entity state
- Lazy-loadable routes
- Type composition for route guards (auth, permissions)
Form
Declarative form state management with validation.
- Field state tracking (value, error, touched)
- Array field support (add/remove/reorder)
- Sync and async validation
- Form-level submission handling
Table
Flexible table component for displaying data.
- Sortable columns
- Customizable cell rendering
- Row selection
- Themeable with CSS
Select
Dropdown with single/multi-select, search, and keyboard nav.
- Single and multi-select modes
- Searchable options
- Keyboard navigation (arrow keys, enter, escape)
- Custom option rendering
Virtual List
Efficient rendering of large lists with virtualization.
- Renders only visible items
- Configurable item height
- Automatic height measurement
- Smooth scrolling with buffering
Using Built-in Components
Basic Setup
import { createStore, mount, html } from "@inglorious/web"
import { form } from "@inglorious/web/form"
import { table } from "@inglorious/web/table"
const types = {
form,
table,
// ... your types
}
const entities = {
form: {
type: "form",
initialValues: { email: "", password: "" },
},
table: {
type: "table",
data: [
/* ... */
],
columns: [
/* ... */
],
},
}
const store = createStore({ types, entities })
mount(
store,
(api) => html` ${api.render("form")} ${api.render("table")} `,
document.getElementById("root"),
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Customizing Components
Override any method:
import { form } from "@inglorious/web/form"
const customForm = {
...form,
// Override validation
validate(entity, schema) {
// Custom validation logic
},
// Override submission
submit(entity, api) {
// Custom submit logic
},
// Override rendering
render(entity, api) {
// Custom form layout
},
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Composing with Behaviors
Add logging, analytics, or guards:
const logging = (type) => ({
fieldChange(entity, payload, api) {
console.log("Field changed:", payload)
type.fieldChange?.(entity, payload, api)
},
})
const types = {
form: [form, logging],
}
2
3
4
5
6
7
8
9
10
When to Use Built-in Components
✅ Use them if:
- You need that specific functionality (form, table, router, etc.)
- You want store-integrated, predictable behavior
- You want simple, pure-function testing
- You want to avoid external dependencies
❌ Consider alternatives if:
- You need complex features (like calendar, date picker)
- You need framework-agnostic components
- You want a design system out of the box
Integration with Third-Party UI
Inglorious Web plays nicely with:
- Web Components — Shoelace, Material Web Components, etc.
- Design Systems — Any CSS framework
- Specialized Libraries — Date pickers, rich editors, etc.
- Data Grids — AG Grid can be integrated directly (no adapter required)
Learn more →AG Grid recipe (no adapter) →
Ecosystem Packages
The Inglorious ecosystem also includes:
- Inglorious Motion — animation primitives for Inglorious Web entities
Docs: https://inglorious.dev/motion/ - Inglorious Charts — declarative chart types and chart composition helpers
Docs: https://inglorious.dev/charts/
Advanced Customization
All built-in components use type composition. This means you can:
- Extend them — Add your own event handlers
- Compose them — Mix with guard behaviors
- Override them — Replace any method completely
- Test them — With simple
trigger()calls
Example: Form with custom validation:
const customForm = {
...form,
validate(entity, schema) {
// Custom validation logic
const errors = {}
if (entity.values.email && !entity.values.email.includes("@")) {
errors.email = "Invalid email"
}
return errors
},
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Testing Components
Testing is straightforward with trigger():
import { form } from "@inglorious/web/form"
import { trigger } from "@inglorious/web/test"
test("form sets field value", () => {
const { entity } = trigger(
{ type: "form", initialValues: { name: "" }, values: { name: "" } },
form.fieldChange,
{ path: "name", value: "Alice" },
)
expect(entity.values.name).toBe("Alice")
})
2
3
4
5
6
7
8
9
10
11
12
Component-Specific Features
Each component has unique features. Dive into the specific docs:
- Router — URL routing with guards
- Form — Validation, array fields, submission
- Table — Sorting, custom rendering
- Select — Multi-select, search, keyboard nav
- List — Virtual scrolling for large datasets
Next Steps
- Pick a component and read its documentation
- Explore integration options: JSX, Vue Templates, Web Components
- Build something! 🚀
Inglorious Web