On this page

Documentation

Installation

Install Luke UI and a theme, and render a component.

Install Luke UI

Install Luke UI, React Aria Components, and a theme. Luke UI uses the application's React Aria Components instance so shared contexts remain compatible. Luke UI needs React and React DOM 19.3.0 or later within React 19, and its type declarations need TypeScript 5.8 or later. This guide uses the Tactile theme.

pnpm add @luke-ui/react @luke-ui/theme-tactile react-aria-components

Set up the theme

The theme's identity class goes on <html>, and it must be there before the first paint. How you set it depends on whether React renders the whole document.

Luke UI's shared stylesheet paints <body> with the theme's surface, text colour, and body font, and portals rendered into <body> inherit them. Read Styling for what else it changes.

Single-page apps

In a Vite app, or any app that mounts React into an existing page, set the identity class in index.html:

<!doctype html>
<html class="luke-ui-theme-tactile" lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>My app</title>
	</head>
	<body>
		<div id="root"></div>
		<script type="module" src="/src/main.tsx"></script>
	</body>
</html>

Import the stylesheets in the entry module. fonts.css loads the theme's Inter font. Leave it out if you load Inter another way.

import '@luke-ui/react/stylesheet.css';
import '@luke-ui/theme-tactile/fonts.css';
import '@luke-ui/theme-tactile/stylesheet.css';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { Welcome } from './welcome.tsx';

const container = document.getElementById('root');
if (container === null) throw new Error('index.html has no #root element');

createRoot(container).render(
	<StrictMode>
		<Welcome />
	</StrictMode>,
);

Frameworks that render the document

When React renders <html> and <body>, as in Next.js, React Router, or TanStack Start, set the identity class in the root layout. The server then sends it in the first HTML.

import '@luke-ui/react/stylesheet.css';
import '@luke-ui/theme-tactile/fonts.css';
import '@luke-ui/theme-tactile/stylesheet.css';
import { themeClassName } from '@luke-ui/theme-tactile';
import type { PropsWithChildren } from 'react';

export function RootLayout({ children }: PropsWithChildren) {
	return (
		<html className={themeClassName} lang="en">
			<body>{children}</body>
		</html>
	);
}

Use components

Import each component from its package path.

import { Button } from '@luke-ui/react/button';
import { Text } from '@luke-ui/react/text';

export function Welcome() {
	return (
		<>
			<Text>Welcome to Luke UI.</Text>
			<Button>Continue</Button>
		</>
	);
}

Content Security Policy

The stylesheet draws the built-in icons from data: image URLs. If your application sets a Content Security Policy, allow them in img-src:

Content-Security-Policy: img-src 'self' data:

Without data:, the browser blocks the icons and they do not appear.

Change the theme

Paper uses the same component APIs with a flatter visual treatment. To use it, install @luke-ui/theme-paper, import its stylesheet.css and fonts.css instead of Tactile's, and set luke-ui-theme-paper on <html>. Each theme package exports its class as themeClassName.

Without data-color-mode, the theme follows the system colour mode. Read Applying a theme to set a mode.

Continue learning