Theming
Set your app's colour theme, shape, scale and text preferences with data attributes.
After importing the theme, set data attributes on html or another ancestor. Components and token utilities inside it use the selected values.
Try each option in the Playground before applying it in your app. It shows the settings on real components and gives you the code for your configuration.
Base defaults
Each axis has its own base value. The table shows what that value selects.
| Axis | Attribute | Base maps to | Example |
|---|---|---|---|
| Theme | data-theme="base" | Default light palette | Body text is dark on a light background. |
| Font | data-fontfamily="base" | Aksara fonts | Display, body and code text use Aksara. |
| Shape | data-shape="base" | Standard radii and border widths | The 16px radius token is 16px. The 1px border token is 1px. |
| Scale | data-scale="base" | 1x | The 16px spacing token is 16px. |
| Font size | data-fontsize="base" | 16px preset | Body text is 16px. |
| Line height | data-fontlineheight="base" | ThaiFont | Body text has a 28px line height at the 16px preset. |
| Breakpoint | data-breakpoint="base" | mobile | The reference width is 376px, horizontal padding is 16px and modal-width tokens are 352px. |
Setting data-theme="base" changes only the colour theme. It does not reset fonts, shape, scale, font size, line height or breakpoint. Set each attribute to base to select all the defaults explicitly.
The breakpoint default selects mobile token values, not a mobile browser width.
What each axis changes
- Theme selects a colour palette. The options are light, dark and high-contrast.
- Font selects a font profile. The options are Aksara, Sarabun and Arena.
- Shape changes corner-radius and border-width tokens.
- Scale changes spacing tokens.
- Font size changes text-size tokens.
- Line height selects the English or Thai text metrics.
- Breakpoint selects responsive token values, such as page padding and dialog widths. It does not resize your browser or change viewport-based CSS media queries.
Dark mode
Set data-theme="dark" on html to apply dark colours across your app.
<html data-theme="dark"></html>To switch back to the default light theme, set data-theme="base". A theme control in your app can update the attribute with ThemeProvider and useTheme.
'use client'
import { Button, useTheme } from '@aksornproject/aksara-ui'
export function ThemeToggle() {
const { theme } = useTheme()
return (
<Button onClick={() => theme.toggle('dark', 'base')}>
Toggle colour theme
</Button>
)
}Render it under <ThemeProvider target="html" persist>. The provider saves the choice and applies it before the page paints on the next visit. If you use another theme provider, configure it to update data-theme with the values below.
The library's Tailwind dark: variant matches data-theme="dark" on the element or an ancestor, rather than a .dark class.
Available colours
data-theme | Use |
|---|---|
base | Default light |
dark | Dark |
light-hc | High-contrast light |
dark-hc | High-contrast dark |
Use semantic colour utilities such as bg-color-background-body and text-color-text-primary so your own layouts follow the theme too. Preview their values on the Colors page.
Fonts
theme.css declares Aksara in weights 400, 500, 600 and 700, the weights the typography tokens use. The default font profile needs nothing else. The browser downloads only the weights a page renders, and shows the fallback font until each one arrives.
The other font profiles name fonts that theme.css doesn't load. Import the entry for each profile your app uses, after the theme.
data-fontfamily | Fonts | Import |
|---|---|---|
base | Aksara | Nothing |
aksornfirst-sarabun | Sarabun | @aksornproject/aksara-ui/fonts/aksornfirst-sarabun.css |
arena, arena-2 | Fredoka, Nunito Sans, Roboto Mono | @aksornproject/aksara-ui/fonts/arena.css |
@import 'tailwindcss';
@import '@aksornproject/aksara-ui/theme.css';
@import '@aksornproject/aksara-ui/fonts/arena.css';Each entry loads weights 400 to 700. The font files are split by script, so a page with only Latin text skips the Thai files. An entry you don't import adds nothing to your build.
Fallbacks
Every font family ends in Aksara, system-ui, sans-serif. The browser uses Aksara for any character the theme's font lacks. Fredoka, Nunito Sans and Roboto Mono have no Thai characters, so Thai text in arena and arena-2 renders in Aksara. If you skip an entry, the browser uses a copy of that font installed on the device, and Aksara when there is none.
Serve the fonts yourself
To serve Aksara from your own server or CDN, declare @font-face rules for Aksara after the theme import. When two rules declare the same family, weight and style, the browser uses the later one and doesn't download the bundled file.
@import 'tailwindcss';
@import '@aksornproject/aksara-ui/theme.css';
@font-face {
font-family: Aksara;
src: url('https://cdn.example.com/Aksara-Regular.woff2') format('woff2');
font-weight: 400;
font-display: swap;
}Repeat the rule for weights 500, 600 and 700. To serve a profile's fonts yourself, skip its entry and declare @font-face rules for the font names in the table.
Shape and scale
You can apply these attributes to the whole app or limit them to a section.
| Attribute | Values | Controls |
|---|---|---|
data-fontfamily | aksornfirst-sarabun, arena, arena-2 | Font profile fonts |
data-shape | base, fun, timeless | Corner radii and border widths |
data-scale | 1x, 1.25x, 1.5x | Spacing token values |
data-fontsize | 16px, 20px, 24px | Text size |
data-fontlineheight | EnglishFont, ThaiFont | Language-specific line heights |
data-breakpoint | desktop, laptop, ipad, mobile | Responsive token values |
<section data-theme="dark" data-fontfamily="arena">
<Typography className="text-color-text-primary">
ตั้งค่าการแจ้งเตือน
</Typography>
</section>The section renders dark colours with Fredoka headings and Nunito Sans body text.
These settings affect token-based styles. Fixed pixel values in your app do not scale with them.