One field, two shapes, inner slots that go flush (full-bleed 1:1) or inset (bare content + gap) — plus detached outer slots. Every circle is polymorphic: button, text, icon, menu, popover, or tooltip-only.
shape=straight · inner=flush · radius=8px · inner cells fill the full height (square-in-square / circle-in-circle, no gap)
Every field is composed from the same parts. Learn these once, build any field. Two separate layers: a construction halo (one line per field edge) and annotations dotted right on each part's border — hover a label to highlight its part.
Guests can view · link expires in 7 days
<UniversalInput shape size innerFit radius><Field><Row> · auto<Inner position fit width><Outer fit width><Top> <Bottom><Input><Annotation><Above> <Below>flush / inset / paddedabove/below × leading/center/trailing<UniversalInput shape="straight" size="md" innerFit="flush">
<UniversalInput.Outer label="filters" onClick={…}>
<SlidersHorizontal />
</UniversalInput.Outer>
<UniversalInput.Field>
<UniversalInput.Inner position="leading">
<Search />
</UniversalInput.Inner>
<UniversalInput.Input placeholder="Search…" />
<UniversalInput.Inner position="trailing" fit="inset" onClick={…}>
<Mic />
</UniversalInput.Inner>
</UniversalInput.Field>
<UniversalInput.Outer label="send" onClick={…}>
<Send />
</UniversalInput.Outer>
</UniversalInput>Top and Bottom boxes live inside the field border and expand its height. Switch each one — the field grows and shrinks around whatever you put in: a tall map, a file strip, a slim notice, a toolbar, a caption, or nothing at all.
Unpadded by default
Padding is yours (p-2, px-3…). Dividers draw themselves.
Height from content
Auto by default; pin it with h-* or cap it with max-h-* + overflow.
Compose freely
Top, Row, Bottom — keep any of them, drop any of them, swap contents live.
Guests can view · link expires in 7 days