When to Use
Model
@universityofmaryland/web-model-library -- Use when building custom web components that follow UMD patterns. Provides attribute parsing, slot management, registration, and lifecycle hooks.
Builder
@universityofmaryland/web-builder-library -- Use when constructing DOM elements with a fluent API. Provides ElementBuilder for building complex element trees with automatic style management.
Model Package Overview
The model package exports 5 main modules:
import { Attributes, Model, Register, Slots, Lifecycle } from '@universityofmaryland/web-model-library';
| Module | Purpose |
|---|---|
Attributes |
Parse and validate HTML attributes (data-*, boolean, enum) |
Model |
Core web component model with Shadow DOM management |
Register |
Register custom elements with the browser |
Slots |
Manage slot content distribution and validation |
Lifecycle |
Connected/disconnected callbacks, attribute change handling |
SlotProps, BaseProps, OptionalProps, SlotResult
Building a Custom Web Component
Full example showing how to create a custom component using the Model package:
import { Attributes, Model, Register, Slots, Lifecycle } from '@universityofmaryland/web-model-library';
import { Composite } from '@universityofmaryland/web-elements-library/composite';
const ELEMENT_TAG = 'umd-custom-feature-card';
const SLOTS = {
headline: { required: true },
text: { required: false },
image: { required: false },
};
const ATTRIBUTES = {
THEME: 'data-theme',
DISPLAY: 'data-display',
};
const createComponent = (element: HTMLElement) => {
// Parse attributes
const theme = Attributes.getValue(element, ATTRIBUTES.THEME) || 'light';
const isThemeDark = theme === 'dark';
// Get slot content
const headline = Slots.getSlot(element, 'headline');
const text = Slots.getSlot(element, 'text');
const image = Slots.getSlot(element, 'image');
// Use elements library to build the UI
const card = Composite.card.standard({
headline: headline?.textContent || '',
text: text?.textContent,
isThemeDark,
});
return card; // Returns { element, styles }
};
// Register the web component
const registration = () => {
Register.define(ELEMENT_TAG, {
slots: SLOTS,
createComponent,
});
};
export { registration };
Usage in HTML
<umd-custom-feature-card data-theme="dark">
<h2 slot="headline">Custom Feature</h2>
<p slot="text">Built with the model and elements packages.</p>
</umd-custom-feature-card>
Builder Package Overview
The Builder package provides a fluent API for constructing DOM elements with automatic style management.
import { ElementBuilder } from '@universityofmaryland/web-builder-library';
The ElementBuilder provides a chainable interface for creating DOM elements, attaching styles, nesting children, and producing the standard { element, styles } result that the rest of the design system expects.
Using ElementBuilder
import { ElementBuilder } from '@universityofmaryland/web-builder-library';
const card = new ElementBuilder('div')
.withClassName('feature-card')
.styled(`
.feature-card {
padding: 1.5rem;
border: 1px solid #dee2e6;
border-radius: 8px;
}
.feature-card__title {
font-weight: 700;
margin-bottom: 0.5rem;
}
`)
.withChild(
new ElementBuilder('h3')
.withClassName('feature-card__title')
.withText('Card Title')
)
.withChild(
new ElementBuilder('p')
.withText('Card description goes here.')
)
.build(); // Returns { element, styles }
build() returns an ElementModel with element (HTMLElement) and styles (string) properties, matching the standard interface used throughout the design system.
Composing with Styles
Combine the Styles library tokens and utilities with the Builder for consistent theming:
import * as Styles from '@universityofmaryland/web-styles-library';
import { ElementBuilder } from '@universityofmaryland/web-builder-library';
// Use styles library tokens and utilities alongside builder
const styledElement = new ElementBuilder('section')
.withClassName('custom-section')
.styled(`
.custom-section {
padding: ${Styles.token.spacing.lg};
background-color: ${Styles.token.color.grayLighter};
}
`)
.build();
Because the Builder produces standard CSS strings, you can reference any token or utility from the Styles package directly inside template literals. This keeps your custom components visually aligned with the rest of the design system without hard-coding values.
Integration with Components
Register custom components alongside official ones so they coexist on the same page:
import { LoadStructuralComponents } from '@universityofmaryland/web-components-library/structural';
import { registration as customFeatureCard } from './custom-feature-card';
// Register official components
LoadStructuralComponents();
// Register custom components
customFeatureCard();
Both official and custom components share the same Shadow DOM, slot, and attribute patterns provided by the Model package. This means your custom components will behave identically to the built-in ones -- same lifecycle, same style encapsulation, same attribute handling.
Related Resources
TypeDoc API Reference
Generated API documentation for all design system packages.
Advanced Component Usage
TypeScript integration, testing, and custom component patterns.
Elements Use Cases
See how element builders leverage the model and builder packages.