@axieinfinity/dango
v0.4.54-beta.5
Published
React UI component library for Axie Infinity products
Keywords
Readme
@axieinfinity/dango
React UI component library for Axie Infinity products. Dark-first design with a CSS custom property theming system.
Install
From npmjs.org — no .npmrc required:
npm install @axieinfinity/dango @axieinfinity/dango-iconsSCSS partials for build-time theming ship in dist/styles/scss/. Import @axieinfinity/dango/dist/bundle.css for runtime CSS.
Required (install in your app)
| Kind | Packages |
|------|----------|
| Peers (you install) | react ^17.0.2 \|\| ^18.0.0 \|\| ^19.0.0, @axieinfinity/dango-icons >=1.0.4 \|\| >=1.0.17-0 |
| Dev (SCSS only) | sass@^1.64.2 when using build-time SCSS customization |
Included automatically (no separate install)
npm install @axieinfinity/dango also installs runtime dependencies used by components:
| Package | Used by |
|---------|---------|
| dayjs | DatePicker, RangePicker |
| framer-motion | animated components |
| rc-dialog, rc-drawer, rc-tabs, rc-picker, … | overlay / form primitives |
You only need these in your own package.json if you import them directly — not for normal Dango component usage.
Troubleshooting
ERESOLVE: @axieinfinity/dango-icons peer conflict
npm error ERESOLVE unable to resolve dependency tree
npm error peer @axieinfinity/dango-icons@">=1.0.4" from @axieinfinity/[email protected]
npm error Found: @axieinfinity/[email protected]npm excludes prerelease icons from plain >=1.0.4 peers on older dango betas. From @axieinfinity/[email protected] onward, the peer range is >=1.0.4 || >=1.0.17-0.
| Fix | Command / action |
|-----|------------------|
| Upgrade dango (recommended) | npm install @axieinfinity/[email protected] @axieinfinity/[email protected] |
| Pin stable icons | @axieinfinity/[email protected] |
| Quick workaround | npm install ... --legacy-peer-deps or .npmrc: legacy-peer-deps=true |
Vite: Could not resolve dayjs
Upgrade to @axieinfinity/[email protected] or later — dayjs installs transitively when using DatePicker / RangePicker. No separate npm install dayjs needed.
Full guide: dist/docs/troubleshooting.md
Usage
import { Button, Input, Intent, Size } from '@axieinfinity/dango';
import '@axieinfinity/dango/dist/bundle.css';
function MyForm() {
return (
<>
<Input placeholder="Enter value" />
<Button text="Submit" intent={Intent.Primary} size={Size.Default} />
</>
);
}Documentation
Guides ship in the published package:
node_modules/@axieinfinity/dango/dist/docs/Start at dist/docs/README.md for the full index.
| Case | Guide |
|------|-------|
| 1 — Basic | dist/docs/basic-usage.md — install, bundle.css, components |
| 2 — Customize | dist/docs/customization.md — CSS variables, scoped themes |
| 3 — Vite + SCSS | dist/docs/vite-scss-customization.md — build-time tokens, Vite config |
| Troubleshooting | dist/docs/troubleshooting.md — ERESOLVE peers, dayjs errors, workarounds |
Reference: dist/docs/scss-integration.md · dist/docs/colors.md
Starters: dist/docs/vite-starter/ · dist/docs/next-15-starter/ (App Router) · dist/docs/next-14-starter/ (Pages Router)
Style imports
| Import | When to use |
|--------|-------------|
| @axieinfinity/dango/dist/bundle.css | Recommended. Global reset, :root CSS variables, and all component styles. |
| @axieinfinity/dango/dist/styles/css/dango.css | Component styles only — use when your app already has its own CSS reset and you manage :root variables yourself. |
| @axieinfinity/dango/dist/styles/scss/* | SCSS source tokens for build-time customization (see Theming below). |
Vite setup
For Vite + SCSS theme customization, see dist/docs/vite-scss-customization.md and copy-paste starters in dist/docs/vite-starter/.
yarn add -D sass@^1.64.2Minimal Vite entry (CSS only)
import '@axieinfinity/dango/dist/bundle.css';Full SCSS entry (build-time customization)
import './styles/index.scss';Create src/styles/ using the vite-starter templates in dist/docs/vite-starter/.
Theming
Dango uses a --dg-* CSS custom property system. All design tokens are generated from SCSS maps at build time and exposed as CSS variables on :root.
Default theme
- Background:
#13161B(--dg-color-background) - Text:
#FFFFFF(--dg-color-text) - Primary: Kam orange
#FF9345(--dg-color-primary) — not blue - Border radius:
8px(--dg-border-radius) - Font: Work Sans (
--dg-font-family) — not bundled; your app must load it. See below.
Loading Work Sans
The theme references Work Sans but the package does not bundle or load it. Without it your app silently falls back to the next font in the stack, so text renders in the wrong face while every other token looks correct.
Load it once in your app, matching the weights you use:
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>Or self-host it and declare it yourself — self-hosting avoids a third-party request and is the better option if you have a strict content security policy:
@font-face {
font-family: 'Work Sans';
src: url('/fonts/work-sans-variable.woff2') format('woff2');
font-weight: 400 700;
font-display: swap;
}To use a different typeface entirely, override the token — no font loading needed if you pick one the browser already has:
:root {
--dg-font-family: 'Inter', system-ui, sans-serif;
}Each intent (primary, danger, success, info, secondary, default) has a full state set: base, hover, active, focus, gradient, outlined-background, text, box-shadow, hover-light.
1. CSS variable override (recommended)
Override tokens globally or on a scoped container. No build tooling required.
/* Global brand override */
:root {
--dg-color-primary: #0066ff;
--dg-color-primary-hover: #0052cc;
--dg-color-primary-active: #004099;
--dg-color-primary-gradient: linear-gradient(104deg, #3399ff 0%, #0066ff 100%);
--dg-border-radius: 6px;
--dg-font-family: 'Inter', sans-serif;
}/* Scoped light theme */
.light-theme {
--dg-color-background: #ffffff;
--dg-color-text: #13161b;
--dg-color-box-background: #f5f5f5;
--dg-color-default: #e8eaed;
}<div className="light-theme">
<Button text="Light mode" intent={Intent.Primary} />
</div>Common semantic variables to override:
| Variable | Purpose |
|----------|---------|
| --dg-color-primary | Primary intent base color |
| --dg-color-primary-hover | Primary hover state |
| --dg-color-danger | Danger/error color |
| --dg-color-success | Success color |
| --dg-color-info | Info color |
| --dg-color-secondary | Secondary intent |
| --dg-color-background | App background |
| --dg-color-text | Default text color |
| --dg-color-box-background | Surface/card background |
| --dg-border-radius | Global border radius |
| --dg-font-family | Global font stack |
See dist/docs/colors.md for the full palette mapped to variable names.
2. className prop
Every component accepts className for targeted CSS overrides:
<Button text="Custom" className="my-button" />.my-button {
min-width: 200px;
}Prefer documented CSS variables and className over targeting hashed CSS-module class names — those can change between releases.
3. SCSS source import (advanced)
Use this when you need build-time control over $theme or component token maps ($button-variant-*, $checkbox-*, etc.). Requires sass and Vite SCSS configuration.
3a. When to use SCSS vs CSS variables
| Need | Use |
|------|-----|
| Change brand colors, radius, font | CSS variables (section 1) — simpler |
| Remap semantic intents at build time | SCSS $theme merge |
| Override button/checkbox/switch variant maps | SCSS component maps |
| Use get-color() / get-theme-value() in your *.module.scss | Full SCSS setup + Vite additionalData |
3b. File structure after install
src/styles/
├── variables.scss # App palette, fonts, breakpoints
├── dango-tokens.scss # Token pipeline + $theme merge
├── dango.scss # tokens → root → reboot
├── index.scss # Entry: dango.css + dango chain
└── components/ # Optional per-component map overrides
└── button.scssCopy from dist/docs/vite-starter/.
3c. Token pipeline (dango-tokens.scss)
Import order is fixed — do not reorder:
@forward './variables';
// Step 1: Dango base tokens
@import '@axieinfinity/dango/dist/styles/scss/common';
@import '@axieinfinity/dango/dist/styles/scss/colors/index';
@import '@axieinfinity/dango/dist/styles/scss/theme';
// Step 2: Override before utilities — all variables use !default
$color-kam-5: #0066ff;
$border-radius: 6px;
$extend: (
'color-primary': $color-kam-5,
'color-primary-hover': #0052cc,
'font-family': 'Inter', sans-serif,
);
$theme: map-merge($theme, $extend);
// Step 3: Utilities — provides get-theme-value(), get-color(), mixins
@import '@axieinfinity/dango/dist/styles/scss/utilities';
// Step 4 (optional): Component overrides — after utilities, before root
// @import './components/button';3d. Generate variables and load component CSS
dango.scss:
@import './dango-tokens';
@import '@axieinfinity/dango/dist/styles/scss/root';
@import '@axieinfinity/dango/dist/styles/scss/reboot';index.scss (import once in main.tsx):
@use '@axieinfinity/dango/dist/styles/css/dango.css';
@import './dango';3e. Component map override example
src/styles/components/button.scss:
$button-variant-background: (
'default': get-color('color-neutral-3'),
'primary': #0066ff,
'secondary': get-theme-value('color-secondary-gradient'),
);
$button-variant-hover: (
'primary': #0052cc,
);Import in dango-tokens.scss after utilities. Variable names match Dango source under dist/styles/scss/button/.
3f. Vite configuration
Prepend tokens to every *.module.scss so get-color() works without manual @use:
// vite.config.ts — see dist/docs/vite-starter/vite.config.snippet.ts
scss: {
additionalData(source, filename) {
// Skip dango-tokens.scss, dango.scss, index.scss (avoid circular imports)
return `@use "${pathToDangoTokens}" as *;\n${source}`;
},
quietDeps: true,
silenceDeprecations: ['import', 'global-builtin'],
}3g. Common mistakes
| Mistake | Result | Fix |
|---------|--------|-----|
| Import bundle.css + SCSS root/reboot | Duplicate reset and :root vars | Use dango.css + SCSS chain only |
| Import root before utilities | Undefined mixin errors | Follow order in 3c |
| Component overrides before utilities | Maps ignored or errors | Import overrides after utilities |
| Missing Vite skip list | Circular @use in entry files | Skip tokens/dango/index in additionalData |
| Target hashed CSS-module classes | Breaks on Dango upgrade | Use --dg-* vars or .dango-* hooks |
See dist/docs/scss-integration.md for the full partials table and Sass API.
Shared API
Intent
enum Intent {
Default = 'default',
Primary = 'primary',
Success = 'success',
Info = 'info',
Danger = 'danger',
Secondary = 'secondary',
}Size
enum Size {
XSmall = 'x-small',
Small = 'small',
Default = 'default',
Large = 'large',
}ButtonVariant
enum ButtonVariant {
Default = 'default',
Outlined = 'outlined',
Plain = 'plain',
}Components
| Component | Key exports |
|-----------|-------------|
| Alert | Alert |
| Badge | Badge |
| Box | Box |
| Breadcrumb | Breadcrumb, BreadcrumbItem, BreadcrumbSeparator |
| Button | Button, IconButton |
| Calendar | DatePicker, RangePicker — requires dayjs (installed with @axieinfinity/dango) |
| Checkbox | Checkbox |
| Collapse | Collapse |
| Dialog | Dialog |
| Drawer | Drawer |
| Dropdown | Dropdown, DropdownMenu |
| Input | Input, Search, TextArea |
| Loader | Loader.Circle, Loader.Dot, Loader.Linear, Loader.ProgressCircle, Loader.Skeleton |
| Menu | Menu, MenuItem, MenuDivider |
| Pagination | Pagination |
| Popover | Popover |
| Progress | Progress.ProgressBar, Progress.ProgressCircle |
| Radio | Radio, RadioGroup |
| Slider | Slider |
| Space | Space |
| Stepper | Stepper, Step, StepIndicator* |
| Switch | Switch |
| Table | Table |
| Tabs | Tabs |
| Tag | Tag, SpecialTag |
| Toast | useToast |
| Tooltip | Tooltip |
| Typography | Typography.Heading, Typography.Text |
License
MIT
