---
title: Installation
description: Install Timeless, load its CSS, and register the elements a route uses.
editUrl: true
head: []
template: doc
sidebar:
  order: 2
  hidden: false
  attrs: {}
pagefind: true
draft: false
---

```bash
pnpm add @timelessui/components
```

That is the only package you install. There are no peer dependencies, no framework runtime, and no
configuration file.

## Load the CSS

Import the tokens plus the components a route renders:

```js
import '@timelessui/components/css/tokens.css'
import '@timelessui/components/css/core/button.css'
import '@timelessui/components/css/core/floating.css'
import '@timelessui/components/css/core/popover.css'
import '@timelessui/components/css/themes/atmosphere/tokens.css'
import '@timelessui/components/css/themes/atmosphere/button.css'
import '@timelessui/components/css/themes/atmosphere/popover.css'
```

Import `tokens.css` first — it declares the cascade-layer order that lets your own CSS override
component styles. For prototypes, `@timelessui/components/css/themes/atmosphere.css` loads
everything in one request. See [Loading CSS](/docs/styling/css/) for the trade-off and
[Theming](/docs/styling/theming/) for what you can override.

## Register the elements you use

CSS-only primitives such as Button, Alert, and Card need no JavaScript at all. Enhanced components
are custom elements, and registration is explicit — per element, never automatic:

```js
import '@timelessui/components/register/ui-popover'
```

`register/<tag>` is a side-effect import. It defines the element as the module evaluates, so it has
to run in code the browser actually loads — an import that only ever executes on the server
registers nothing, and the element never upgrades. `@timelessui/components/register` registers every
element in one import, which is convenient in a prototype and ships every component's behavior.

### Registering it yourself

The same registration is also a function, on the matching `define/` path:

```js
import { definePopoverElement } from '@timelessui/components/define/ui-popover'

definePopoverElement()
```

Reach for this when you need to control _when_ registration happens — after a feature check, inside
an `onMount`, behind a dynamic import — or to define into a window other than the current one, which
the optional `targetWindow` argument is for. `define/<tag>` has no side effect of its own: importing
it and calling nothing registers nothing.

Importing `@timelessui/components/popover` gives you the class and helpers without registering
anything either, which keeps that import safe during server rendering. Your framework's guide covers
when the upgrade happens relative to hydration — see [React](/docs/frameworks/react/),
[Vue](/docs/frameworks/vue/), [Svelte](/docs/frameworks/svelte/), or
[Solid](/docs/frameworks/solid/) — and [Packages and entrypoints](/docs/reference/packages/) lists
every import.

## Next

Build something with it in [Quick start](/docs/getting-started/quick-start/), or jump straight to a
component such as [Button](/docs/components/button/) or [Dialog](/docs/components/dialog/).