OPEN SOURCE · BSD-3-CLAUSE
Framework-agnostic components,
without the compromise.
dj-* web components you consume the same way from React, Vue, Angular, and Svelte, or from plain HTML with no framework at all.
Try the playground Get started
React Vue Angular Svelte Plain HTML
<dj-data-grid>: static facsimile, styled to match a React-hosted render
<dj-data-grid>: static facsimile, styled to match a Vue-hosted render
<dj-data-grid>: static facsimile, styled to match an Angular-hosted render
<dj-data-grid>: static facsimile, styled to match a Svelte-hosted render
<dj-data-grid>: static facsimile, styled to match a plain-HTML render
| Component | Category | Status |
|---|---|---|
| dj-data-grid | Data | Stable |
| dj-rich-text | Editing | Stable |
| dj-button | Foundation | Stable |
Most component libraries lock you into one framework. Switch frameworks, or run more than one across your org, and you rebuild your design system from scratch. Dojo NG's components are custom elements: the same dj-* tags work natively in React, Vue, Angular, and Svelte, and in plain HTML with no framework at all, so the library outlives whatever framework you're on today.
How it works
One set of components
Every dj-* element is built once: markup, styling, and behavior all live in the component itself.
Every framework, or none
React, Vue, Angular, and Svelte consume the same elements through thin, typed adapters. Plain HTML needs no adapter.
No lock-in
Swap frameworks, run more than one, or drop the JS framework entirely. The components don't care.
Extend it with plugins
The core components stay small. Anything optional layers on as a separate package, through the same public extension points anyone else can write against.
Data grid plugins
Row grouping with aggregates, tree rows, and column selection ship as separate packages. The grid core never reads their config.
Browse the plugins →Rich-text plugins
Headings, tables, mentions, the slash menu, embeds, and a paste sanitizer, each its own package on the Lexical core.
Browse the plugins →Write your own
defineDataGridPlugin and defineRichTextPlugin are public API. Extend a component without forking it.
Read the guide →Built for real apps
Not a marketing-page component kit: designed for the data- and forms-heavy apps teams actually ship.
WCAG 2.2 AA
Accessible by default
WCAG 2.2 AA is a standing requirement, checked with automated axe audits across the set.
Form-associated
Every input plugs into native HTML forms via ElementInternals. No wrapper libraries needed.
Built for scale
Designed for large, data- and forms-heavy line-of-business applications, not landing pages.
Pick your starting point
Same components, five getting-started paths.
Illustrative — these snippets don't resolve until the packages publish. See Getting started.
npm install @dojo-ng/button
import '@dojo-ng/button';
function App() {
return <dj-button kind="contained">Get started</dj-button>;
}
npm install @dojo-ng/button
<script setup>
import '@dojo-ng/button';
</script>
<template>
<dj-button kind="contained">Get started</dj-button>
</template>
npm install @dojo-ng/button
import '@dojo-ng/button';
@Component({
selector: 'app-root',
template: <dj-button kind="contained">Get started</dj-button>,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppComponent {}
npm install @dojo-ng/button
<script>
import '@dojo-ng/button';
</script>
<dj-button kind="contained">Get started</dj-button>
<script type="importmap">
{ "imports": { "@dojo-ng/button": "https://esm.sh/@dojo-ng/button" } }
</script>
<script type="module">import "@dojo-ng/button";</script>
<dj-button kind="contained">Get started</dj-button>Coming from another library?
Component-by-component mapping guides so a migration doesn't mean a rewrite.
Coming from Ant Design
A component and theming-token mapping from Ant's system to --dj-* tokens.
Read the guide →Re-skin the whole library with tokens
Every dj-* component reads its color, spacing, and type from --dj-* custom properties. Override the primitives, and the whole library follows.
--dj-color-primary-500
#3B82F6
--dj-color-primary-600
#2563EB
--dj-color-neutral-800
#1F2937
--dj-color-success-600
#16A34A