A familiar feeling.
Built your way.
Home Assistant-inspired UI. Independent web components.
Your data, your application, your home.
Interaction events Interact with a component to see its event
No events yet.
Energy overview.
Connected flows, source totals, signed stacked bars, history and a shared date selector.
Component collection.
From a single switch to an entire room. Every component, ready to use.
No components match your search.
Make yourself at home.
A small foundation. Familiar controls. No framework to learn.
Install & import
The only runtime dependency is BaseCustomWebComponent. Use the package with your bundler, or copy the self-contained ESM bundle and theme stylesheet to your own server.
npm install @node-projects/luma-elements // In your application entry point: import '@node-projects/luma-elements'; import '@node-projects/luma-elements/themes.css';
The npm package is prepared in this repository; installation from the registry requires a release. To try it now, run npm install && npm run dev in a local checkout.
<!-- No bundler: copy these files from dist/ after npm run build --> <link rel="stylesheet" href="./themes.css"> <script type="module" src="./luma-elements.js"></script> <luma-tile label="Desk lamp" state="on" toggle></luma-tile>
Your data goes in. Events come out.
Simple values use attributes or properties. Arrays and objects use JavaScript properties, or JSON-serialized attributes. Assign a new array or object when updating complex values. Boolean attributes follow HTML presence semantics: remove disabled to enable a control.
<luma-entities id="room" label="Living room"
entities='[{"label":"Lamp","state":"on","toggle":true}]'>
</luma-entities>
<script type="module">
import './luma-elements.js';
const room = document.querySelector('#room');
room.entities = [{
label: 'Lamp', state: 'on', icon: 'light',
entityId: 'light.living_room', toggle: true
}];
room.addEventListener('luma-change', ({ detail }) => {
console.log(detail.property, detail.value, detail.entityId);
});
</script>
Connect any automation backend
Luma displays the values you provide. Handle luma-change to persist changed values. Handle luma-action for commands such as open, close, arm-away, and more-info. These events bubble across Shadow DOM. Slider movement emits luma-input; releasing commits luma-change. Invalid JSON attributes preserve the previous value and emit luma-error.
Make it yours
Set data-theme="light" or data-theme="dark" on an ancestor. With neither, the stylesheet follows the OS. Theme variables inherit through the composed cards. Use exposed ::part() selectors to customize individual surfaces.
:root {
--luma-primary: #03a9f4;
--luma-radius: 12px;
--luma-card-background: #fff;
--luma-text: #212121;
--luma-secondary-text: #727272;
--luma-border: #e0e0e0;
--luma-font: system-ui, sans-serif;
}
luma-tile::part(card) { border-radius: 20px; }
Browse the complete API
Each component in the collection includes a running example, a copyable HTML snippet, property descriptions, attribute names, types, and defaults. The package also includes a Custom Elements Manifest for editor integrations and generated TypeScript declarations.
Home Assistant-inspired, application-independent
This is an independent implementation of common Lovelace UI patterns. It does not depend on Home Assistant, Lit, Material components, chart libraries, external fonts, or icon services. The Controls, Devices, Cards and Popups groups show the complete current library. All 53 public tile feature kinds are mapped to standalone controls; entity popups route by domain. The built-in icons are local SVG artwork; additional icons and trusted rich text can be slotted in.