Skip to content

Installation

Simurgh supports two installation models. Choose one model for a component and keep its import path consistent:

  • Copy source with the CLI when you want the component implementation inside your application and expect to edit it.
  • Install packages when you want normal dependency upgrades and imports from @simurgh-ui/{framework}.

The project is pre-release. Pin exact versions in production and review changes before upgrading or overwriting copied source.

Run the initializer from the root of an existing Angular, React, or Vue application:

Terminal window
pnpm dlx @simurgh-ui/cli init
pnpm dlx @simurgh-ui/cli add dialog tabs checkbox

init detects the framework from package.json, writes simurgh.json, copies the token stylesheet and recipe index, and installs that adapter’s runtime dependencies. Each add command copies the matching component recipes and adds them to the index. Pass --framework react, --framework vue, or --framework angular only when detection cannot choose correctly. Use --skip-install when your package manager or workspace policy requires installing dependencies separately.

Generated files default to these locations:

FrameworkComponent sourceStyles
React[src/]components/ui/<component>.tsx[src/]styles/simurgh/
Vue[src/]components/ui/<component>.ts[src/]styles/simurgh/
Angularsrc/app/components/ui/<component>.tssrc/styles/simurgh/

For React and Vue, the src/ prefix is used when the application already has a src directory. Projects using a root layout, including Next.js applications created without the src option, stay root-based; init does not create a new src directory.

add writes one framework-native source file and one CSS recipe per component. Existing source and recipe files are preserved unless --overwrite is supplied. The generated recipes.css file imports only installed component recipes. With no component names, add copies the complete catalog.

Terminal window
# Inspect available registry components
pnpm dlx @simurgh-ui/cli list
# Check one locally copied component against the current registry
pnpm dlx @simurgh-ui/cli diff dialog

diff exits with a non-zero status when the local source differs, including intentional local customizations. Review the difference before running add dialog --overwrite; overwrite replaces the local component and is not a merge operation. Commit or otherwise back up local changes first.

Import copied components from their local path, not from @simurgh-ui/react, @simurgh-ui/vue, or @simurgh-ui/angular. Add the copied tokens.css and recipes.css to the application’s global stylesheet entry according to the framework build tool. Component styles live under styles/simurgh/components/ and can be customized independently.

Install the adapter for your framework plus the optional recipe package:

Terminal window
# React
pnpm add @simurgh-ui/react @simurgh-ui/styles
# Vue
pnpm add @simurgh-ui/vue @simurgh-ui/styles
# Angular
pnpm add @simurgh-ui/angular @simurgh-ui/styles

The package manager installs Core and positioning dependencies declared by the chosen adapter. React 18 or newer, Vue 3.4 or newer, or Angular 18 or newer is required. Import recipe CSS in a global stylesheet or framework-level entry so it is available before the component renders.

import { Button } from '@simurgh-ui/react/button';
import '@simurgh-ui/styles/button.css';
export function SaveButton() {
return <Button type="button">Save changes</Button>;
}

React components accept the documented component props together with supported native attributes. Use the component subpath shown above to keep unrelated components out of the bundle.

<script setup lang="ts">
import { Button } from '@simurgh-ui/vue/button';
import '@simurgh-ui/styles/button.css';
</script>
<template>
<Button type="button">Save changes</Button>
</template>

Vue components forward supported attributes to their interactive element. Importing component CSS from a global application entry is also valid and avoids repeating it across single-file components.

import { Component } from '@angular/core';
import { ButtonComponent } from '@simurgh-ui/angular/button';
@Component({
selector: 'app-save-button',
standalone: true,
imports: [ButtonComponent],
template: `<simurgh-button type="button">Save changes</simurgh-button>`,
})
export class SaveButtonComponent {}

Add the recipe to the application’s global styles entry:

@import '@simurgh-ui/styles/button.css';

Angular exports standalone components. Import the documented component class into the consuming standalone component or NgModule.

Import tokens.css for semantic variables and component recipes for the optional visual layer. Headless behavior does not depend on either stylesheet. Avoid importing the complete recipes.css catalog in production unless the application genuinely uses most components.

Prefer component subpaths so application bundlers receive the narrowest possible graph:

import { Button } from '@simurgh-ui/react/button';
import '@simurgh-ui/styles/button.css';

Each component stylesheet includes the shared tokens, so applications can import only button.css in this example. Import tokens.css separately when an application consumes tokens without a component recipe.

The same pattern applies to Vue (@simurgh-ui/vue/button) and Angular (@simurgh-ui/angular/button). When several primitives are needed together, @simurgh-ui/{framework}/basic provides common non-floating controls, while @simurgh-ui/{framework}/overlays provides dialogs, menus, tooltips, and related positioned UI. The basic boundary intentionally excludes overlay positioning code.

Root adapter imports and @simurgh-ui/styles/all.css remain convenient opt-in aggregates. Use them when the complete catalog is genuinely required; component JavaScript and CSS subpaths are the recommended production default.

Dialogs, menus, tooltips, and other positioned components include Simurgh’s small internal positioning layer. Keep that positioning code out of the initial application bundle by loading an overlay at its route or interaction boundary.

// React
import { lazy } from 'react';
const Dialog = lazy(() =>
import('@simurgh-ui/react/dialog').then((module) => ({
default: module.Dialog,
})),
);
// Vue
import { defineAsyncComponent } from 'vue';
const Dialog = defineAsyncComponent(() =>
import('@simurgh-ui/vue/dialog').then((module) => module.Dialog),
);
// Angular route
{
path: 'dialog-example',
loadComponent: () =>
import('@simurgh-ui/angular/dialog').then(
(module) => module.DialogComponent,
),
}

Lazy loading moves the overlay and positioning layer into an asynchronous chunk. It does not reduce the total downloaded code when the overlay is opened, but it keeps that cost off the initial path.

Last verified on 2026-08-13 against Simurgh registry 0.1.1.