v2.0 · Released Mar 14, 2026 · MIT

Unstyled components. Bring your own design system.

38 accessible, fully-keyboard primitives with zero opinions about how they look — shipped to React, Vue and Solid from a single shared a11y test suite.

$ npm install @borealis/react

also: @borealis/vue · @borealis/solid

0GitHub stars
0components
0frameworks
2.8Mweekly installs

Trusted in production at

Vercel Linear Stripe Raycast Shopify Figma Cal.com Sentry Notion
Compound components

A Dialog that's all behavior, no chrome.

Borealis ships the focus trap, scroll lock, escape handling and ARIA wiring. The markup and every class name are entirely yours.

Dialog.tsx
1import { Dialog } from '@borealis/react'
2
3export function InvitePanel() {
4  return (
5    <Dialog.Root>
6      <Dialog.Trigger className="btn-primary">Invite people</Dialog.Trigger>
7      <Dialog.Content className="card w-[440px]">
8        <Dialog.Title className="text-lg font-semibold">
9          Invite to workspace
10        </Dialog.Title>
11        <Dialog.Description className="text-muted">
12          They'll get an email with a join link.
13        </Dialog.Description>
14        <Dialog.Close className="btn-ghost">Done</Dialog.Close>
15      </Dialog.Content>
16    </Dialog.Root>
17  )
18}
Focus trap, scroll-lock & aria-modal handled automatically
Why Borealis exists

Accessibility is hard.
Shipping it three times is harder.

Things we don't do

  • No bundled CSS, no theme, no className we picked for you.
  • No design tokens, no <ThemeProvider>, no runtime style engine.
  • No "kitchen-sink" components — we ship primitives, not page templates.
  • No framework favoritism — React, Vue and Solid ship the same release, same day.
  • No silent breaking changes — every a11y regression fails CI before it ships.

A button that opens a menu is deceptively expensive. It needs roving tabindex, type-ahead matching, an aria-activedescendant contract, escape-to-close, focus return, and correct behavior under a screen reader's virtual cursor. Styled component kits bundle all of that with a visual design you'll fight forever. Headless libraries unbundle the two: you get the unglamorous, correct behavior — and you write every pixel yourself.

Radix UI proved the headless model is the right one. Composable primitives, real WAI-ARIA semantics, no styling baggage — it reset the industry's expectations. But Radix is React, and only React. Teams on Vue or Solid have been re-implementing the same focus traps and the same listbox keyboard contracts, badly, in isolation, for years — each project paying the accessibility tax from scratch.

Borealis ports those primitives to all three frameworks from one shared specification and one accessibility test suite. The Combobox keyboard contract is defined once; React, Vue and Solid each implement against it; the same 1,900 axe-core and keyboard-interaction assertions run against every framework on every commit. A fix landed for Solid is, by construction, a fix the React and Vue maintainers can't forget to mirror.

1,900
a11y assertions
3
frameworks, 1 spec
0
bytes of CSS
What's in the box

38 components. Every one accessible by default.

From Dialog and Combobox to RangeSlider and DatePicker — primitives that handle the hard parts so your design system stays the only thing you maintain.

38 components, 3 frameworks

Dialog, Popover, Combobox, Menu, Tabs, Tooltip, Accordion, Select, Toast and 29 more — identical API surface across React, Vue and Solid.

import {'{'} Combobox {'}'} from '@borealis/vue'

WAI-ARIA compliant

Every primitive implements the matching ARIA Authoring Practices pattern — roles, states and properties wired correctly, verified by axe-core in CI.

role="dialog" · aria-modal="true"

Full keyboard navigation

Roving focus, type-ahead, arrow-key traversal, Home / End, Page Up / Down and screen-reader announcements — the parts everyone forgets, handled.

↑ ↓ ⏎ ⎋ · type-ahead built in

RTL support, built in

Direction-aware focus order and arrow keys. Set dir="rtl" once — Menu, Slider and Tabs flip their interaction model automatically.

<Menu.Root dir="rtl" />

Server-component friendly

Static parts render on the server; only the interactive shell hydrates. No "use client" at the top of your whole tree.

RSC-safe · streams without flicker

Animation primitives

Mount and unmount states stay in the DOM through your exit transition — pair Borealis with CSS, Motion or GSAP without orphaned nodes.

data-state="open" | "closed"

Framework coverage

38 / 38 components per framework
How it compares

Headless is a crowded field. Here's the honest table.

Radix, Ariakit and Headless UI are all excellent. The difference Borealis makes is the same primitives, the same audited contract, across three frameworks.

Capability
Borealis
Radix UI Ariakit Headless UI
Cross-framework support React · Vue · Solid React only React only React · Vue
Components shipped 38 28 31 10
Shared a11y test suite
Built-in RTL support partial
Server-component safe partial partial
Animation primitives
License MIT MIT MIT MIT

Component counts as of v2.0 · Mar 2026. Corrections welcome — open a PR against docs/comparison.md.

Quick start

Hello world in under 60 seconds.

Three steps. No config file, no provider, no build plugin. The example is React — Vue and Solid are line-for-line equivalent.

1

Install the package

Pull in the build for your framework — they're independent packages, so install only what you use.

terminal
$ npm install @borealis/react
2

Compose a primitive

Import the namespace and assemble its parts. Borealis manages open state — pass your own classes for everything visual.

Menu.tsx
import { Menu } from '@borealis/react'

<Menu.Root>
  <Menu.Trigger className="btn">Options</Menu.Trigger>
  <Menu.Items className="menu-panel">
    <Menu.Item>Rename</Menu.Item>
    <Menu.Item>Duplicate</Menu.Item>
  </Menu.Items>
</Menu.Root>
3

Style it with anything

Tailwind, CSS Modules, vanilla-extract, plain CSS — Borealis exposes data-state and data-highlighted hooks to target.

menu.css
/* highlighted via keyboard or pointer */
.menu-panel [data-highlighted] {
  background: #67E8F9;
  color: #06121A;
}
Community

Built in the open, with 240 contributors.

Every primitive's keyboard contract was argued over in a GitHub Discussion before it shipped. Come help shape v2.1.

0 GitHub Discussions

RFCs, keyboard-contract debates and triage — all public.

0 Discord members 1,206 online

Real-time help, a #showcase channel, and weekly office hours.

Core maintainers

+ 240 contributors
Lena Hoffmann
@lenahz · lead
Rohan Kapadia
@rohan-k · React
Mei Nakamura
@mei-n · Vue
Diego Salazar
@dsalazar · Solid
Amara Okeke
@amaraok · a11y
Tomasz Świderski
@tomasz-s · docs
Sofia Vinciguerra
@sofiav · DX
Halldór Ásgeirsson
@halldora · infra

Borealis is funded entirely by GitHub Sponsors — no VC, no company behind it.

Become a sponsor
Sponsors

Funded by the teams that ship on it.

Every dollar goes to maintainer time and the a11y audit budget. 88 sponsors and counting.

Sponsoring organizations

Vercel
Linear
Shopify
Figma

0 individual sponsors

FAQ

Questions, answered straight.

Is Borealis production-ready?
Yes. v2.0 is the third major release and is in production at Vercel, Linear and Shopify, serving more than 2.8 million weekly npm installs. The API is stable and follows semantic versioning — breaking changes only land in major releases, each with a published codemod. Every component carries the same 1,900-assertion accessibility suite, run on all three frameworks per commit, so a release that regresses keyboard behavior or an ARIA contract cannot reach npm.
How is this different from Radix?
Radix UI is excellent, and it directly inspired Borealis — the compound-component shape will feel familiar. The core difference is reach: Radix is React-only, while Borealis ships the same primitives to React, Vue and Solid from a single specification and one shared accessibility test suite. Borealis also ships 38 components to Radix's 28, with built-in RTL support and animation primitives. If your stack is exclusively React, Radix is a great choice; if you maintain components across frameworks — or expect to — Borealis removes the duplicate accessibility work.
Will React Server Components break it?
No. Borealis is designed for the RSC boundary. Static parts — a Dialog's title and description, an Accordion's headings — render on the server with no client cost. Only the interactive shell carries a "use client" directive, so you mark the component, not your entire page tree. Components stream without hydration flicker and ship correct markup on first paint. The Next.js App Router and Remix are both covered by our example apps and tested in CI.
What about animation?
Borealis stays headless about animation too — it never bundles a motion library. Instead each primitive exposes a data-state attribute (open / closed) and keeps unmounting elements in the DOM until their exit transition completes. That means you can animate with plain CSS keyframes, Motion, GSAP or View Transitions — your choice — without the classic problem of a popover vanishing before its fade-out finishes. There is nothing to configure; the mount/unmount lifecycle is handled for you.
Long-term commitment, or corporate sponsor lock-in?
Borealis is MIT-licensed and owned by no company. Vercel, Linear, Shopify and Figma sponsor the project, but none of them controls the roadmap, holds the trademark or can relicense the code — sponsorship funds maintainer time and the third-party accessibility audit, nothing more. Governance is a published document, releases follow a public RFC process in GitHub Discussions, and 240 contributors hold commit history across the codebase. If every sponsor walked away tomorrow, the MIT license and the community keep the project alive — that is the entire point of building it this way.
v2.0 · MIT · zero dependencies

Get started in 60 seconds.

Install one package, compose a primitive, style it your way. No config, no provider, no lock-in.

$ npm install @borealis/react