UI elements catalog
The building blocks available for composing block UIs.
Everything on this page imports from @gauntlet/ui-builder. When you build a block, reach for these elements before writing raw React Native. They read the platform's style trees, merge theme defaults, and handle the edge cases (CDN image sizing, layout animation, link routing) you would otherwise reimplement.
Prefer ui-builder for new blocks
Some of these elements are also re-exported from @gauntlet/components. For new blocks, always import from @gauntlet/ui-builder and prefer its elements over reaching into @gauntlet/components — the components library is for legacy maintenance and a few app-specific organisms.
Atoms
The primitives. Each takes a style object shaped like the block config's style section, so merchants can restyle them without code.
Layout and structure
Box— a view with an optional background:{ kind: 'image' | 'gradient' | 'solid' | 'none' }. Use for any container that needs a background asset; plain containers can stayViews.Row/Column— flex containers, so you stop typingflexDirectionby hand.Spacer— a fixed gap whose dimensions live in config.Header— the standard "section title + optional image + see-all link" row. Don't hand-roll a heading with a chevron.BlockSection— the root wrapper for a block: pass it theuseBlockresult and it renders the configured header, navigation button, and content padding for you. Most "carousel of cards" blocks should start here. (Sectionis its lower-level primitive when you need to bypass the config plumbing.)
Content
Text— themed text leaf; setstyle.kindto pick a typography token. Use it for every text node instead of React Native'sText.Image— responsive image that rounds widths to CDN breakpoints and adapts quality to the connection. Requires auriand a width or height; returns null otherwise.Icon— renders a registered SVG byiconId, with a remote-URL fallback.HtmlRichText— renders an HTML string (product descriptions, rich-text metafields stored as HTML) with per-tag styles.ShopifyRichText— renders Shopify's rich-text JSON format (whatrich_textmetafields contain). UseHtmlRichTextfor raw HTML instead.Video— native MP4/HLS playback, portrait by default; allreact-native-videoprops pass through.YoutubeVideo— thumbnail-plus-play-button YouTube embed.
Interaction
Button— pressable CTA with text, optional start/end icons, loading and disabled states, and theme kinds (primary/secondary/tertiary).Link— a pressable that routes a config link ({ kind, value }) through the app's navigation. Use it when the pressable is purely navigational; useButtonwhen it looks like a CTA.Accordion— self-managed expand/collapse panel with animated layout and configurable icons. Always prefer it over a hand-rolledPressable+ state.
Lists
List— virtualized scrolling list (FlatList under the hood). For a static handful of items, a plain.map()is lighter.VerticalList— multi-column grid with row/column separators and correct handling of a partial last row. Use for 2+ column grids.
Helper elements
Higher-level, config-shaped compositions. Each renders a complete section from a data prop plus optional layout and style overrides. Use them when your block is "one of the usual sections" rather than a bespoke design.
Cta, Faq, Media, MediaList, MediaListAccordion, RichTextElement (Shopify rich text), RichTextAccordion, RichTextList, TestimonialsList, TextElement, LinkButton, VideoHelperElement, VideoList, HtmlRichTextElement, and YoutubeVideoComponent.
Layout elements
The units a config-declared layout is assembled from. You will mostly meet them indirectly, since the platform instantiates them from layout config, but they are exported for blocks that render layout regions themselves:
TextLayoutItem, ImageLayoutItem, RichTextLayoutItem, HtmlRichTextLayoutItem, AccordionLayoutItem, ListLayoutItem, LinkLayoutItem, LinkButtonLayoutElement, VideoLayoutElement, SpacerLayoutElement.
Layout-driven rendering: Content and getLayoutItem
Content is a block that renders whatever layout its config declares — the fully config-driven end of the spectrum, where even the structure is data. Under the hood it calls getLayoutItem(layout, source, style, options), which resolves a layout tree into the layout elements above. Call getLayoutItem yourself when your own block needs to render a config-declared region inside otherwise hand-written UI.
Putting it together
A card composed from atoms, with an image, a title, and a CTA inside a padded column:
import { Button, Column, Image, Text } from '@gauntlet/ui-builder'
<Column style={settings.style?.root}>
<Image uri={imageUrl} width={width} aspectRatio={1.5} resizeMode="cover" />
<Text style={settings.style?.title}>{title}</Text>
<Button
style={settings.style?.button ?? {}}
text={ctaText}
onPress={handlePress}
/>
</Column>Every element's style comes from the block's style section, so the whole card restyles from the dashboard. Copy that pattern: elements from this catalog, data and styling from config. See it in a full block in Custom blocks.

