Frameworks
Use ARC UI in React, Vue, Svelte, Angular, Solid, Preact, or no framework at all.
Overview
The core @arclux/arc-ui package contains Lit-based custom elements that work in any environment. Our code generator, Prism, parses the Lit source and produces a framework-native wrapper package for each framework:
- Proper event binding (e.g. React's synthetic events)
- TypeScript type definitions
- Idiomatic imports for each framework
- SSR compatibility where supported
React
Published as
npm install @arclux/arc-ui-react @arclux/arc-ui lit
import '@arclux/arc-ui/base.css';
import { Button, Card, Input } from '@arclux/arc-ui-react';
function App() {
return (
<Card>
<h3>Sign In</h3>
<Input label="Email" placeholder="you@example.com" />
<Button variant="primary" onClick={() => console.log('clicked')}>
Submit
</Button>
</Card>
);
}
React wrappers use @lit/react createComponent, which handles event binding and ref forwarding.
Vue
Published as
npm install @arclux/arc-ui-vue @arclux/arc-ui lit
<script setup>
import '@arclux/arc-ui/base.css';
import { Button, Card } from '@arclux/arc-ui-vue';
</script>
<template>
<Card>
<h3>Hello Vue</h3>
<Button variant="primary" @click="handleClick">
Click Me
</Button>
</Card>
</template>
Svelte
Published as
npm install @arclux/arc-ui-svelte @arclux/arc-ui lit
<script>
import '@arclux/arc-ui/base.css';
import { Button, Card } from '@arclux/arc-ui-svelte';
</script>
<Card>
<h3>Hello Svelte</h3>
<Button variant="primary" on:click={() => console.log('clicked')}>
Click Me
</Button>
</Card>
Angular
Published as
npm install @arclux/arc-ui-angular @arclux/arc-ui lit
Add the stylesheet to your global styles, then import the standalone components:
/* styles.css */
@import '@arclux/arc-ui/base.css';
import { Component } from '@angular/core';
import { Button, Card } from '@arclux/arc-ui-angular';
@Component({
selector: 'app-hello',
imports: [Button, Card],
template: `
<arc-card>
<h3>Hello Angular</h3>
<arc-button variant="primary" (click)="handleClick()">
Click Me
</arc-button>
</arc-card>
`,
})
export class HelloComponent {
handleClick() {
console.log('clicked');
}
}
Solid
Published as
npm install @arclux/arc-ui-solid @arclux/arc-ui lit
import '@arclux/arc-ui/base.css';
import { Button, Card } from '@arclux/arc-ui-solid';
function App() {
return (
<Card>
<h3>Hello Solid</h3>
<Button variant="primary" onClick={() => console.log('clicked')}>
Click Me
</Button>
</Card>
);
}
Preact
Published as
npm install @arclux/arc-ui-preact @arclux/arc-ui lit
import '@arclux/arc-ui/base.css';
import { Button, Card } from '@arclux/arc-ui-preact';
function App() {
return (
<Card>
<h3>Hello Preact</h3>
<Button variant="primary" onClick={() => console.log('clicked')}>
Click Me
</Button>
</Card>
);
}
Without a wrapper
The wrappers are a convenience, not a requirement. Every component is a standard custom element, so <arc-button> works inside a framework template the moment the element is registered. This path has shipped since v3 and was documented nowhere; it is the right one if you would rather not add a dependency, or if you are already writing custom elements elsewhere in the app.
Register what you use, with a side-effect import per component or the whole catalog at once:
import '@arclux/arc-ui/base.css';
import '@arclux/arc-ui/button'; // just this element
import '@arclux/arc-ui/register'; // or every element
Telling your framework the tag is real
Most frameworks need one line so the compiler stops treating an unknown tag as a typo or a component of its own. Svelte and Solid need nothing.
// Vue — vite.config.js
export default {
plugins: [vue({
template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('arc-') } },
})],
};
// Angular — on the component or module that uses the tags
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@Component({
// …
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppComponent {}
Typed tags in JSX
React, Preact and Solid each get a generated declaration file that types every ARC tag, with the same props and enum unions as the wrapper packages.Add it to your program as a file. Atypes entry looks like the natural way to do it and silently does nothing: TypeScript resolves types as a package name and never follows an export subpath, so the name matches nothing, nothing is included, and every tag stays untyped without a diagnostic.
{
"include": [
"src",
"node_modules/@arclux/arc-ui/types/react-jsx.d.ts"
]
}
Swap in preact-jsx.d.ts or solid-jsx.d.ts as needed, or reference the file from one module instead:/// <reference path="./node_modules/@arclux/arc-ui/types/solid-jsx.d.ts" />
What you give up
Custom events are the whole difference, and it is not the same in every framework. Solid binds them natively (on:arc-change={handler}), and the declaration file types it. React 19 forwards unknown props to the element, so an event needs a ref and a listener. Preact is the strictest case: it lowercases the name after on, so a dashed event like arc-change cannot be reached from a plain prop at all, and a ref withaddEventListener is the only route.That listener wiring is what the wrapper packages are for. If you use custom events heavily in React or Preact, take the wrapper.
Vanilla JS / CDN
No framework needed. Use the core Web Component package directly:
npm install @arclux/arc-ui lit
import '@arclux/arc-ui/button';
import '@arclux/arc-ui/card';
Or via CDN with no build step:
<link rel="stylesheet"
href="https://unpkg.com/@arclux/arc-ui@4.9.1/base.css">
<script type="module"
src="https://unpkg.com/@arclux/arc-ui@4.9.1/register">
</script>
<arc-button variant="primary">Click Me</arc-button>
<arc-card>
<h3>Hello World</h3>
<p>Pure HTML, no framework needed.</p>
</arc-card>
<!-- Full bundle -->
<link rel="stylesheet" href="https://unpkg.com/@arclux/arc-ui-html@4.9.1/css/arc-ui.css">
<!-- Individual component -->
<link rel="stylesheet" href="https://unpkg.com/@arclux/arc-ui-html@4.9.1/css/button.css">
<button class="arc-button arc-button--primary">Click Me</button>
See Also
- Getting Started: installation and setup
- Theming: dark/light mode and custom themes
- Browser Support: supported browsers and polyfills