npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@molecule/app-ui-tailwind

v1.2.1

Published

Tailwind CSS UI components for molecule.dev

Readme

@molecule/app-ui-tailwind

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Tailwind CSS UI components for molecule.dev.

Provides pre-built, accessible UI components using Tailwind CSS classes. These are framework-agnostic class strings that can be used with any rendering library (React, Vue, Svelte, etc.).

Quick Start

// 1. Wire the ClassMap once at startup (bonds.ts):
import { setClassMap } from '@molecule/app-ui'
import { classMap } from '@molecule/app-ui-tailwind'

setClassMap(classMap)

// 2. In the app's Tailwind v4 CSS entry (e.g. src/index.css):
//      @import 'tailwindcss';
//      @import '@molecule/app-ui-tailwind/base.css';   <- theme tokens
//      @source "../node_modules/@molecule/app-ui-tailwind/dist";  <- keep
//        Tailwind's purge from stripping the classes this package emits
// (Scaffolded molecule apps already have both — this is only needed when
//  integrating into an app not generated by mlcl.)

// 3. Resolve classes anywhere via the ClassMap — never hardcode Tailwind:
import { getClassMap } from '@molecule/app-ui'
const cm = getClassMap()
element.className = cm.button({ color: 'primary', size: 'md' })

Type

provider

Installation

npm install @molecule/app-ui-tailwind @molecule/app-styling @molecule/app-ui

API

Interfaces

CVAConfig

Configuration for a class-variance-authority (cva) function: the variant definitions, default selections, and compound variants used to resolve a component's final class string from its props.

interface CVAConfig<T extends Record<string, Record<string, string>>> {
  variants?: T
  defaultVariants?: {
    [K in keyof T]?: keyof T[K]
  }
  compoundVariants?: Array<
    {
      [K in keyof T]?: keyof T[K]
    } & {
      class: string
    }
  >
}

Types

ClassValue

Class name value types accepted by {@link cn}.

type ClassValue =
  | string
  | number
  | boolean
  | undefined
  | null
  | ClassValue[]
  | Record<string, boolean | undefined | null>

Constants

accordion

Accordion component classes.

const accordion: 'w-full'

accordionChevron

Accordion chevron icon classes (rotates on open).

const accordionChevron: 'h-4 w-4 shrink-0 transition-transform duration-200'

accordionContent

Accordion content wrapper classes with collapse animation.

const accordionContent: 'overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down'

accordionContentInner

The accordion content inner.

const accordionContentInner: 'pb-4 pt-0'

accordionItem

The accordion item.

const accordionItem: 'border-b'

accordionTrigger

The accordion trigger.

const accordionTrigger: (
  props?: ({ variant?: 'default' | 'bordered' | undefined } & { class?: string }) | undefined,
) => string

accordionTriggerBase

The accordion trigger base.

const accordionTriggerBase: 'w-full text-left'

actionSheet

Action sheet: bottom-anchored panel for pickers and action menus.

const actionSheet: 'fixed bottom-0 left-0 right-0 z-[1300] bg-surface rounded-t-2xl max-h-[50vh] overflow-hidden'

actionSheetHeader

Action sheet header with bottom border.

const actionSheetHeader: 'flex-shrink-0 px-4 py-3 border-b border-border'

alert

Alert component classes with variant support (default, info, success, warning, error).

const alert: (
  props?:
    | ({ variant?: 'default' | 'success' | 'warning' | 'error' | 'info' | undefined } & {
        class?: string
      })
    | undefined,
) => string

alertContent

The alert content.

const alertContent: 'flex-1'

alertDescription

The alert description.

const alertDescription: 'text-sm [&_p]:leading-relaxed'

alertDismiss

The alert dismiss.

const alertDismiss: 'flex-shrink-0 ml-2 p-1 rounded hover:bg-black/5 transition-colors'

alertIconWrapper

Alert icon wrapper classes.

const alertIconWrapper: 'flex-shrink-0'

alertTitle

The alert title.

const alertTitle: 'mb-1 font-medium leading-none tracking-tight'

appLayout

Main app layout classes (min-height, horizontal/bottom padding). No top padding: the shell renders the header IN FLOW (AppHeader's fixed default contributes no position utility — headerFixed is offsets only), so a top pad cleared a header that never overlapped the content and every page opened with a phantom 55px gap. Apps with a genuinely fixed/sticky header add their own top padding.

const appLayout: 'min-h-screen px-[15px] pb-[55px]'

authAfterSubmit

The auth after submit.

const authAfterSubmit: 'mt-[15px]'

authArrowIcon

The auth arrow icon.

const authArrowIcon: 'ml-[2.5px]'

authBackButton

The auth back button.

const authBackButton: 'w-[45px] mr-[10px]'

authButtonRow

Auth button row (flex container).

const authButtonRow: 'flex'

authField

The auth field.

const authField: 'mb-[15px]'

authFormError

Auth form error message classes.

const authFormError: 'text-error mt-[15px]'

authFormWrapper

The auth form wrapper.

const authFormWrapper: 'w-max min-w-[330px] max-w-[90vw] py-[30px] mx-auto text-center'

authHeaderInner

Auth page header inner container classes.

const authHeaderInner: 'w-full h-10 p-[5px]'

authHidden

The auth hidden.

const authHidden: 'hidden'

authLoginSignup

The auth login signup.

const authLoginSignup: 'grow whitespace-nowrap mr-[10px]'

authLoginSubmit

The auth login submit.

const authLoginSubmit: 'grow whitespace-nowrap'

authLoginSubmitFull

The auth login submit full.

const authLoginSubmitFull: 'w-full whitespace-nowrap'

authPageBody

The auth page body.

const authPageBody: 'flex flex-col flex-1 items-center justify-center px-4 pb-[30px]'

authSubmitButton

The auth submit button.

const authSubmitButton: 'grow whitespace-nowrap'

avatar

Avatar component classes.

const avatar: (
  props?: ({ size?: 'sm' | 'md' | 'lg' | 'xl' | undefined } & { class?: string }) | undefined,
) => string

avatarFallback

Avatar fallback container classes (centered, rounded, secondary background).

const avatarFallback: 'flex h-full w-full items-center justify-center rounded-full bg-surface-secondary text-foreground-secondary'

avatarFallbackIcon

The avatar fallback icon.

const avatarFallbackIcon: 'h-1/2 w-1/2'

avatarImage

The avatar image.

const avatarImage: 'aspect-square h-full w-full object-cover'

avatarInitials

Avatar initials text classes.

const avatarInitials: 'text-sm font-medium'

avatarSquare

The avatar square.

const avatarSquare: 'rounded-md'

badge

Badge component classes with variant support.

const badge: (
  props?:
    | ({
        variant?: 'default' | 'secondary' | 'success' | 'outline' | 'warning' | 'error' | undefined
      } & { class?: string })
    | undefined,
) => string

badgeSquare

Badge with square (rounded-md) corners.

const badgeSquare: 'rounded-md'

bgBorder

Tailwind class for a background matching the theme border color.

const bgBorder: 'bg-border'

bgErrorSubtle

Subtle error background utility class.

const bgErrorSubtle: 'bg-error-light'

bgPrimaryContainer

Primary-tinted container surface; pair with {@link textOnPrimaryContainer}.

const bgPrimaryContainer: 'bg-primary-container'

borderAll

The border all.

const borderAll: 'border border-border'

borderB

Bottom border with theme border color.

const borderB: 'border-b border-border'

borderBPrimary

The border b primary.

const borderBPrimary: 'border-b-2 border-b-primary'

borderR

Tailwind classes for a right border with the theme border color.

const borderR: 'border-r border-border'

borderT

Tailwind classes for a top border with the theme border color.

const borderT: 'border-t border-border'

button

Button component classes.

const button: (
  props?:
    | ({
        variant?:
          | 'default'
          | 'secondary'
          | 'success'
          | 'outline'
          | 'ghost'
          | 'link'
          | 'warning'
          | 'danger'
          | undefined
        size?: 'sm' | 'md' | 'lg' | 'icon' | undefined
      } & { class?: string })
    | undefined,
) => string

buttonIconLeft

Button left icon spacing classes.

const buttonIconLeft: 'mr-2'

buttonIconRight

The button icon right.

const buttonIconRight: 'ml-2'

buttonSpinner

The button spinner.

const buttonSpinner: 'mr-2'

card

Card component classes.

const card: (
  props?:
    | ({ variant?: 'default' | 'outline' | 'ghost' | 'elevated' | undefined } & { class?: string })
    | undefined,
) => string

cardContent

The card content.

const cardContent: 'p-6 pt-0'

cardDescription

The card description.

const cardDescription: 'text-sm text-foreground-secondary'

cardFooter

The card footer.

const cardFooter: 'flex items-center p-6 pt-0'

cardHeader

The card header.

const cardHeader: 'flex flex-col space-y-1.5 p-6'

cardInteractive

Interactive card classes (hover shadow effect).

const cardInteractive: 'cursor-pointer hover:shadow-md transition-shadow'

cardTitle

The card title.

const cardTitle: 'text-lg font-semibold leading-none tracking-tight'

center

Center layout classes.

const center: 'flex items-center justify-center'

checkbox

Checkbox component classes.

const checkbox: (
  props?: ({ variant?: 'default' | 'error' | undefined } & { class?: string }) | undefined,
) => string

classMap

Tailwind CSS UIClassMap implementation mapping abstract UI tokens to Tailwind class strings.

const classMap: UIClassMap

cn

Merges class names, filtering out falsy values. Supports strings, numbers, conditional objects, and nested arrays.

When a class merger is registered via {@link setClassMerger} (e.g. the Tailwind bond registers tailwind-merge), conflicting utilities such as two gap-* classes are resolved by it; otherwise the joined string is returned as-is.

const cn: (...classes: ClassValue[]) => string

container

Container component classes.

const container: (
  props?:
    | ({ size?: 'sm' | 'md' | 'lg' | 'xl' | 'full' | '2xl' | undefined } & { class?: string })
    | undefined,
) => string

controlContainer

The control container.

const controlContainer: 'flex items-center'

controlDisabled

The control disabled.

const controlDisabled: 'opacity-50 cursor-not-allowed'

controlLabel

Control (checkbox/switch/radio) label wrapper classes.

const controlLabel: 'flex items-center gap-2 cursor-pointer'

controlText

The control text.

const controlText: 'text-sm'

cursorPointer

The cursor pointer.

const cursorPointer: 'cursor-pointer'

cva

Creates a class variance authority (CVA) function for component variants. Given a base class and variant configuration, returns a function that resolves the final class string based on selected variants.

const cva: <T extends Record<string, Record<string, string>>>(
  base: string,
  config?: CVAConfig<T>,
) => (props?: { [K in keyof T]?: keyof T[K] } & { class?: string }) => string

dialogBody

The dialog body.

const dialogBody: 'flex-1 min-h-0 overflow-y-auto px-6 py-6'

dialogClose

Dialog close button classes.

const dialogClose: 'flex-shrink-0 ml-4 -mr-4 p-1.5 cursor-pointer text-foreground-secondary hover:text-foreground transition-colors focus:outline-none'

dialogCloseFloating

Floating close for title-less dialogs — overlays the top-right corner of the dialog box (dialogContent is relative) instead of rendering a header row that pushes the body down.

const dialogCloseFloating: 'absolute right-3 top-3 z-10 p-1.5 cursor-pointer text-foreground-secondary hover:text-foreground transition-colors focus:outline-none'

dialogContent

The dialog content.

const dialogContent: (
  props?:
    ({ size?: 'sm' | 'md' | 'lg' | 'xl' | 'full' | undefined } & { class?: string }) | undefined,
) => string

dialogDescription

The dialog description.

const dialogDescription: 'text-sm text-foreground-secondary'

dialogFooter

Dialog footer classes.

const dialogFooter: 'flex-shrink-0 flex flex-col-reverse px-6 py-4 border-t border-border sm:flex-row sm:justify-end sm:space-x-2'

dialogHeader

The dialog header.

const dialogHeader: 'flex-shrink-0 flex items-center justify-between px-6 py-2'

dialogOverlay

Modal/Dialog overlay classes — the TINT only. The backdrop blur lives on {@link dialogWrapper} (the dialog's PARENT), never here: a backdrop-filter on a same-z sibling relies on DOM paint order, and browser-extension DOM injection (e.g. Bitwarden's autofill overlay) can trigger a Chromium recomposite that momentarily sorts the filter layer above the dialog — blurring the dialog itself. A parent's backdrop-filter can never affect its children, by spec.

const dialogOverlay: 'fixed inset-0 z-[1300] bg-overlay pointer-events-none'

dialogTitle

The dialog title.

const dialogTitle: 'text-xl font-semibold leading-tight tracking-tight'

dialogWrapper

The dialog wrapper. Carries the backdrop blur (see {@link dialogOverlay} for why it must be on the dialog's parent, not a sibling) and sits one z above the tint overlay so the dialog's stacking never depends on DOM order.

const dialogWrapper: 'fixed inset-0 z-[1301] flex items-center justify-center px-4 py-10 backdrop-blur-[2px]'

displayBlock

Display block utility class.

const displayBlock: 'block'

displayContents

The display contents.

const displayContents: 'contents'

displayInlineBlock

The display inline block.

const displayInlineBlock: 'inline-block'

dropdownContent

Dropdown menu content container classes.

const dropdownContent: 'z-[1000] min-w-[8rem] overflow-hidden rounded-md border bg-surface p-1 text-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95'

dropdownItem

Dropdown menu item classes.

const dropdownItem: 'relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-surface-secondary focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50'

dropdownItemDisabled

The dropdown item disabled.

const dropdownItemDisabled: 'opacity-50 cursor-not-allowed'

dropdownItemIcon

The dropdown item icon.

const dropdownItemIcon: 'mr-2 flex-shrink-0'

dropdownItemLabel

The dropdown item label.

const dropdownItemLabel: 'flex-1'

dropdownItemShortcut

The dropdown item shortcut.

const dropdownItemShortcut: 'ml-auto text-xs text-foreground-tertiary'

dropdownLabel

The dropdown label.

const dropdownLabel: 'px-2 py-1.5 text-sm font-semibold'

dropdownSeparator

The dropdown separator.

const dropdownSeparator: '-mx-1 my-1 h-px bg-border'

dropdownTrigger

Dropdown trigger wrapper classes.

const dropdownTrigger: 'inline-block'

emptyState

EmptyState root — centered column layout.

const emptyState: 'flex flex-col items-center justify-center py-16 px-4 text-center'

emptyStateAction

EmptyState action slot.

const emptyStateAction: ''

emptyStateDescription

EmptyState description.

const emptyStateDescription: 'text-sm text-gray-500 dark:text-gray-400 mb-6 max-w-md'

emptyStateIcon

EmptyState icon wrapper.

const emptyStateIcon: 'mb-4 text-gray-400 dark:text-gray-500'

emptyStateTitle

EmptyState heading.

const emptyStateTitle: 'text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2'

flex

Flex layout classes.

const flex: (
  props?:
    | ({
        direction?: 'row' | 'row-reverse' | 'col' | 'col-reverse' | undefined
        align?: 'center' | 'start' | 'end' | 'stretch' | 'baseline' | undefined
        justify?: 'center' | 'start' | 'end' | 'between' | 'around' | 'evenly' | undefined
        wrap?: 'wrap' | 'nowrap' | 'wrap-reverse' | undefined
        gap?: 'sm' | 'md' | 'lg' | 'xl' | 'none' | 'xs' | undefined
      } & { class?: string })
    | undefined,
) => string

flex1

Flex grow utility class (flex-1).

const flex1: 'flex-1'

floatingInput

The floating input.

const floatingInput: 'peer'

floatingInputWrapper

Floating input wrapper classes (relative container).

const floatingInputWrapper: 'relative inline-block align-middle w-full'

floatingLabel

Floating label classes (absolute positioned, animated on focus).

const floatingLabel: 'absolute top-0 left-0 right-0 w-full p-[3px] text-[11px] leading-none whitespace-nowrap text-foreground pointer-events-none transition-all duration-250 peer-hover:bg-input-background peer-focus:text-primary peer-focus:[text-shadow:0_0_var(--color-primary)] peer-focus:bg-input-background'

footerBar

Footer bar classes (full-width). Position is determined by the consuming layout, not forced here.

const footerBar: 'w-full flex flex-wrap items-center justify-around p-[5px] bg-background text-[12px] text-foreground-secondary'

footerButton

Footer button classes.

const footerButton: 'inline-flex items-center gap-1 border-0 m-0 p-[5px] text-[12px] text-foreground-secondary hover:text-foreground bg-transparent cursor-pointer'

footerLink

Footer link classes.

const footerLink: 'p-[5px] text-[12px] text-foreground-secondary hover:text-foreground no-underline'

forgotPasswordLink

Forgot password link classes.

const forgotPasswordLink: 'border-0 p-0 m-0 bg-transparent text-foreground-secondary text-[12px] cursor-pointer hover:text-primary'

formError

Form error message classes.

const formError: 'text-sm text-error mt-1'

formField

The form field.

const formField: 'space-y-1.5'

formFieldset

The form fieldset.

const formFieldset: 'space-y-4'

formFieldsetContents

The form fieldset contents.

const formFieldsetContents: 'contents'

formFieldWrapper

The form field wrapper.

const formFieldWrapper: 'flex flex-col'

formHint

Form hint message classes.

const formHint: 'text-sm text-foreground-secondary mt-1'

grid

Grid layout classes.

These cols values are the FIXED (non-responsive) column classes — a grid that is cols-wide at every viewport width. The ClassMap grid resolver (see classMap.ts) uses these only for the opt-out (responsive: false) and single-column paths; by DEFAULT it emits the mobile-first ramp in {@link gridResponsiveCols} instead.

const grid: (
  props?:
    | ({
        cols?: 1 | 2 | 3 | 4 | 5 | 6 | 12 | undefined
        gap?: 'sm' | 'md' | 'lg' | 'xl' | 'none' | 'xs' | undefined
      } & { class?: string })
    | undefined,
) => string

gridResponsiveCols

Mobile-first responsive column ramps for cm.grid({ cols }).

Each value is a COMPLETE, literal Tailwind class string (never built by template interpolation) so Tailwind's scanner picks it up from this package's compiled dist (see the @source note in index.ts), and base.css safelists the same set. A multi-column grid starts at one column on phones and steps up to the requested cols at sm/lg/xl, so KPI / listing / card grids COLLAPSE on mobile instead of overflowing. cols: 1 stays single-column. The ClassMap grid resolver uses this as the DEFAULT for cols >= 2; pass responsive: false there for the fixed grid-cols-N from the {@link grid} CVA above. Every emitted token is a real Tailwind utility (grid-cols-1..6, grid-cols-12, and the sm:/lg:/xl: variants of each).

const gridResponsiveCols: Record<number, string>

headerFixed

Header container classes (full-width). Position is determined by the consuming layout, not forced here.

const headerFixed: 'top-0 left-0 right-0 w-full'

headerInner

The header inner.

const headerInner: 'w-full max-w-[1280px] mx-auto h-10 p-[5px]'

hstack

HStack layout classes (horizontal flexbox).

const hstack: (
  props?:
    | ({
        justify?: 'center' | 'start' | 'end' | 'between' | undefined
        gap?: 'sm' | 'md' | 'lg' | 'xl' | 'none' | 'xs' | undefined
      } & { class?: string })
    | undefined,
) => string

iconMd

Tailwind classes for medium icons (20x20).

const iconMd: 'h-5 w-5'

iconSm

Tailwind classes for small icons (16x16).

const iconSm: 'h-4 w-4'

iconXs

Icon extra-small size classes (12×12).

const iconXs: 'h-3 w-3'

input

Input component classes.

const input: (
  props?:
    | ({
        variant?: 'default' | 'error' | undefined
        size?: 'sm' | 'md' | 'lg' | undefined
        align?: 'left' | 'center' | undefined
      } & { class?: string })
    | undefined,
) => string

inputClearButton

The input clear button.

const inputClearButton: 'text-foreground-secondary hover:text-foreground'

inputInner

The input inner.

const inputInner: 'relative'

inputLeftElement

Input left addon/icon container classes.

const inputLeftElement: 'absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none text-foreground-secondary'

inputPadLeft

The input pad left.

const inputPadLeft: 'pl-10'

inputPadRight

The input pad right.

const inputPadRight: 'pr-10'

inputRightElement

The input right element.

const inputRightElement: 'absolute inset-y-0 right-0 flex items-center pr-3'

inputWrapper

Input wrapper classes.

const inputWrapper: 'w-full'

label

Label component classes.

const label: (
  props?: ({ required?: 'true' | 'false' | undefined } & { class?: string }) | undefined,
) => string

labelBlock

Block-level label classes.

const labelBlock: 'mb-1.5 block'

languageActive

Language option (active/selected) classes. Same coarse-pointer touch floor as {@link languageOption}.

const languageActive: 'px-3 py-2 rounded-md text-sm cursor-pointer text-center transition-colors bg-primary/15 text-primary font-medium pointer-coarse:min-h-[44px] pointer-coarse:flex pointer-coarse:items-center pointer-coarse:justify-center'

languageGrid

Language selector grid container classes.

const languageGrid: 'grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2 max-h-96 overflow-y-auto p-2'

languageOption

Language option (inactive) classes. On coarse pointers (touch) the row grows to the 44px touch floor and centers its label with flex (text-center alone cannot center flex items, hence justify-center); fine-pointer rendering is unchanged.

const languageOption: 'px-3 py-2 rounded-md text-sm cursor-pointer text-center transition-colors hover:bg-surface-secondary pointer-coarse:min-h-[44px] pointer-coarse:flex pointer-coarse:items-center pointer-coarse:justify-center'

languagePickerTrigger

Language picker trigger button classes (globe icon + native locale name). Inherits surface/foreground tokens so it sits cleanly inside Settings cards, header chrome, or footers without forcing a specific background.

const languagePickerTrigger: 'inline-flex items-center gap-2 px-3 py-2 rounded-md text-sm font-medium bg-transparent text-foreground-secondary hover:text-foreground hover:bg-surface-secondary border border-border-secondary cursor-pointer transition-colors'

logoIcon

Tailwind class for the logo icon color.

const logoIcon: 'text-primary'

logoText

Logo text classes (tracked, 26px).

const logoText: 'text-[26px] leading-[26px] tracking-[-1px]'

mxAuto

Horizontal auto-margin centering utility class.

const mxAuto: 'mx-auto'

notSrOnly

The not sr only.

const notSrOnly: 'not-sr-only'

oauthButton

OAuth provider button classes.

const oauthButton: 'group grow basis-[40px] flex flex-col justify-center items-center min-h-[60px] bg-surface border-0 rounded-[3px] cursor-pointer p-0 transition-all duration-250 hover:bg-surface-hover'

oauthButtonGroup

OAuth provider button group container classes.

const oauthButtonGroup: 'flex flex-wrap gap-[15px] w-full max-w-[330px] mx-auto justify-center items-center'

oauthButtonIcon

OAuth provider button icon classes.

const oauthButtonIcon: 'opacity-75 group-hover:opacity-100 text-foreground transition-opacity'

oauthDivider

OAuth divider classes (horizontal line with text).

const oauthDivider: 'relative mt-[45px] mb-[15px] text-[15px] text-center uppercase text-foreground-secondary'

oauthDividerLine

OAuth divider horizontal line classes.

const oauthDividerLine: 'absolute top-1/2 left-0 right-0 w-full h-[1px] border-t border-[rgba(170,170,170,0.33)]'

oauthDividerText

The oauth divider text.

const oauthDividerText: 'relative px-[15px] bg-background'

oauthProviderLabel

OAuth provider label (fallback when no icon).

const oauthProviderLabel: 'text-sm font-medium'

pageHeader

PageHeader root container.

const pageHeader: 'mb-6'

pageHeaderActions

PageHeader action buttons container.

const pageHeaderActions: 'flex gap-2 mt-4 sm:mt-0'

pageHeaderBreadcrumbItem

PageHeader breadcrumb item.

const pageHeaderBreadcrumbItem: 'hover:text-gray-700 dark:hover:text-gray-200'

pageHeaderBreadcrumbs

PageHeader breadcrumb trail.

const pageHeaderBreadcrumbs: 'flex items-center gap-1 text-sm text-gray-500 dark:text-gray-400 mb-2'

pageHeaderBreadcrumbSeparator

PageHeader breadcrumb separator.

const pageHeaderBreadcrumbSeparator: 'mx-1'

pageHeaderDescription

PageHeader description.

const pageHeaderDescription: 'mt-1 text-sm text-gray-500 dark:text-gray-400'

pageHeaderTitle

PageHeader title.

const pageHeaderTitle: 'text-2xl font-bold text-gray-900 dark:text-gray-100'

pageShell

PageShell root — flex row filling the screen.

Use this pattern (or an equivalent flex row on the page root) whenever a persistent sidebar and <main> are siblings. A full-height sticky sidebar in block flow (no flex row on the parent) still occupies vertical space, so <main> with only ml-[…] starts below the viewport — content appears under fixed headers / near the bottom. Prefer pageShell + pageShellSidebar, or a fixed inset-y-0 sidebar plus horizontal offset on main.

const pageShell: 'flex h-screen overflow-hidden'

pageShellContent

PageShell main content area.

const pageShellContent: 'flex-1 overflow-y-auto'

pageShellSidebar

PageShell sidebar — fixed-width left panel.

const pageShellSidebar: 'w-60 flex-shrink-0 border-r border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 overflow-y-auto transition-all duration-300'

pageShellSidebarCollapsed

PageShell sidebar collapsed modifier — narrow width.

const pageShellSidebarCollapsed: 'w-16'

pageShellSidebarToggle

PageShell sidebar collapse/expand toggle button.

const pageShellSidebarToggle: 'p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors'

pageShellTopbar

PageShell top bar — horizontal strip above content.

const pageShellTopbar: 'h-14 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 flex items-center px-4 gap-3'

pagination

Pagination component classes.

const pagination: 'mx-auto flex w-full justify-center'

paginationContent

The pagination content.

const paginationContent: 'flex flex-row items-center gap-1'

paginationEllipsis

The pagination ellipsis.

const paginationEllipsis: 'flex h-9 w-9 items-center justify-center'

paginationInteractive

Pagination interactive item (cursor pointer).

const paginationInteractive: 'cursor-pointer'

paginationItem

The pagination item.

const paginationItem: (
  props?:
    | ({ variant?: 'default' | 'active' | undefined; size?: 'sm' | 'md' | 'lg' | undefined } & {
        class?: string
      })
    | undefined,
) => string

paginationLink

The pagination link.

const paginationLink: 'cursor-pointer'

paginationNext

The pagination next.

const paginationNext: 'gap-1 pr-2.5'

paginationPrevious

The pagination previous.

const paginationPrevious: 'gap-1 pl-2.5'

progress

Progress component classes.

const progress: 'relative h-2 w-full overflow-hidden rounded-full bg-surface-secondary'

progressIndeterminate

The progress indeterminate.

const progressIndeterminate: 'animate-indeterminate-progress'

progressIndicator

The progress indicator.

const progressIndicator: 'h-full w-full flex-1 bg-primary transition-all'

progressLabelContainer

The progress label container.

const progressLabelContainer: 'flex justify-between mb-1 text-sm'

progressLabelText

The progress label text.

const progressLabelText: 'text-foreground-secondary'

progressWrapper

Progress bar wrapper classes.

const progressWrapper: 'w-full'

radio

Radio component classes.

const radio: (
  props?: ({ variant?: 'default' | 'error' | undefined } & { class?: string }) | undefined,
) => string

radioGroupLabel

Radio group label classes.

const radioGroupLabel: 'text-sm font-medium mb-2 block'

roundedFull

The rounded full.

const roundedFull: 'rounded-full'

select

Select component classes.

const select: (
  props?:
    | ({ variant?: 'default' | 'error' | undefined; size?: 'sm' | 'md' | 'lg' | undefined } & {
        class?: string
      })
    | undefined,
) => string

selectNative

Native select appearance reset classes.

const selectNative: 'appearance-none'

separator

Separator component classes with horizontal/vertical orientation.

const separator: (
  props?:
    ({ orientation?: 'horizontal' | 'vertical' | undefined } & { class?: string }) | undefined,
) => string

skeleton

Skeleton component classes.

const skeleton: 'animate-pulse rounded-md bg-surface-secondary'

skeletonCircle

The skeleton circle.

const skeletonCircle: 'rounded-full'

skeletonNone

The skeleton none.

const skeletonNone: 'animate-none'

skeletonTextContainer

Skeleton text placeholder container (vertical spacing).

const skeletonTextContainer: 'space-y-2'

skeletonWave

Skeleton wave animation classes (shimmer gradient effect).

const skeletonWave: 'animate-shimmer bg-gradient-to-r from-surface-secondary via-surface to-surface-secondary bg-[length:200%_100%]'

spinner

Spinner component classes with size variants.

const spinner: (
  props?: ({ size?: 'sm' | 'md' | 'lg' | 'xl' | undefined } & { class?: string }) | undefined,
) => string

srOnly

Screen reader only classes.

const srOnly: 'sr-only'

stack

Stack layout classes (vertical flexbox).

const stack: (
  props?:
    | ({
        align?: 'center' | 'start' | 'end' | 'stretch' | undefined
        gap?: 'sm' | 'md' | 'lg' | 'xl' | 'none' | 'xs' | undefined
      } & { class?: string })
    | undefined,
) => string

surfaceSecondary

Secondary surface background utility class.

const surfaceSecondary: 'bg-surface-secondary'

switchBase

Switch component classes.

The color axis maps 1:1 to the semantic ColorVariant scale (same primary/secondary/success/warning/error/info tokens progressColor already uses) — no lookup table needed, unlike button's differently-named CVA variants.

const switchBase: (
  props?:
    | ({
        color?: 'secondary' | 'success' | 'warning' | 'error' | 'primary' | 'info' | undefined
        size?: 'sm' | 'md' | 'lg' | undefined
      } & { class?: string })
    | undefined,
) => string

switchThumb

Switch thumb (the sliding circle) classes.

const switchThumb: (
  props?: ({ size?: 'sm' | 'md' | 'lg' | undefined } & { class?: string }) | undefined,
) => string

table

Table root classes.

const table: 'w-full caption-bottom text-sm'

tableBody

The table body.

const tableBody: '[&_tr:last-child]:border-0'

tableBordered

The table bordered.

const tableBordered: 'border'

tableCaption

The table caption.

const tableCaption: 'mt-4 text-sm text-foreground-secondary'

tableCell

The table cell.

const tableCell: 'p-4 align-middle [&:has([role=checkbox])]:pr-0'

tableEmptyCell

The table empty cell.

const tableEmptyCell: 'py-10 text-center text-foreground-secondary'

tableFooter

The table footer.

const tableFooter: 'border-t bg-surface-secondary font-medium [&>tr]:last:border-b-0'

tableHead

Table header cell classes.

const tableHead: 'h-12 px-4 text-left align-middle font-medium text-foreground-secondary [&:has([role=checkbox])]:pr-0'

tableHeader

The table header.

const tableHeader: '[&_tr]:border-b'

tableHeadSortable

The table head sortable.

const tableHeadSortable: 'cursor-pointer select-none hover:bg-surface-secondary'

tableLoadingOverlay

Table loading overlay classes (semi-transparent centered spinner container).

const tableLoadingOverlay: 'absolute inset-0 bg-background/50 flex items-center justify-center z-10'

tableRow

Table row classes.

const tableRow: 'border-b transition-colors hover:bg-surface-secondary data-[state=selected]:bg-surface-secondary'

tableRowClickable

The table row clickable.

const tableRowClickable: 'cursor-pointer'

tableRowHoverable

The table row hoverable.

const tableRowHoverable: 'hover:bg-surface-secondary'

tableRowStriped

The table row striped.

const tableRowStriped: 'bg-surface-secondary/50'

tableSortIcon

The table sort icon.

const tableSortIcon: 'ml-1'

tableSortWrapper

The table sort wrapper.

const tableSortWrapper: 'flex items-center gap-1'

tableWrapper

Table wrapper classes (scrollable container).

const tableWrapper: 'relative w-full overflow-auto'

tabsContent

Tabs content (panel) classes.

variant only adjusts the top spacing beneath the tablist — enclosed (the default) reproduces the single style this used to be hardcoded to, token-for-token.

const tabsContent: (
  props?:
    | ({ variant?: 'line' | 'enclosed' | 'soft-rounded' | 'solid-rounded' | undefined } & {
        class?: string
      })
    | undefined,
) => string

tabsFitted

Fitted (full-width) tabs container classes.

const tabsFitted: 'w-full'

tabsList

Tabs list (tablist container) classes.

variant controls shape/background (a full-width underline rail for line; a filled/bordered box for enclosed; a soft or solid pill track for *-rounded); size controls only the container height, so it never conflicts with tabsTrigger's own size-driven padding.

enclosed+md (the defaults) reproduce the single style this used to be hardcoded to, token-for-token.

const tabsList: (
  props?:
    | ({
        variant?: 'line' | 'enclosed' | 'soft-rounded' | 'solid-rounded' | undefined
        size?: 'sm' | 'md' | 'lg' | undefined
      } & { class?: string })
    | undefined,
) => string

tabsTrigger

Tabs trigger (individual tab button) classes.

variant controls the shape/color of the ACTIVE state via data-[state=active]:* attribute selectors — the caller (see @molecule/app-ui-react's Tabs) sets data-state="active"|"inactive" on the element; nothing here reads a JS active flag. size controls padding/font-size only, shared across every variant so it can never conflict with a variant's own classes.

enclosed+md (the defaults) reproduce the single style this used to be hardcoded to, token-for-token.

const tabsTrigger: (
  props?:
    | ({
        variant?: 'line' | 'enclosed' | 'soft-rounded' | 'solid-rounded' | undefined
        size?: 'sm' | 'md' | 'lg' | undefined
      } & { class?: string })
    | undefined,
) => string

tabTriggerFitted

The tab trigger fitted.

const tabTriggerFitted: 'flex-1'

tabTriggerIcon

The tab trigger icon.

const tabTriggerIcon: 'mr-2'

textarea

Textarea component classes.

const textarea: (
  props?:
    | ({ variant?: 'default' | 'error' | undefined; size?: 'sm' | 'md' | 'lg' | undefined } & {
        class?: string
      })
    | undefined,
) => string

textOnPrimaryContainer

Readable text on {@link bgPrimaryContainer}.

const textOnPrimaryContainer: 'text-on-primary-container'

textPrimary

Primary text color utility class.

const textPrimary: 'text-primary'

textRight

Text right-alignment utility class.

const textRight: 'text-right'

textSuccess

The text success.

const textSuccess: 'text-success'

textWarning

The text warning.

const textWarning: 'text-warning'

themeToggleButton

Theme toggle button classes.

const themeToggleButton: 'h-10 w-10 p-0 border-0 bg-transparent text-foreground-secondary hover:text-foreground cursor-pointer flex items-center justify-center'

toast

Tailwind toast notification variant classes (default, success, error, warning).

const toast: (
  props?:
    | ({ variant?: 'default' | 'success' | 'warning' | 'error' | 'info' | undefined } & {
        class?: string
      })
    | undefined,
) => string

toastAction

Toast action button classes.

const toastAction: 'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-surface-secondary focus:outline-none focus:ring-2 disabled:pointer-events-none disabled:opacity-50'

toastClose

Toast close button classes.

const toastClose: 'absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100'

toastContentWrapper

The toast content wrapper.

const toastContentWrapper: 'flex-1 gap-1'

toastDescription

The toast description.

const toastDescription: 'text-sm opacity-90'

toastIconWrapper

Toast icon wrapper classes.

const toastIconWrapper: 'flex-shrink-0'

toastTitle

The toast title.

const toastTitle: 'text-sm font-semibold'

toastViewport

Toast viewport container classes (positioned fixed, stacked).

const toastViewport: 'fixed top-0 z-[1600] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]'

tooltipContent

Tooltip content container classes.

const tooltipContent: 'z-[1500] max-w-[90vw] overflow-hidden whitespace-nowrap rounded-md border bg-surface px-3 py-1.5 text-sm text-foreground shadow-md animate-in fade-in-0 zoom-in-95'

tooltipTrigger

Tooltip trigger wrapper classes.

const tooltipTrigger: 'inline-block'

Core Interface

Implements @molecule/app-ui interface.

Injection Notes

Requirements

Peer dependencies:

  • @molecule/app-styling ^1.0.1
  • @molecule/app-ui ^1.2.0

Runtime Dependencies

  • @molecule/app-styling
  • @molecule/app-ui

Theming / where colors come from: the class strings here use semantic tokens (bg-primary, text-primary, bg-surface, …), NOT literal palette classes (bg-blue-600). Those tokens are defined in this package's base.css @theme block, where the ~15 CORE colors read --color-primary: var(--mol-color-primary, <default>) (from the @molecule/app-theme bond) and every other token (hover, container, Material on-*, surface tiers) is AUTO-DERIVED from the cores via color-mix() — so changing one core recolors all its shades.

To recolor a scaffolded app: edit app/src/theme.css (the --color-* variables, :root = light, [data-mol-mode='dark'] = dark) when it exists — it overrides everything here. Only when there is no theme.css do the --mol-color-* from the theme bond drive the palette. NEVER hardcode a literal Tailwind color class in a component — it breaks theming and the safelist.