---
id: "packages/active-ui/utilities"
title: "Utilities"
description: "Class merging, slugs, the link contract for a host's router, and the code highlighter."
url: "/packages/active-ui/utilities"
locale: "en"
revision: "97c182ef128c31fc"
---

# Utilities

The small functions and types active-ui uses itself, exported for your own components.

**Example: A slug and merged classes**

Client: Runs entirely in your browser. Source: `examples/ui/utilities.tsx`.

```tsx
// apps/docs/examples/ui/utilities.tsx
'use client';

import {useState} from 'react';

import {
  Field,
  FieldDescription,
  FieldLabel,
} from '@workspace/active-ui/components/primitives/field';
import {Input} from '@workspace/active-ui/components/primitives/input';
import {cn, slugify} from '@workspace/active-ui/lib/utils';

/**
 * `slugify` turns a display string into a URL-safe slug; `cn` merges
 * classes so that a later Tailwind class wins over a conflicting one.
 */
export default function UtilitiesExample() {
  const [name, setName] = useState("'s-Hertogenbosch Café");
  return (
    <div className="grid w-full max-w-sm gap-6">
      <Field>
        <FieldLabel htmlFor="slug-source">Name</FieldLabel>
        <Input
          id="slug-source"
          value={name}
          onChange={(event) => setName(event.target.value)}
        />
        <FieldDescription>
          <code>slugify</code>: <code>{slugify(name) || "''"}</code>
        </FieldDescription>
      </Field>
      <p className="text-sm">
        <code>cn(&apos;px-2 py-1&apos;, &apos;px-4&apos;)</code> ={' '}
        <code>&apos;{cn('px-2 py-1', 'px-4')}&apos;</code>
      </p>
    </div>
  );
}
```

## What is here

- `cn(...)`: merges class names, clsx-style arguments included, and resolves Tailwind conflicts so
  the later class wins: `cn('px-2 py-1', 'px-4')` is `'py-1 px-4'`. Every component of the package
  uses it for its `className`.
- `slugify(value)`: a URL-safe slug, lower case, without diacritics, at most 80 characters. For ids
  and URL segments, not for security.
- `LinkComponent` and `LinkComponentProps`: the contract for your router's link. A component that
  renders a link, such as [StatCard](/packages/active-ui/stat-card), takes it as `linkComponent`
  and passes only `href`, `className` and `children`; without it a plain `<a>` is used.
- `loadHighlighter(language)` and `highlightCode(code, language)`: the Shiki highlighter behind
  [CodeBlock](/packages/active-ui/code-block) and [`useHighlightedCode`](/packages/active-ui/hooks).
  Shiki and each language load on first use. The languages are `bash`, `css`, `diff`, `html`,
  `javascript`, `json`, `jsx`, `markdown`, `python`, `sql`, `tsx`, `typescript` and `yaml`, with
  the aliases `js`, `md`, `py`, `sh`, `shell`, `ts`, `yml` and `zsh`; another language stays plain.
  The themes reach AA contrast for every token in light and dark.

## Usage

```tsx
import {highlightCode} from '@workspace/active-ui/lib/highlighter';
import {cn, slugify} from '@workspace/active-ui/lib/utils';

const lines = await highlightCode(source, 'ts'); // in a server component
```

## API

**cn**: `CnFunction`

Merge Tailwind CSS classes with clsx-style arguments (strings, arrays,
objects, conditionals). Drop-in replacement for `twMerge(clsx(...))`.

**slugify**: `(value: string) => string`

Convert an arbitrary display-string into a URL-safe slug.

Lower-cases, strips diacritics via NFD-decomposition, replaces any run of
non-alphanumeric characters with a single hyphen, trims leading/trailing
hyphens, and caps length at 80 characters.

Intended for IDs, slugs, and URL-segments derived from human-readable
text — not for security-critical identifiers (no collision-resistance
guarantee for similar inputs).

**LinkComponentProps**

```ts
interface LinkComponentProps {
  href: string;
  className?: string;
  children: ReactNode;
}
```

What a host link component receives from a component of this package that
renders a link: the destination, the component's class for the link and
its content. Nothing else is passed.

The same three props as the grid's `GridLinkProps` in active-grid, so one
host link serves both.

**LinkComponent**

```ts
type LinkComponent = ComponentType<LinkComponentProps>;
```

A host's own link, for example a router link such as `next/link`, so that
navigation stays client-side. Without one a component renders a plain
`<a href>` and the browser navigates. Passed per instance as the
`linkComponent` prop of `StatCard` and `DashboardServiceRow`.

**loadHighlighter**: `(language: string) => Promise<{ highlight(code: string, state?: GrammarState): { lines: DetailedReactHTMLElement<{ key: number; style: CSSProperties; className: string; }, HTMLElement>[][]; state: GrammarState \| undefined; }; } \| null>`

Loads a language and returns a highlighter for it, or `null` for a language
that is not listed. Shiki and each language load on first use.

**highlightCode**: `(code: string, language: string) => Promise<DetailedReactHTMLElement<{ key: number; style: CSSProperties; className: string; }, HTMLElement>[][] \| null>`

Highlights code once, for a server component or a build step: one React
node per line, with a light and a dark colour per token, or `null` for a
language that is not listed.
