# SpaceUI
> A React 19 component library and design system for dark interfaces. Zero runtime dependencies, precompiled CSS, and a role-based design-token system. Install it, import one stylesheet, and the components are finished: there is no theme to configure, no provider to mount and no build-time plugin to register.
- Package: `@inkorange/space-ui` v1.11.0, MIT
- Peer dependencies: react >= 19, react-dom >= 19. No other runtime dependencies.
- Repository: https://github.com/inkorange/space-ui
- Interactive gallery: https://space-components.vercel.app
- Full API reference for machines: https://space-components.vercel.app/llms-full.txt
- Full API reference as HTML: https://space-components.vercel.app/reference.html
## Install
```bash
npm install @inkorange/space-ui
```
```tsx
import "@inkorange/space-ui/styles.css";
import { Card, Heading, Text, Badge, Button } from "@inkorange/space-ui";
export function Planet() {
return (
Kepler-442bTemperateA super-earth in the habitable zone.
);
}
```
Two further entry points exist: `@inkorange/space-ui/styles.css` is the one required
stylesheet, and `@inkorange/space-ui/tokens.css` is the token layer on its own, for a
project that wants the palette and the scales without the components.
## Rules for writing code against this library
1. **Import the stylesheet once, at the application root.** Every component's CSS ships precompiled in one file. There is no per-component import and no Sass for consumers.
```tsx
import "@inkorange/space-ui/styles.css";
```
2. **Do not add a provider, context or theme wrapper.** Components read design tokens straight from CSS custom properties on the document. Nothing needs to be mounted above them.
3. **The library is dark-only, by design.** The tokens can be re-pointed, but the components are drawn as lit glass over a dark ground, so a light palette misrepresents every surface. There is no supported light theme; do not build one.
4. **Style with tokens, never with raw lengths or colours.** Spacing comes from the step scale, control heights from the ladder, colour from a named role. A raw px value puts the layout off the 8pt grid the whole library shares.
```css
/* Right */
.panel { padding: var(--spacing-md); gap: var(--spacing-sm); }
/* Wrong — off the grid, and it will not retune with the library */
.panel { padding: 16px; gap: 8px; }
```
5. **Override a component token on a class, not with an inline style.** An inline style sets the property at the highest specificity there is, so it defeats every media and container query the consumer later writes. Set the token on a class instead.
```css
/* Right */
.featured { --sp-carousel-view-count: 2.5; }
/* Wrong */
```
6. **Component tokens are named --sp-[component]-[modifier]-[type].** So `--sp-carousel-gap-size`, `--sp-checkbox-label-gap-size`. Every token a component accepts is listed with that component below.
7. **Boolean props default to false, so the bare attribute is the idiom.** Write ``, not `fullWidth={true}`. The one deliberate exception is `animated`, which defaults to true.
8. **Selection components are controlled through onValueChange.** Select, Slider, RadioGroup, CheckboxGroup and Tabs take a `value` and an `onValueChange`. Native text inputs (TextField, TextArea) keep React's own `value` and `onChange`.
```tsx
const [size, setSize] = useState("md");
```
9. **Keyboard support and ARIA are already inside each component.** Roving tabindex, arrow-key navigation, Escape handling, aria-checked, aria-expanded and aria-current are implemented. Do not re-declare them from outside. Do pass `aria-label` wherever a control has no visible label.
10. **Nothing touches the DOM at import time.** Components that measure do it inside effects, so the entry point imports cleanly in a server build. Components that need the top layer use the platform popover API, so no portal target has to be provided.
## Scales
Spacing is an 8pt grid: every step is a multiple of `--sp-grid-base-size`
(8px), so one token retunes the library's rhythm. A value off the
scale means the design is off the grid.
| Token | Value |
| --- | --- |
| `--spacing-xs` | 4px |
| `--spacing-sm` | 8px |
| `--spacing-md` | 16px |
| `--spacing-lg` | 24px |
| `--spacing-xl` | 32px |
| `--spacing-2xl` | 40px |
| `--sp-control-height-sm` | 36px |
| `--sp-control-height` | 40px |
| `--sp-control-height-lg` | 48px |
| `--sp-font-xs` | 12px |
| `--sp-font-sm` | 14px |
| `--sp-font-md` | 16px |
| `--sp-font-xl` | 24px |
Type is sized in rem so it follows a reader who has enlarged their browser
text. Control heights come from the ladder, never from padding arithmetic, so
a Button and the Select beside it are the same height.
## Colour roles
Colour is always a named role, never a hue or a step on a ramp. Within a role,
the suffix says the job: `-solid` fills a shape, `-text` sits on the dark
ground, `-soft` is a wash behind it, `-border` outlines, `-glow` is a halo,
and `-deep` ends a gradient. The emphasis role is `primary`; the status roles
are `success`, `warning`, `danger` and `accent`.
## Components
- **Autocomplete** — A text field that offers matching rows as you type.
- **Badge** — A compact status label.
- **BarList** — A ranked list of values as bars: a label, a track, a filled bar, a figure.
- **Box** — A plain div that understands the spacing scale.
- **Button** — The thing a reader presses to make something happen.
- **Card** — A translucent panel for grouping related content, one step above the page surface.
- **Carousel** — A row of slides that scrolls sideways, with arrows and optional dots.
- **Chart** — A chart of one or more datasets over a shared set of categories — as bars, a line, or a filled area.
- **Checkbox** — A single yes/no choice: accepting terms, turning one setting on.
- **Dialog** — A modal window over the page, for a task that has to finish or be abandoned before anything else happens.
- **DropdownMenu** — A button that opens a list of actions.
- **Flex** — A flex row or column whose gap comes from the spacing scale, so layouts inherit the 8pt grid instead of restating it in pixels.
- **Grid** — A simple column grid, 1-3 wide, with the same gap scale as Flex.
- **Heading** — A section heading.
- **IconToggle** — A segmented icon toggle: every option visible at once in a single pill, the selected one reading as active, and a click on any of them selecting it.
- **Link** — An inline anchor, styled to sit inside running text without disturbing its rhythm.
- **Loader** — An orbital spinner, for work whose length you cannot measure: a small pulsing planet at the centre of a static ring, with a moon travelling it.
- **Message** — A banner that tells the reader something about the state of the page — a risk, a result, a failure.
- **Pagination** — Page-by-page navigation for a long list.
- **PieChart** — Parts of a whole, as a circle.
- **Popover** — A button that opens a floating panel of anything — a small form, a set of filters, a prompt — without leaving the page.
- **Progress** — A determinate bar for work you can measure — use Loader when you cannot.
- **RadioGroup** — Exactly one choice from a set you can see all of at once.
- **Select** — Choosing one value from a list, with the list kept out of the way until it is wanted.
- **Separator** — A hairline rule for dividing content within a surface, where a full panel boundary would be too heavy.
- **Slider** — A range control: one thumb for a value, two for a span between values.
- **Tabs** — Several panels sharing one piece of the page, one visible at a time.
- **Text** — Body copy.
- **TextArea** — Multi-line text entry.
- **TextField** — A single line of text the reader types.
- **Tooltip** — A short label revealed on hover or focus, for naming a control whose icon is not self-evident.
## Icons
23 icons ship from the same entry point, as React components taking the
standard SVG props: `BookmarkIcon`, `ChatBubbleIcon`, `CheckIcon`, `ChevronDownIcon`, `ChevronLeftIcon`, `ChevronRightIcon`, `ChevronUpIcon`, `CrossCircledIcon`, `EnterFullScreenIcon`, `ExclamationTriangleIcon`, `ExitFullScreenIcon`, `HeartFilledIcon`, `HeartIcon`, `InfoCircledIcon`, `MagnifyingGlassIcon`, `MinusIcon`, `Pencil1Icon`, `PersonIcon`, `PlusIcon`, `QuestionMarkCircledIcon`, `Share2Icon`, `TrashIcon`, `XIcon`.
## Full documentation
- [Full API reference](https://space-components.vercel.app/llms-full.txt): every component, prop, data shape and token.
- [HTML reference](https://space-components.vercel.app/reference.html): the same, crawlable, no JavaScript required.
- [Interactive gallery](https://space-components.vercel.app): live specimens, source for each, and task guides.
- [Source](https://github.com/inkorange/space-ui): components, tests and tokens.
- [npm](https://www.npmjs.com/package/@inkorange/space-ui): published with provenance.