Appica UIUI 1.0.0

Composition

Swap elements, compose with your router, merge styles.


Appica UI components ship fully styled, but you often need them to be something else — a navigation link that's actually your router's Link, a tooltip trigger that's actually your own button. The render prop, inherited from Base UI, makes that possible without losing the component's styling or behavior.

For the related case of a plain link that should merely look like a button, use the exported variant helpers instead — see Links that look like a button.

Rendering as a different element

Pass an element to render and the component adopts it as its output, merging in its own props, classes, and event handlers. For instance, render a Badge as an <a> so a status chip becomes a real link:

Rendering as a component

render also accepts a component element — ideal for framework routers. A NavigationLink stays a link while delegating navigation to your router's Link:

The same pattern composes the interactive parts of larger components. For instance, make a tooltip's trigger your own button:

Sometimes you don't want to change a component's element — you want a plain link (or other element) to simply wear a component's styling. Don't reach for render here: rendering an <a> through Button forces button semantics onto a link. Instead, apply the exported buttonVariants classes directly to the element that already has the right semantics:

buttonVariants isn't the only one — several components export their variant recipe for exactly this purpose:

Each takes the same variant props as its component and returns a className string, so they drop into any element and compose with your own classes through cn or a template literal.

Where to put className

This is the one rule worth memorizing. When composing a render-prop wrapper:

  • Visual overrides (className, style) go on the wrapper.
  • Structural/behavioral props (href, type, variant, size, rendering as a different element) go on the JSX inside render.

If you specifically need a class on the inner element, extract the trigger into its own 'use client' component rather than promoting the whole page to client.

Class merging

Overrides are merged with tailwind-merge, so conflicting utilities are de-duplicated and the last one wins. You don't need to fight specificity:

© 2026 Appica UI. A free component library, crafted by the Appica team.