suiss/ui
  • Docs
  • Components
  • Patterns
  • Interactions
  • Charts
  • Blocks

Search

Search documentation

GitHubGet started
DocsComponentsPatternsInteractionsChartsBlocks
Docs4
Get Started
  • Introduction
  • Installation
  • Theming
  • CLI

suiss/ui

Installation

Set up a React, React Native, SwiftUI or Jetpack Compose project with init, then add the components you need.

Requirements

  • React with TypeScript, such as Next.js or Vite
  • Tailwind CSS 4.2 or later
  • Node.js 18 or later

Add components

suiss/ui is a registry under the @esuiss namespace. In any project with a components.json, add components with the registry CLI:

$ pnpm dlx shadcn@latest add @esuiss/button @esuiss/dialog @esuiss/sidebar

Each item comes with the components, hooks and npm packages it depends on, and its icons are written for the icon library set in components.json. Patterns go to components/patterns/, interactions to components/interactions/, charts to components/charts/ and blocks to components/blocks/.

Choose the primitive base

Every item is published for three primitive bases under the same name. The registry picks one from the style in your components.json, so @esuiss/dialog installs the second base in a project whose style is radix-nova, the third in one whose style is aria-nova, and the default base everywhere else:

style in components.jsonPrimitive base
base-nova, base-vega and every other styleThe default base
radix-nova, radix-vega and any other radix-* style, new-york, defaultThe second base
aria-nova, aria-vega and any other aria-* styleThe third base

All three install the same files into the same folders, with the same component names and styles. They differ in how a part takes a custom element: the default base passes it to render, the second base wraps it with asChild, and in the third base the pressable element itself is the trigger, with state props such as isOpen and isDisabled.

<DialogTrigger render={<Button variant="outline" />}>Open</DialogTrigger>

<DialogTrigger asChild>
  <Button variant="outline">Open</Button>
</DialogTrigger>

<Dialog>
  <Button variant="outline">Open</Button>
  <DialogContent>…</DialogContent>
</Dialog>

Combobox, drawer and toast use the default base's primitives in all three. Stepper does too in the second base, and menubar and navigation menu in the third. The code on this site shows the default base with Phosphor icons. Pick another base or icon library under code options in the header to see the code you will get. Previews always run on the default base.

To start a new project, pick the base when you set it up:

$ pnpm dlx shadcn@latest init --base base$ pnpm dlx shadcn@latest init --base radix$ pnpm dlx shadcn@latest init --base aria

Register the namespace

Once @esuiss is listed in the public registry directory, the namespace works without any setup. Until then, add it to components.json once:

components.json
{
  "registries": {
    "@esuiss": "https://ui.suiss.app/r/{style}/{name}.json"
  }
}

The full catalog is at ui.suiss.app/r/registry.json, the second base's at ui.suiss.app/r/radix/registry.json and the third base's at ui.suiss.app/r/aria/registry.json.

Use the suiss/ui theme

Adding components never changes your colors. To switch to the suiss/ui theme, add it as an item. See Theming.

$ pnpm dlx shadcn@latest add @esuiss/theme-suiss

Use the suiss/ui CLI

The suiss/ui CLI sets up a Next.js or Vite project from scratch, writes the full theme stylesheet and uses Phosphor icons. Run init once, in the root of your project.

$ pnpm dlx @esuiss/ui@latest init

What init does

  1. Detects Next.js or Vite and checks for TypeScript and Tailwind CSS 4.2 or later.
  2. Adds the @/* import alias to tsconfig.json if it is missing.
  3. Installs and wires up Tailwind CSS if needed: postcss.config.mjs for Next.js, vite.config.ts for Vite.
  4. Writes the theme stylesheet to app/globals.css (Next.js) or src/index.css (Vite). It asks before replacing a stylesheet that already has content.
  5. Sets up the font. Text uses the system font on macOS and Inter everywhere else. Inter is loaded with next/font/google in the root layout (Next.js), or with @fontsource-variable/inter imported from the stylesheet (Vite).
  6. Installs tw-animate-css and shadcn, whose stylesheets provide the animations, variants and utilities the components rely on. The stylesheet imports them, as in any project set up with the registry CLI.
  7. Adds the button component and the cn helper it uses.

Add components with the suiss/ui CLI

Pass one or more component names to add.

$ pnpm dlx @esuiss/ui@latest add button dialog sidebar

Run add without names to pick from a list instead. Choose a group, type to filter, select with space and press enter. See CLI.

$ pnpm dlx @esuiss/ui@latest add

Components are written to components/ui/ under your @/* alias root. Components they depend on are added too, and missing npm packages are installed with your package manager: npm, pnpm, yarn or bun.

The suiss/ui CLI uses the default base. In a project whose components.json has a radix-*, new-york or default style, it adds the second base instead, and with an aria-* style the third. Pass --base to choose for yourself:

$ pnpm dlx @esuiss/ui@latest init --base radix$ pnpm dlx @esuiss/ui@latest add dialog --base radix$ pnpm dlx @esuiss/ui@latest add dialog --base aria

Then import and use them:

components/example.tsx
import { Button } from "@/components/ui/button"

export function Example() {
  return <Button>Continue</Button>
}

The cn helper

Components merge class names with cn, imported from @/lib/utils. init and add write it to lib/utils.ts under your @/* alias root when it is missing. To add it by hand, install cn and create the file:

lib/utils.ts
export { cn } from "cn"

Update components

Components are your code, so updates never overwrite your changes silently. Review the latest version first, then replace your copy if you want it.

$ pnpm dlx @esuiss/ui@latest add button --diff$ pnpm dlx @esuiss/ui@latest add button --overwrite

With the registry CLI, add the item again with --overwrite:

$ pnpm dlx shadcn@latest add @esuiss/button --overwrite

Running add for a component you already have keeps your file and tells you when it differs from the registry.

Troubleshooting

MessageFix
Tailwind CSS 4.2 or later is requiredUpgrade with npm install tailwindcss@latest and run init again.
No @/* import alias foundRun init first, or add "paths": { "@/*": ["./src/*"] } to compilerOptions in tsconfig.json.
Unknown registry "@esuiss"Add the registries entry from Register the namespace to components.json.
A newly published version is not foundnpm can take a few minutes to make new versions available. Run npx --prefer-online @esuiss/ui@latest ....

Requirements

  • An Expo or React Native project with TypeScript
  • The @/* import alias in tsconfig.json, such as "paths": { "@/*": ["./*"] }
  • For Uniwind or NativeWind, the styling library set up as its own guide describes, with global.css imported in your root component

Add components

The React Native components are published as a registry too, once per styling library. Add a components.json to the root of your project and point the @esuiss-rn namespace at the registry for your styling:

components.json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": false,
  "tsx": true,
  "tailwind": {
    "config": "",
    "css": "global.css",
    "baseColor": "neutral",
    "cssVariables": true
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "hooks": "@/hooks"
  },
  "registries": {
    "@esuiss-rn": "https://ui.suiss.app/r/rn-uniwind/{name}.json"
  }
}
Styling@esuiss-rn registrytailwind in components.json
Uniwindhttps://ui.suiss.app/r/rn-uniwind/{name}.json"css": "global.css"
NativeWind v4https://ui.suiss.app/r/rn-nativewind/{name}.json"css": "global.css", "config": "tailwind.config.js"
StyleSheethttps://ui.suiss.app/r/rn-stylesheet/{name}.json"css": ""

Then add components with the registry CLI:

$ pnpm dlx shadcn@latest add @esuiss-rn/button @esuiss-rn/dialog @esuiss-rn/select

Each item comes with the components, primitives and npm packages it depends on. In Expo projects packages are installed with expo install, so native modules match the Expo SDK. Components go to components/ui/, the primitives they build on to components/primitives/, patterns to components/patterns/, interactions to components/interactions/, charts to components/charts/ and blocks to components/blocks/. Icons use phosphor-react-native.

Add the theme

$ pnpm dlx shadcn@latest add @esuiss-rn/theme-suiss
  • Uniwind: writes theme-suiss.css to the root of your project and imports it from global.css. If global.css lives in another folder, fix the path of that import.
  • NativeWind: adds the color variables to global.css and the colors, type scale, shadows and radius scale to tailwind.config.js.
  • StyleSheet: writes components/ui/theme.ts with the colors and a useTheme() hook. Every component that needs it adds it on its own.

Render the portal host

Dialogs, sheets, menus and toasts render into a portal host. Render it once, as the last child of your root component:

App.tsx
import { View } from "react-native"
import { PortalHost } from "@/components/primitives/portal"
import { Button } from "@/components/ui/button"
import { Text } from "@/components/ui/text"

export default function App() {
  return (
    <View style={{ flex: 1 }}>
      <Button>
        <Text>Continue</Text>
      </Button>
      <PortalHost />
    </View>
  )
}

The catalogs are at ui.suiss.app/r/rn-uniwind/registry.json, ui.suiss.app/r/rn-nativewind/registry.json and ui.suiss.app/r/rn-stylesheet/registry.json.

Use the suiss/ui CLI

The suiss/ui CLI sets up the styling library, the theme, the Metro config and the portal host for you. Run init once, in the root of your project.

$ pnpm dlx @esuiss/ui@latest init

init sets up:

  • the styling library: Uniwind, NativeWind or StyleSheet
  • the @/* import alias
  • the theme stylesheet
  • the Metro config
  • the portal host in the root layout
  • the button component

The styling library is detected from your project. When neither Uniwind nor NativeWind is installed, init asks. Pass --styling to choose up front:

$ pnpm dlx @esuiss/ui@latest init --styling uniwind$ pnpm dlx @esuiss/ui@latest init --styling nativewind$ pnpm dlx @esuiss/ui@latest init --styling stylesheet

StyleSheet needs no Tailwind. init writes components/ui/theme.ts with the colors and a useTheme() hook. For NativeWind, init also writes tailwind.config.js and the NativeWind Babel preset.

Add components with the suiss/ui CLI

$ pnpm dlx @esuiss/ui@latest add dialog

Run add without names to pick from a list instead. See CLI.

Components are copied into components/ui/ together with the components and packages they depend on.

React Native without Expo

init also adds the @/* alias to Babel with babel-plugin-module-resolver, and add adds the Reanimated Babel plugin when a component needs it. Run pod install after adding components:

cd ios && pod install

Requirements

  • iOS 17 or later.
  • Components with icons use the Phosphor Swift package.
  • Charts are drawn with Apple's Swift Charts framework, which ships with iOS.

Set up your project

Run init in the folder that holds your Xcode project or Package.swift. It copies the theme files, Theme.swift and Tokens.swift, and the button.

$ pnpm dlx @esuiss/ui@latest init --platform swift

Add components

$ pnpm dlx @esuiss/ui@latest add button --platform swift

Leave out the names to pick from a list that only shows what exists for SwiftUI. The CLI lists the Swift packages a component needs; add them to your app target in Xcode.

Manual setup

  1. Add the Phosphor package to your app:
Package.swift
.package(url: "https://github.com/phosphor-icons/swift", from: "2.1.0")
  1. Copy the theme files, Theme.swift and Tokens.swift. Every view uses them.
  2. Copy the component and the files it uses, then add them to your app target.

Usage

Components follow SwiftUI conventions. The button, for example, is a button style:

struct ContentView: View {
  var body: some View {
    Button("Continue") {}
      .buttonStyle(.variant())
  }
}

Every color in Tokens.swift has a light and a dark value, so views follow the system appearance without extra setup.

Requirements

  • minSdk 24 or higher.
  • Jetpack Compose Foundation and UI. The components do not depend on Material.
  • Components with icons use the Phosphor icons library for Android.

Set up your project

Run init in the folder that holds your Android Gradle module. It copies the theme files, Theme.kt and Tokens.kt, and the button.

$ pnpm dlx @esuiss/ui@latest init --platform kotlin

Add components

$ pnpm dlx @esuiss/ui@latest add button --platform kotlin

Leave out the names to pick from a list that only shows what exists for Jetpack Compose. The CLI lists the Gradle dependencies a component needs; it never edits your Gradle files.

Manual setup

  1. Add the dependencies:
build.gradle.kts
implementation(platform("androidx.compose:compose-bom:2026.09.00"))
implementation("androidx.compose.foundation:foundation")
implementation("androidx.compose.ui:ui")
implementation("com.adamglin:phosphor-icon-android:1.0.0")
  1. Copy the theme files, Theme.kt and Tokens.kt. Every composable uses them.
  2. Copy the component and the files it uses.
  3. Update the com.esuiss.ui package names to match your project.

Usage

Wrap your content in EsuissTheme, then use the components:

@Composable
fun App() {
    EsuissTheme {
        Button("Continue", onClick = {})
    }
}

EsuissTheme follows the system setting through isSystemInDarkTheme(). Pass darkTheme to choose a mode yourself.

NextThemingPreviousIntroduction

On this page

  1. 01Requirements
  2. 02Add components
    • Choose the primitive base
    • Register the namespace
    • Use the suiss/ui theme
  3. 03Use the suiss/ui CLI
    • What init does
    • Add components with the suiss/ui CLI
  4. 04The cn helper
  5. 05Update components
  6. 06Troubleshooting
  7. 07Requirements
  8. 08Add components
    • Add the theme
    • Render the portal host
  9. 09Use the suiss/ui CLI
    • Add components with the suiss/ui CLI
    • React Native without Expo
  10. 10Requirements
  11. 11Set up your project
  12. 12Add components
    • Manual setup
  13. 13Usage
  14. 14Requirements
  15. 15Set up your project
  16. 16Add components
    • Manual setup
  17. 17Usage