FLOWDocs

Utilities

cn(), useIsMobile(), and shared patterns.

A small set of helpers used by every Flow UI component.

cn()

Merges class names like clsx, but also de-duplicates Tailwind utilities that conflict. Use it anywhere you'd use clsx alone.

import { cn } from "@flow-industries/ui";

cn("p-4", condition && "bg-brand", className);
// → "p-4 bg-brand <whatever caller passed>"

cn("p-4 p-6");
// → "p-6" (later wins, clsx + tailwind-merge de-duped)

Every Flow component calls cn() internally on its root element, so any className you pass composes predictably with the built-in classes.

useIsMobile()

Returns a boolean that flips below a standard breakpoint (default: 768px). Live-updates on resize.

import { useIsMobile } from "@flow-industries/ui";

function Nav() {
  const isMobile = useIsMobile();
  return isMobile ? <MobileNav /> : <DesktopNav />;
}

The hook matches (max-width: 767px). If you need a different breakpoint, write your own with matchMedia — the Flow hook is just the common case.

Shared patterns

render prop (not asChild)

Flow UI is built on Base UI, so composition uses the render prop:

<Button render={<a href="/home" />}>Home</Button>

Renders an <a> with button styles and behavior. Do not use asChild — that's Radix, not Base UI.

data-slot attributes

Every component tags its root with data-slot="<name>". Style or query across consumers without wrestling with generated class names:

[data-slot="button"] {
  font-feature-settings: "tnum";
}

Reduced motion

Motion-driven components — Accordion, Tabs, WordFlash, Dock, and the animated icons — call useReducedMotion() from motion/react to skip or shorten their JS-driven transitions when the user prefers reduced motion. Everything else is covered for free by a global @media (prefers-reduced-motion: reduce) reset in base.css that collapses all remaining CSS animations and transitions, so you never have to wire this up yourself.

No transition-all

Flow UI components specify exact transition properties — transition-colors, transition-[border-color,background-color], never transition-all. If you override styles, match this discipline to avoid accidentally animating padding, font-size, or layout.

On this page