npm package: @geowiki/design-system
Description: The foundational UI component library for the GeoWiki platform. This package provides accessible, themeable components built on [Radix UI](https://www.radix-ui.com/) primitives, a comprehensive icon set, design tokens, and shared utilities — all styled wi
Latest version: 0.16.0-dev.6

# @geowiki/design-system

The foundational UI component library for the GeoWiki platform. This package provides accessible, themeable components built on [Radix UI](https://www.radix-ui.com/) primitives, a comprehensive icon set, design tokens, and shared utilities — all styled with [Tailwind CSS](https://tailwindcss.com/).

## Installation

```bash
pnpm add @geowiki/design-system
```

**Peer dependencies:** `react >= 18.2.0` and `react-dom >= 18.2.0`

## Setup

### 1. Import styles

Import the package stylesheet in your application entry point:

```tsx
import "@geowiki/design-system/styles.css";
```

### 2. Extend Tailwind config

To use the design system's Tailwind theme (colors, typography, animations) in your own components:

```js
// tailwind.config.js
const designSystemConfig = require("@geowiki/design-system/tailwind-config");

/** @type {import('tailwindcss').Config} */
module.exports = {
  presets: [designSystemConfig],
  content: [
    "./src/**/*.{js,ts,jsx,tsx}",
    // Include design-system components in Tailwind's content scan
    "./node_modules/@geowiki/design-system/dist/**/*.{js,mjs}",
  ],
};
```

### 3. Import components

```tsx
import { Button, Dialog, DialogContent, DialogTrigger, cn } from "@geowiki/design-system";
```

## Package Exports

| Export Path                        | Description                                |
| ---------------------------------- | ------------------------------------------ |
| `@geowiki/design-system`          | All components, icons, hooks, and utilities |
| `@geowiki/design-system/styles.css` | Compiled CSS (Tailwind + design tokens)   |
| `@geowiki/design-system/tailwind-config` | Tailwind configuration preset        |

## Component Catalog

### UI Primitives

41 accessible, unstyled-by-default components built on Radix UI, styled with Tailwind and `class-variance-authority`:

| Component | Component | Component | Component |
| --------- | --------- | --------- | --------- |
| Accordion | Alert | AlertDialog | AspectRatio |
| Avatar | Badge | Button | Calendar |
| Card | Checkbox | Collapsible | Command |
| ContextMenu | Dialog | DropdownMenu | Form |
| HoverCard | Input | Label | Menubar |
| NavigationMenu | Popover | Progress | RadioGroup |
| ScrollArea | Select | Separator | Sheet |
| Skeleton | Slider | Switch | Table |
| Tabs | Tag | TagList | Textarea |
| Toast | Toaster | Toggle | Tooltip |
| useToast | | | |

### Icons

28 custom SVG icon components for application UI:

`AccountIcon` `AtomIcon` `BookTextIcon` `CalendarIcon` `CameraIcon` `ChartLineDotsIcon` `ChatsIcons` `ClipboardIcon` `CpuIcon` `DesktopCodeIcon` `FarmerClustersIcon` `GridDividersIcon` `HardDriveIcon` `HeadphonesIcon` `ImageIcon` `LayerGroupIcon` `LegendIcon` `MapLayersIcon` `MicroscopeIcon` `MinusIcon` `PlusIcon` `ResourcesIcon` `SettingsIcon` `StopWatchCheckIcon` `UserGroupIcon` `VideoPlayIcon` `XIcon`

A polymorphic `Icon` component is also available for dynamic icon rendering.

### Map Icons

11 specialized icons for GIS and map visualization:

`Download` `FarmerClusterPin` `Hexagon` `IconPaths` `Legend` `LocationIcon` `MapIcon` `Microscope` `ObservationPin` `Overlay` `UsersGroup`

### Design Elements

22 higher-level, application-specific components:

`AboutInfoItem` `Breadcrumb` `DesignButton` `Carousel` `DesignCheckbox` `Cookies` `Country` `Infobox` `DesignInput` `KeyInfoItem` `LastUpdatedTag` `NoResults` `DesignRadioGroup` `DesignSelect` `SimpleTag` `DesignSwitch` `DesignTag` `TagsGroup` `TestWeight` `ThreeColumn` `Typography` `VersionDisplay`

### Elements

15 utility and presentation components:

`ElementButton` `ButtonLink` `Error` `FeatureDisabled` `IframeViewer` `Loader` `LocalLoader` `MediaEmbedItem` `PermissionDisabled` `ShowLargeText` `ShowShortText` `SizedImage` `UnderConstruction` `DisplayItem`

### Shared Components

Reusable composite components and hooks:

| Component | Description |
| --------- | ----------- |
| `CustomTable` | Data table built on `@tanstack/react-table` |
| `FullPageLoader` | Full-screen loading overlay |
| `CustomImage` | Enhanced image component |
| `Loader` | Inline loading spinner |
| `Pagination` | Page navigation controls |
| `Search` | Search input with debounce |
| `ThemeSwitcher` | Light/dark theme toggle |
| `useDebounce` | Debounce hook for values |

### Buttons & Inputs

| Component | Description |
| --------- | ----------- |
| `DeleteButton` | Destructive action button |
| `PrimaryButton` | Primary CTA button |
| `OldCustomInput` | Legacy styled input |
| `MultiSelect` | Multi-value select (react-select) |
| `TextArea` | Styled textarea |

### Other

| Component | Description |
| --------- | ----------- |
| `UmamiAnalytics` | Umami analytics script injection |
| `HeroImage` | Hero section image component |
| `Horizontal` | Horizontal panel layout |

## Utilities

| Export | Description |
| ------ | ----------- |
| `cn(...inputs)` | Merges class names using `clsx` + `tailwind-merge`. Use this instead of raw string concatenation to avoid Tailwind class conflicts. |
| `getPages(totalItems, pageSize)` | Calculates pagination metadata (total pages, offsets). |

## Models

| Export | Description |
| ------ | ----------- |
| `LinkButtonItem` | TypeScript interface for link button configuration objects. |

## Design Tokens

The package ships a comprehensive set of CSS custom properties defined in `src/styles/tokens.css`. These tokens drive the Tailwind theme and can be overridden for theming.

### Color System

- **Primary scale:** `--primary-50` through `--primary-950` (11 steps)
- **Semantic colors:** `--background`, `--foreground`, `--card`, `--popover`, `--muted`, `--secondary`, `--accent`, `--destructive`, `--border`, `--input`, `--ring`
- **Tag palette:** 11 named tag colors — blue, dark-blue, light-green, dark-green, orange, light-purple, purple, dark-purple, pink, turquoise, yellow
- **Legacy colors:** `--primary-black`, `--primary-green`, `--primary-white`, `--system-error`

### Typography

Fonts: **Montserrat** (primary), **Open Sans**, **Hanken Grotesk**

| Scale | Sizes |
| ----- | ----- |
| Headings | `h1`–`h9` (with accent/italic variants for `h1`, `h2`) |
| Body | `body-12`, `body-14`, `body-15`, `body-16`, `body-18`, `body-20` (with medium/semibold/bold variants) |
| Landing | `landing-title` (80px, with accent italic variant) |
| Caption | `caption` (16px, tracked) |

## Architecture

```
@geowiki/design-system
├── src/
│   ├── components/
│   │   ├── ui/              # Radix UI primitives (41)
│   │   ├── Icons/           # Custom SVG icons (28)
│   │   │   └── MapIcons/    # GIS-specific icons (11)
│   │   ├── DesignElements/  # Application components (22)
│   │   ├── Elements/        # Utility components (15)
│   │   ├── Shared/          # Composite components (8) + hooks
│   │   ├── Button/          # Specialized buttons (2)
│   │   ├── Input/           # Input variants (3)
│   │   ├── Analytics/       # Analytics integration
│   │   ├── Hero/            # Hero section
│   │   └── Panel/           # Panel layouts
│   ├── lib/
│   │   ├── utils.ts         # cn(), getPages()
│   │   ├── models/          # TypeScript interfaces
│   │   └── styles/
│   │       └── tokens.css   # CSS custom properties
│   └── index.tsx            # Barrel export
├── tailwind.config.js       # Tailwind theme (importable as preset)
├── styles.css               # Entry point for CSS build
└── tsup.config.ts           # Build configuration
```

### How it fits in the monorepo

```
geowiki app  →  @geowiki/ui  →  @geowiki/design-system
                (business UI)    (primitives & tokens)
```

`@geowiki/design-system` contains only standalone, dependency-free UI components. It has no knowledge of APIs, state management, or application logic. The `@geowiki/ui` package imports from design-system and adds business-specific behavior (API integration, store bindings, etc.).

## Development

### Scripts

```bash
pnpm build        # Build with tsup + Tailwind CSS
pnpm lint         # ESLint
pnpm type-check   # TypeScript validation
pnpm clean        # Remove dist, node_modules, .turbo
```

### Build output

The build produces three artifacts in `dist/`:

| File | Format | Description |
| ---- | ------ | ----------- |
| `index.js` | CommonJS | Node.js / bundler import |
| `index.mjs` | ESM | Modern bundler import |
| `index.d.ts` | TypeScript | Type declarations |
| `styles.css` | CSS | Minified Tailwind + tokens |

### Adding a new component

1. Create the component in the appropriate `src/components/` subdirectory.
2. Export it from `src/index.tsx`.
3. If the component uses new design tokens, add the CSS custom properties to `src/styles/tokens.css` and map them in `tailwind.config.js`.
4. Run `pnpm build` to verify the build succeeds.

## Tech Stack

| Concern | Library |
| ------- | ------- |
| Component primitives | [Radix UI](https://www.radix-ui.com/) |
| Styling | [Tailwind CSS 3.3](https://tailwindcss.com/) |
| Variant API | [class-variance-authority](https://cva.style/) |
| Class merging | [clsx](https://github.com/lukeed/clsx) + [tailwind-merge](https://github.com/dcastil/tailwind-merge) |
| Icons | Custom SVG + [Lucide React](https://lucide.dev/) + [Heroicons](https://heroicons.com/) |
| Data tables | [@tanstack/react-table](https://tanstack.com/table) |
| Multi-select | [react-select](https://react-select.com/) |
| Calendar | [react-day-picker](https://react-day-picker.js.org/) |
| Carousel | [Embla Carousel](https://www.embla-carousel.com/) |
| Command palette | [cmdk](https://cmdk.paco.me/) |
| Build tool | [tsup](https://tsup.egoist.dev/) |

## License

MIT