Files
skills/docs/ui/react/react-ui/src/components/input-group/input-group.variants.md
2026-05-29 08:20:56 +01:00

3.9 KiB

InputGroup Variants (cva config)

Purpose

inputGroupVariants, inputGroupAddonVariants, inputGroupInputVariants, inputGroupTextareaVariants, and inputGroupButtonVariants are the five cva (class-variance-authority) configurations powering the <InputGroup> primitives. They are split from input-group.tsx into their own module so an ejected source copy under npx shadcn@latest add @suaveplan/input-group keeps the cva configurations in a dedicated file. Theme overrides flow through useThemedVariants(...).

The wrapper cva carries the shared border + focus ring; the inner <InputGroupInput> / <InputGroupTextarea> cvas strip the standard border + shadow + ring that would otherwise double up with the wrapper's own.

Features

  • Wrapper flex w-full items-center rounded-md border border-input bg-transparent shadow-sm with focus-within:ring-2 and data-[invalid=true]:border-destructive.
  • Addon recipe with three positions: start (right-border separator), end (left-border separator), none (no separator, used for inline buttons).
  • Input recipe strips the standard <Input> border / shadow / focus ring (border-0 outline-none shadow-none focus:ring-0).
  • Textarea recipe strips the standard <Textarea> border / shadow / focus ring with a default min-height: 80px.
  • Button recipe carries the inline icon-button surface (h-8 w-8 mx-1 rounded-md) with the standard data-icon slot rules.
  • NEVER uses space-x-* per the shadcn skill rule.
  • motion-reduce:transition-none for users with prefers-reduced-motion: reduce.

Usage: Basic Example

import {
    inputGroupVariants,
    inputGroupInputVariants,
    inputGroupAddonVariants,
} from "@suaveplan/react-ui";

const wrapperCls = inputGroupVariants();
const inputCls = inputGroupInputVariants();
const addonCls = inputGroupAddonVariants({ position: "start" });

Usage: Advanced Example

import {
    inputGroupVariants,
    inputGroupInputVariants,
    cn,
} from "@suaveplan/react-ui";

export function CustomInputGroup() {
    return (
        <div className={cn(inputGroupVariants(), "ring-2 ring-accent")}>
            <span className="px-3 text-sm text-muted-foreground">@</span>
            <input className={inputGroupInputVariants()} />
        </div>
    );
}

API Reference

inputGroupVariants(): string

Returns the wrapper classes.

inputGroupAddonVariants(props?: { position?: "start" | "end" | "none" }): string

Returns the addon classes. Omitted position falls back to the cva defaultVariants (position: "start").

inputGroupInputVariants(): string

Returns the input classes — strips inner border / shadow / focus ring so the wrapper carries them.

inputGroupTextareaVariants(): string

Returns the textarea classes — same border-stripping treatment as the input.

inputGroupButtonVariants(): string

Returns the inline icon-button classes — h-8 w-8 mx-1 rounded-md with the standard data-icon slot rules.

Implementation Notes

  • The five cvas are kept separate so consumer themes can override each independently — for example a theme that styles the wrapper as a pill while leaving the inner input untouched.
  • The input's focus:ring-0 focus-visible:ring-0 is intentional: the wrapper carries the ring via focus-within:ring-2 so removing the inner ring is the only way to avoid the double-ring artefact. Consumers MUST use <InputGroupInput> (not <Input>) inside the group for this reason.
  • The button cva uses mx-1 so the inline button does not press flush against the input's text — a minor padding tweak that keeps the layout breathing under both LTR and RTL.
  • Per the shadcn skill rule, the cvas NEVER use space-x-* / space-y-*.
  • Tokens reference theme-driven CSS custom properties (border-input, bg-transparent, text-muted-foreground) so the colour palette comes from the active ThemePlugin.cssVariables payload.