Skip to content
Facade UI
Colour mode
GitHub (opens in a new tab)
lib

cn

Class merging helper: clsx plus tailwind-merge. Identical to shadcn/ui's, so it overwrites nothing meaningful.

Installation

Package manager
pnpm dlx shadcn@latest add https://facadeui.dev/r/utils.json

Pulls in clsx@^2.1.1, tailwind-merge@^3.7.0. The CLI installs them for you.

Source

What the CLI copies into your project, byte for byte.

lib/utils.ts
/**
 * `cn` — the single class-merging helper every Facade UI component uses.
 *
 * clsx resolves conditionals; tailwind-merge resolves Tailwind conflicts so a
 * caller's `className` always wins over a component's defaults.
 *
 * Deliberately identical to shadcn/ui's `lib/utils.ts` so that installing a
 * Facade item into an existing shadcn project overwrites nothing meaningful.
 *
 * Dependencies: clsx, tailwind-merge.
 */

import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]): string {
  return twMerge(clsx(inputs))
}

/**
 * Turns heading text into a stable DOM id for `aria-labelledby`.
 *
 * Sections are server components, so `useId()` is unavailable — and a hydration-
 * stable id derived from content is preferable anyway. Pass an explicit `id` to
 * a section when two headings on one page would otherwise slugify identically.
 */
export function slugId(text: string, prefix = "facade"): string {
  const slug = text
    .normalize("NFKD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "")
    .slice(0, 48)
  return slug ? `${prefix}-${slug}` : `${prefix}-section`
}