Skip to Content

Components

Ready-made React Native components, from @vio-live/react-native-sdk/ui. They are the fast path — and they are built so that taking one part of your design back never costs you the behaviour around it.

What ships today

ComponentWhat it does
VioProductCardImage, brand, title, price, discount badge, availability, add to cart
VioProductCarouselA horizontal row — from products you pass, or from a placement
VioCheckoutFour steps: contact, shipping, payment, review

Theming

The tokens are one object, passed to the provider. Anything you leave out keeps its default.

<VioProvider theme={{ color: { text: { primary: '#111' }, accent: { editorial: '#c14a3b' }, }, radius: { md: 8 }, density: 0.85, }} >
GroupWhat it covers
colortext, accent, surface, border, status
fontserif for headlines, sans for everything else
size · weight · tracking · lineHeightType scale
space · radiusSpacing and corners
densityMultiplies every spacing value

density is the quiet one: 0.75 gives a feed the compact layout it wants without you restating the whole scale.

Fonts resolve differently per platform. theme.font.serif is one string, but iOS looks up a PostScript name and Android a file name. Bundle the font on both and verify the name on each — this is the first place a theme looks different between the two.

Slot overrides

Every component takes render* props. Each receives the data and the resolved theme, so an override can stay on-brand without reaching into the SDK. Return null to drop that part entirely.

<VioProductCard product={product} renderPrice={({ price, theme }) => ( <Text style={{ color: theme.color.accent.editorial }}>From {price}</Text> )} renderAction={() => null} />
ComponentSlots
VioProductCardrenderImage renderTitle renderBrand renderPrice renderAction
VioProductCarouselrenderHeader renderItem renderLoading renderEmpty
VioCheckoutrenderHeader renderStep renderFooter

renderStep is the interesting one: replace a single checkout step with your own form and keep the step machine, the validation and the backend patching.

VioProductCard

<VioProductCard product={product} layout="grid" // or "list" width={160} onPress={(p) => navigate('Product', { id: p.id })} onAddToCart={async (p) => { /* defaults to Vio.cart.addItem */ }} addLabel="Legg i handlekurv" soldOutLabel="Utsolgt" />

Given only a product it is a pure rendering component — it works without a provider, which makes it easy to drop into a storybook.

VioProductCarousel

Two modes, one component:

<VioProductCarousel products={products} title="New in" /> {/* yours */} <VioProductCarousel locationId="home_top" /> {/* backend-driven */}

With locationId it resolves the placement bound to that slot, takes its title from the placement config, and follows it live. With products it never touches the network.

<VioProductCarousel locationId="home_top" cardWidth={160} cardProps={{ showAction: false }} onProductPress={(p) => navigate('Product', { id: p.id })} />

VioCheckout

<VioCheckout cartId={cart?.cart_id} successUrl="myapp://checkout/success" cancelUrl="myapp://checkout/cancel" onComplete={(checkout) => pay(checkout)} onCancel={() => navigation.goBack()} labels={{ contact: 'Kontakt', next: 'Fortsett', pay: 'Fullfør bestilling' }} />

It is a screen, not an overlay. It renders into whatever container you give it, so a modal, a bottom sheet or a pushed screen are all your call — the SDK never owns your navigation.

Every visible string goes through labels, so translating it does not mean forking it.

Each step is saved to the backend as the user leaves it, which means an abandoned checkout still carries the address.

Last updated on