AntaInstall and configure
Switch to dark theme
Search documentation
On this page

Install and configure Documentation has not yet been reviewed by a human.

Installation

Terminal window
npm install @antadesign/anta # or pnpm / bun

Pin an exact version in package.json ("@antadesign/anta": "0.3.16") instead of a floating tag such as "latest".

Full bundle

Use the full bundle as the default setup. Import the JavaScript entry and its stylesheet in your browser app entry:

import '@antadesign/anta/bundle.css'
import { Progress } from '@antadesign/anta/bundle'
<Progress value={42} label="Uploaded" hint="3 of 7" />

bundle registers every custom element and exports the JSX wrappers. bundle.css contains global tokens, the reset, element styles, and composed wrapper styles. The JavaScript bundle does not import this stylesheet, so keep both imports. Its React peer dependency and Preact configuration are the same as the regular JSX entry.

Use this pair together. Adding granular element imports also loads their CSS, duplicating rules already in bundle.css.

Granular usage (advanced)

Use granular imports to choose which browser elements and styles your app loads, or to render JSX on a server or in a worker. Load shared tokens once, optionally include the reset, and import the element entries you use:

import '@antadesign/anta/tokens.css'
import '@antadesign/anta/reset.css'
import '@antadesign/anta/elements/a-progress'
import '@antadesign/anta/elements/a-title'
import '@antadesign/anta/elements/a-tag'
import { Progress, Title, Tag } from '@antadesign/anta'
<>
<Title>Uploads</Title>
<Progress value={42} label="Uploaded" hint="3 of 7" />
<Tag>In progress</Tag>
</>

Each element entry imports its own CSS for your bundler to include and registers its browser class when needed. Some entries load only CSS and have no custom element class to register. Element entries do not import global tokens or the reset.

JSX wrappers produce <a-*> tags and attributes. They do not register browser elements or import CSS. Load element entries in the browser’s UI thread; see Registering elements for server and worker rendering.

Composed components have CSS-only entries for their layout styles:

JSX wrapper UI-side style entry
Breadcrumbs @antadesign/anta/elements/a-breadcrumbs
Steps @antadesign/anta/elements/a-steps
InputDate @antadesign/anta/elements/a-input-date
Select @antadesign/anta/elements/a-select
SelectFaceted @antadesign/anta/elements/a-select-faceted

These entries load layout CSS without registering a class or loading nested elements. Import the browser elements used by the composition too. For example, Steps uses Tabs and Tooltip, and may render icons, loaders, or panels depending on its props:

// Browser UI entry, alongside shared tokens and the optional reset.
import '@antadesign/anta/elements/a-steps'
import '@antadesign/anta/elements/a-tabs'
import '@antadesign/anta/elements/a-tab'
import '@antadesign/anta/elements/a-tabpanel'
import '@antadesign/anta/elements/a-tooltip'
import '@antadesign/anta/elements/a-icon'
import '@antadesign/anta/elements/a-loader'

Import Steps from @antadesign/anta where you render JSX, including in a worker or on the server. Select and SelectFaceted share one stylesheet, which bundlers include once when both style entries are imported.

To load all elements through the separate entries, replace the per-element imports with import '@antadesign/anta/elements'. Keep the tokens and optional reset.

Individual stylesheets are also exported for direct CSS imports. With a bundler that supports ?raw, you can read a stylesheet as text:

import titleCss from '@antadesign/anta/elements/a-title.css?raw'

This returns CSS text; it does not apply styles or register an element.

Optional theme

Add one optional theme after either the full bundle CSS or the granular styles:

import '@antadesign/anta/theme-antune.css'

Use theme-antithesis.css for Antithesis, or omit both themes to keep the seed-derived default palette. These theme files do not load fonts. Choose fonts separately; see Fonts.

What you import (and why)

Import Provides
@antadesign/anta/bundle All browser element definitions and the JSX API in one minified ESM runtime.
@antadesign/anta/bundle.css Global tokens, reset, element, and composed wrapper styles in one minified stylesheet.
@antadesign/anta/tokens.css Shared color roles, fonts, dark-mode support, and layer order for granular usage.
@antadesign/anta/reset.css Optional reset and typography defaults in @layer anta.reset.
@antadesign/anta/elements/a-* One element’s behavior and CSS, or CSS alone for structural tags and composed layouts.
@antadesign/anta/elements All browser element definitions, element styles, and composed layout styles through separate modules.
@antadesign/anta Typed JSX wrappers for React, Preact, and configured runtimes, without CSS or element registration.
@antadesign/anta/elements/*.css Individual stylesheets without element registration.
@antadesign/anta/theme-antune.css Optional Antune theme.
@antadesign/anta/theme-antithesis.css Optional Antithesis theme.

With granular usage, include tokens.css before element styles unless your app provides those variables. Elements depend on them for their default appearance.

Cascade layers

Anta’s reset and element CSS use child layers inside @layer anta. Every Anta stylesheet reserves the same order, so granular stylesheets remain safe when a bundler loads them before tokens.css:

@layer base, anta, components, utilities;
@layer anta.reset, anta.components, anta.theme;

anta.theme lets the optional reference palette replace component formulas. The outer anta layer keeps its public cascade position.

To change that order, declare it in CSS loaded before any Anta stylesheet. The first declaration fixes a layer’s position:

/* your global.css, loaded before anta */
@layer reset, anta, my-components, utilities;

Token custom properties stay unlayered so they apply everywhere.

Gotcha: an unlayered hard reset defeats Anta’s element rules.

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

Unlayered styles beat layered ones regardless of specificity. This reset overrides Anta’s element defaults. Delete the duplicate, or put your reset in @layer base { … }; reset.css already applies the same universal reset in @layer anta.reset.

AI setup

Anta includes version-matched Markdown documentation in its npm package. Append this section to your application’s agent instruction file, such as AGENTS.md, CLAUDE.md, or your tool’s equivalent. Keep existing project rules:

## Anta
Before Anta UI work, read
`node_modules/@antadesign/anta/docs/index.md`
and the pages relevant to the task.
Verify component names, imports, props, and event signatures against the
installed documentation and TypeScript declarations. Do not infer Anta APIs
from similarly named components in other libraries.

The path is relative to the application directory where Anta is installed. Adjust it for your workspace or package-manager layout. Installing Anta does not modify your agent configuration.

For tools without local file access, provide the web documentation index and your installed Anta version. Web documentation may describe a newer release.

Registering elements

JSX wrappers render <a-*> tags. Load their browser definitions and styles in the UI thread before rendering or hydrating those tags. For full bundle usage, import both entries at the top of your browser app entry, outside components and hooks:

// src/main.tsx (or wherever your root render lives)
import '@antadesign/anta/bundle.css'
import '@antadesign/anta/bundle'
import { createRoot } from 'react-dom/client'
import App from './App'
createRoot(document.getElementById('root')!).render(<App />)

The JavaScript bundle registers all browser elements. With granular usage, load shared tokens, the optional reset, and the entries your app uses:

import '@antadesign/anta/tokens.css'
import '@antadesign/anta/reset.css'
import '@antadesign/anta/elements/a-tooltip' // <a-tooltip> behavior and CSS
import '@antadesign/anta/elements/a-button' // <a-button> behavior and CSS
import '@antadesign/anta/elements/a-title' // Title CSS only
import '@antadesign/anta/elements/a-tag' // Tag CSS only

To load all browser elements and layout styles, replace the individual element imports with import '@antadesign/anta/elements'. Keep the shared tokens and optional reset. Registration is idempotent and guarded when customElements is unavailable. CSS imports need a bundler that handles stylesheets.

CSS-only components such as Title, Tag, Progress, Icon, and Loader render without custom element registration. Their entries load styles. Icon and Loader retain register_a_icon() and register_a_loader() for integrations that explicitly require a defined tag.

Static imports register classes before the app’s first client render or hydration. Server-rendered HTML can paint before the browser loads JavaScript; load its CSS with the initial document, as in the Next.js setup below.

Loading elements in useEffect can delay registration until after paint. The dynamic import resolves later, so unregistered elements can appear first. Moving the dynamic import into useLayoutEffect still leaves the import asynchronous. Use a static import at the top of the UI entry.

Choose the entry point for your runtime:

Server and worker rendering

Import JSX wrappers in the code that renders your UI:

// Server or worker
import { Button, Title } from '@antadesign/anta'

Load the matching browser definitions and styles in a separate UI entry:

// Browser UI thread
import '@antadesign/anta/tokens.css'
import '@antadesign/anta/reset.css'
import '@antadesign/anta/elements/a-button'
import '@antadesign/anta/elements/a-title'

Rendering a JSX wrapper does not register its browser element. Raw <a-*> markup uses the same browser entries and can omit the JSX wrappers. For a custom JSX runtime, call configure() in the process or thread that renders the wrappers; see Framework setup. Worker renderers receive native event subscriptions in the first projection. The browser listener workaround does not delay worker subscriptions or require access to UI-thread DOM.

Framework setup

React

Client-rendered React apps need no configure() call. Load the JavaScript and CSS entries for your chosen import strategy before rendering. If your app hydrates server-rendered HTML, enable browser hydration.

Next.js

For the full bundle setup, import its stylesheet in the App Router root layout:

app/layout.tsx
import '@antadesign/anta/bundle.css'
import type { ReactNode } from 'react'
export default function Layout({ children }: { children: ReactNode }) {
return <html lang="en"><body>{children}</body></html>
}

Import the runtime and JSX wrappers in a Client Component:

app/page.tsx
'use client'
import * as React from 'react'
import { Button, Title, configure } from '@antadesign/anta/bundle'
configure(React.createElement, React.Fragment, React, { hydratingEvents: true })
export default function Page() {
const [count, setCount] = React.useState(0)
return <>
<Title>Anta in Next.js</Title>
<Button label={`Count: ${count}`} onClick={() => setCount(value => value + 1)} />
</>
}

Next.js prerenders Client Components on the server for the initial page load. 'use client' marks the client/server module boundary; it does not disable server rendering. Anta guards element registration when browser APIs are absent and registers the elements when the client module runs before hydration. The configuration enables the event-prop workaround for that hydration.

For granular usage, replace the layout’s bundle stylesheet with shared tokens and the optional reset:

// app/layout.tsx imports
import '@antadesign/anta/tokens.css'
import '@antadesign/anta/reset.css'

Keep the same page component and replace its imports with:

app/page.tsx
'use client'
import * as React from 'react'
import '@antadesign/anta/elements/a-button'
import '@antadesign/anta/elements/a-title'
import { Button, Title, configure } from '@antadesign/anta'
configure(React.createElement, React.Fragment, React, { hydratingEvents: true })

Both setups work with Next.js’s default Turbopack bundler.

Preact with compat

If your bundler aliases react to preact/compat, Anta needs no configure() call for client rendering. Load the entries for your chosen import strategy. The Vite Preact preset provides these runtime aliases. For server-rendered HTML, enable browser hydration.

Preact without compat

If react is not aliased to preact/compat, pass Preact’s JSX factory and hooks to configure() before rendering Anta components. For full bundle usage:

import '@antadesign/anta/bundle.css'
import { configure } from '@antadesign/anta/bundle'
import { h, Fragment } from 'preact'
import * as hooks from 'preact/hooks'
import { useSyncExternalStore } from 'preact/compat'
configure(h, Fragment, { ...hooks, useSyncExternalStore })

Pass the hooks object as a whole. It replaces the previous renderer’s hooks; missing hooks report an error when used. React’s hooks are the default when no object is supplied. The extra useSyncExternalStore export supports components that subscribe to external stores.

Import JSX wrappers from @antadesign/anta/bundle with this setup. For granular usage, import both configure and the wrappers from @antadesign/anta and load the UI entries separately. The root package and the prebuilt bundle each have their own renderer configuration, so use configure from the same entry as your wrappers. The explicit preact/compat hook import does not require an alias.

Browser hydration

When your browser app hydrates server-rendered HTML, set hydratingEvents: true before mounting Anta components:

import * as React from 'react'
import { configure } from '@antadesign/anta/bundle'
configure(React.createElement, React.Fragment, React, {
hydratingEvents: true,
})

This lets Input, Banner, Expander, and expandable Text attach their native event handlers after the first browser commit. With false or no option, handlers pass through immediately without a listener setup effect or extra mount render. Client-only apps use that default without configuration.

Use configure from the same entry as your wrappers: @antadesign/anta or @antadesign/anta/bundle. For Preact without compat aliases, pass its factory and hooks with the same fourth argument. Configure each rendering process or thread separately. Servers and workers without window forward immediately, even when this option is enabled.

Keep the option unchanged while components are mounted. If any root using that package entry hydrates server HTML, enable it before mounting any root. Each configure() call resets an omitted option to false, so later setup calls must preserve hydratingEvents: true. Next.js Client Components still hydrate on the initial page load; 'use client' does not make an app client-only.

Astro

For hydrated React or Preact islands, configure Anta before Astro hydrates them. Use Astro’s before-hydration script stage in an integration:

// astro.config.mjs: add to integrations alongside your React or Preact integration
{
name: 'anta-hydration',
hooks: {
'astro:config:setup': ({ injectScript }) => {
injectScript('before-hydration', `
import * as React from 'react';
import { configure } from '@antadesign/anta/bundle';
configure(React.createElement, React.Fragment, React, {
hydratingEvents: true,
});
`)
},
},
}

This example uses full bundle wrappers. For granular wrappers, use @antadesign/anta instead and load browser elements separately. Import bundle.css in your layout for the full bundle. Preact requires the @astrojs/preact integration’s compat: true setting for this example. Static markup and client:only islands do not need the hydration option.

Custom renderer events

Worker renderers receive event subscriptions in their first projection by default, including renderers with a window shim:

configure(h, Fragment, hooks)

Pass the runtime’s hooks object as a whole. You do not need to opt into browser hydration for worker projections. If shared setup previously enabled it, pass { hydratingEvents: false } as the fourth argument before mounting the worker UI.

TypeScript: typing raw <a-*> tags in JSX

JSX wrappers such as <Button> and <Progress> need no extra typing. Configure JSX only when you write raw <a-*> tags.

Option A (preferred) — point JSX types at Anta in tsconfig.json:

{ "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "@antadesign/anta" } }

Every a-* tag type-checks, standard HTML tags keep working, and importing @antadesign/stickers adds its tags automatically.

Option B — if jsxImportSource cannot change, merge Anta’s tag map into your JSX namespace with AntaIntrinsicElements (and StickerIntrinsicElements when needed):

import type { AntaIntrinsicElements } from '@antadesign/anta'
import type { StickerIntrinsicElements } from '@antadesign/stickers' // only if you use stickers
declare global {
namespace JSX {
interface IntrinsicElements extends AntaIntrinsicElements, StickerIntrinsicElements {}
}
}

With @types/react 18+ and jsx: "react-jsx", JSX is module-scoped. Extend the react module instead:

import type { AntaIntrinsicElements } from '@antadesign/anta'
declare module 'react' {
namespace JSX {
interface IntrinsicElements extends AntaIntrinsicElements {}
}
}

Both options reject unknown tags and invalid props. New tags arrive with Anta upgrades; there is no per-tag list to maintain.

Raw web components (no JSX)

Elements also work in plain HTML without JSX wrappers. This example requires a bundler that processes module scripts and CSS imports:

<script type="module">
import '@antadesign/anta/tokens.css'
import '@antadesign/anta/reset.css'
import '@antadesign/anta/elements/a-progress'
</script>
<a-progress value="42" max="100" tone="info" role="progressbar"
aria-label="Upload" aria-valuenow="42" aria-valuemin="0" aria-valuemax="100">
</a-progress>

An import map resolves module names but does not process the plain CSS imports in Anta’s element entries. When serving native modules without a bundler, use a separately prepared JavaScript entry and linked stylesheets.

Dark mode

For a page-wide dark mode, add dark to html. Shared tokens switch the palette and root color scheme, including scrollbar colors. The reset, included in bundle.css or loaded separately as reset.css, paints body with --bg-2:

<html class="dark">
<body>
<a-progress value="50" role="progressbar" aria-label="Upload"
aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">
</a-progress>
</body>
</html>

Use dark or light on another ancestor to scope its color scheme and palette. If you omit the reset, set your app’s background and text color in your own CSS, for example with --bg-2 and --text-2.

Fonts

Anta works with system fonts without any font downloads. tokens.css, also included in bundle.css, defines system stacks in --sans-serif, --serif, and --monospace, and sets 1rem to 15px. The optional themes keep those stacks and do not register font faces or request font files. Components and theme rules choose which stack to use.

Use fonts from Google Fonts or host font files in your application. Manage font loading in a separate application stylesheet such as fonts.css, and import it after the Anta styles and optional theme:

import '@antadesign/anta/bundle.css'
import '@antadesign/anta/theme-antune.css' // Optional
import './fonts.css'

With granular usage, load fonts.css after tokens.css, your element styles, and the optional theme. Anta.design also loads its reference fonts through a separate stylesheet. That setup is an example, and is not imported by the package. See Font examples for that setup and Google Fonts examples.

Register your fonts and override only the stacks you want to change. Keep fallback families after each custom font name. This fonts.css example uses separate Roman and Italic variable files and keeps the default serif and monospace stacks:

@font-face {
font-family: "App Sans";
src: url("/fonts/app-sans-roman.woff2") format("woff2");
font-style: normal;
font-weight: 100 900;
font-display: swap;
}
@font-face {
font-family: "App Sans";
src: url("/fonts/app-sans-italic.woff2") format("woff2");
font-style: italic;
font-weight: 100 900;
font-display: swap;
}
:root {
--sans-serif: "App Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
}

Font display with swap shows fallback text while the custom font loads, then switches to that font when it is ready. If the font fails to load, the browser keeps using a fallback family. The variables remain valid in either case.

Anta’s reset styles semantic italics (em, i, var, and dt) to select the Italic face. If you omit the reset, your application or the browser’s default rules provide those styles.

Variable slant

A variable font with a standard slnt axis can provide both instances. Expose it through font-style: oblique instead of setting slnt on italic elements:

@font-face {
font-family: "App Variable";
src: url("/fonts/app-variable.woff2") format("woff2");
font-style: oblique 0deg 12deg;
font-weight: 100 900;
font-stretch: 75% 100%;
font-display: swap;
}
:root {
--sans-serif: "App Variable", sans-serif;
}

The browser selects 0deg for normal text and 11deg for semantic italics. Use the range your font declares to avoid combining slnt with a synthetic oblique.

Browser support

Anta requires ARIA element references, custom-element states, and the Popover API. It ships no baseline polyfills or copied-text fallback for ARIA references.

Browser Minimum version
Chrome / Edge, including Android Chrome and WebView 135
Safari / iOS Safari 17.4
Firefox, including Android Firefox 136

ARIA element references are Baseline 2025. Anta also relies on relative OKLCH, :has(), dvh, cascade layers, and constructable shadow DOM. Older browsers can fail hard, including :state() being unrecognized or showPopover() throwing. Gate Anta on your own support matrix when you support older browsers.

checkVisibility() falls back to getClientRects(). Some raw attributes use typed CSS attr(), whose support extends beyond Anta’s minimum browser requirements. JSX wrappers supply CSS variables for these values. Each component’s Web Component reference describes its raw attribute requirements.

Content Security Policy

Anta’s tokens, component stylesheets, and optional themes work when your Content Security Policy (CSP) allows their stylesheet URLs through style-src-elem or its style-src fallback. External CSS and named theme values do not require inline style attributes.

Custom color props such as tone="#6750a4", explicit lengths such as round={12} or Icon’s size={24}, and some dynamic value props produce inline CSS custom properties. The style prop also produces inline styles. Server rendering serializes these values into HTML style attributes, which style-src-attr 'none' blocks. Named tones, preset sizes, and boolean round use external CSS without these attributes.

When inline attributes are forbidden, omit the customization prop and apply its value through className and an allowed stylesheet. For example, replace <Icon shape="check" size={24} /> with:

<Icon shape="check" className="confirmation-icon" />
.confirmation-icon {
--icon-size: 24px;
}

Define runtime values in an application-managed stylesheet permitted by your policy when they cannot be expressed with predefined classes. Check each component’s reference for its styling surface and dynamic-value requirements. Client-side assignments to individual CSS properties can behave differently; do not rely on hydration to repair blocked server-rendered styles. See CSP rules for style attributes.

Server-rendered <style> blocks also need CSP permission. They follow style-src-elem, falling back to style-src and then default-src. 'self' allows same-origin stylesheet files, but does not authorize inline <style> blocks. Use a matching nonce or hash for those blocks under a strict policy. A nonce on a <style> element does not authorize HTML style attributes. See CSP rules for stylesheet elements.

Component defaults in @antadesign/anta, including Panel’s maximized surface and backdrop, use external stylesheets. Load the UI entry or bundle CSS as described in Installation. Custom props and application styles can still require inline-style permission as described here.

When placing an Anta component inside an application-owned shadow root, load its external CSS in that root through a stylesheet link. Document styles do not cross that boundary.

The separate @antadesign/stickers package has its own CSP requirements. Its static and animated elements still inject shadow <style> blocks, which a policy allowing only external styles blocks. Loading Anta’s external CSS or a theme does not authorize those blocks.