DuskMoon Elements
43 custom element packages built on @duskmoon-dev/el-base. Each element is a standard Web Component with Shadow DOM.
Installation
# Individual element
bun add @duskmoon-dev/el-button
# All elements at once
bun add @duskmoon-dev/elementsRegistration
// Option 1: Explicit (tree-shakable)
import { register } from '@duskmoon-dev/el-button';
register();
// Option 2: Side-effect auto-register
import '@duskmoon-dev/el-button/register';
// Option 3: Register all elements
import { registerAll } from '@duskmoon-dev/elements';
registerAll();Usage in HTML
<el-dm-button variant="filled" color="primary" size="md">
Click me
</el-dm-button>
<el-dm-dialog id="my-dialog">
<span slot="header">Title</span>
Dialog content here.
<div slot="footer">
<el-dm-button onclick="this.closest('el-dm-dialog').hide()">Close</el-dm-button>
</div>
</el-dm-dialog>Properties & Attributes
Set via HTML attributes (kebab-case) or JS properties (camelCase). Properties with reflect: true sync both directions.
<!-- HTML attributes -->
<el-dm-button variant="outlined" disabled>Save</el-dm-button>
<!-- JS properties -->
<script>
const btn = document.querySelector('el-dm-button');
btn.variant = 'outlined';
btn.disabled = true;
</script>Common properties across elements:
| Property | Type | Description |
|---|---|---|
variant | String | Visual variant (filled, outlined, soft, text, ghost) |
color | String | Color theme (primary, secondary, success, warning, error, info) |
size | String | Size (sm, md, lg) |
disabled | Boolean | Disable interaction |
Complex data (arrays, objects) must be set via JS — use attribute: false:
const table = document.querySelector('el-dm-table');
table.columns = [{ field: 'name', header: 'Name' }];
table.data = [{ name: 'Alice' }, { name: 'Bob' }];Events
Listen with addEventListener. Events bubble and are composed (cross shadow DOM).
const table = document.querySelector('el-dm-table');
table.addEventListener('sort', (e) => {
console.log(e.detail); // { column: 'name', direction: 'asc' }
});
table.addEventListener('row-click', (e) => {
console.log(e.detail); // { row: {...}, rowIndex: 0 }
});Common events:
| Element | Event | Detail |
|---|---|---|
| dialog | open, close | — |
| table | sort | {column, direction} |
| table | select | {selectedIds, selectedRows} |
| table | page-change | {page, pageSize} |
| pagination | page-change | {page} |
| tabs | tab-change | {index, tab} |
| input | dm-input, dm-change | {value} |
Slots
Named slots project light DOM content into the element's shadow DOM.
<el-dm-button>
<span slot="prefix">🔍</span>
Search
<span slot="suffix">→</span>
</el-dm-button>
<el-dm-card>
<span slot="header">Card Title</span>
Card body content
<div slot="footer">Footer</div>
</el-dm-card>Common slots: (default), header, footer, prefix, suffix, empty, actions.
CSS Parts
Style shadow DOM internals from outside using ::part():
el-dm-button::part(button) {
border-radius: 0;
}
el-dm-dialog::part(backdrop) {
backdrop-filter: blur(4px);
}
el-dm-table::part(thead) {
background: var(--color-surface-container-high);
}Theming
Elements use CSS custom properties from @duskmoon-dev/el-base. Apply a preset theme:
import { applyTheme } from '@duskmoon-dev/el-base';
applyTheme(document.documentElement, 'moonlight'); // dark
applyTheme(document.documentElement, 'sunshine'); // light
// Also: 'ocean', 'forest', 'rose'Override individual variables:
:root {
--color-primary: oklch(60% 0.15 250);
--color-surface: #ffffff;
}Key variables: --color-primary, --color-surface, --color-on-surface, --color-outline, --color-surface-container.
See references/core-api.md for full CSS variable list.
Batched Rendering
Property changes are batched via queueMicrotask. Multiple changes in the same tick produce a single re-render:
const el = document.querySelector('el-dm-button');
el.variant = 'outlined';
el.color = 'error';
el.size = 'lg';
// → single re-renderReferences
- Element catalog — all 43 packages by category with class names
- Core API — BaseElement API, mixins, style utilities, CSS variables, themes, validation
For CSS art elements (<el-dm-art-*>), see the duskmoon-art-elements skill.