Krizaka UI
Krizaka UI
Mobile

Parity with the web

What exists in React Native, and how each component differs from its web twin.

What runs in React Native, from @krizaka/ui/native. Most components exist on both platforms with the same name and the same props; a few exist only on mobile, because the platform asks for them (a tab bar, a sheet, a pull to refresh).

61 components on both platforms, 15 on mobile only, 86 on the web only.

Parity of the components between the web and React Native
WebMobileWhat differs on mobile
Action sheet—YesMobile only
Activity feedYesYesA SectionList with sticky day headings; live announces through the platform. No Timeline yet: use Stepper for a history on a phone.
Area chartYesYesNo data table or export: the summary is the accessible label, swipe up and down to hear each week. A tap selects the nearest point; no hover.
AvatarYesYesThe fallback is the initial of alt when fallback is not given. size also takes a number of points. src is a URI string (an Image source), not a URL object. An SVG src (….svg, data:image/svg+xml,…, or any URI with svg) is drawn by react-native-svg — Image cannot. presence adds a dot (online, away, busy, offline) and ring a story ring (new, seen, live): mobile only for now.
BadgeYesYesThe text is set in capitals by the component. No className: style it with style.
Bar chartYesYesVertical bars only (no horizontal), no value labels at the tips. No data table or export: swipe up and down on the chart to hear each category.
ButtonYesYesThe text is the label prop (a string), not children: it is also the accessible name. onPress instead of onClick (a Pressable); haptics, if any, belong to your onPress. icon places an icon before the label; there is no asChild. loading shows the platform's ActivityIndicator in place of the icon. variant="gradient" draws its fill with react-native-svg (React Native has no CSS gradient).
CardYesYesonPress on Card.Root makes the whole card a button (no asChild, no interactive). Built on View, Image and Text: style with style, not className. No Card.Stat and no reveal.
Charts providerYesYesAlso takes scheme and theme (the app's roles); no useSlidingWindow export on native.
ChatYesYesThe composer keeps clear of the home indicator; the send button plays a light tap. A failed bubble is itself the retry button. ConversationItem takes presence (a dot on the avatar) instead of online.
CheckboxYesYesAlways a 44-pt row: the box and its words, pressed as one; error shows under it (no Field around it). checked is true or false (no indeterminate); label names it when the words are a sentence with links.
ChipYesYesThe group's name is aria-label (not label). scrollable makes the group one horizontal row: a filter bar. onPress semantics: a chip alone is a checkbox, in a single group a radio.
ComboboxYesYesA field that opens a Sheet with a search box and the matching options: radios for one value, checkboxes and a Done button with multiple. onSearch(query, signal) is debounced (250 ms) and aborted by a newer query, as on the web; no creatable yet.
CountdownYesYesSame props and same clock as the web; style with style. useCountdown and splitDuration are exported for a custom layout.
Credit usageYesYesNo description, loading or className: lay it out with style. The daily use is a native sparkline, read as one element.
Date pickerYesYesNo popover field (DatePicker, DateRangePicker): on a phone, the Calendar, the DayStrip or the wheels sit in the screen or in a Sheet. DateField is typed (day · month · year, numeric keypads); DateWheel is the same date as three wheels — the native form's DateField uses the wheels. Each value a wheel passes, each day or slot pressed plays a selection haptic — when the app passes haptics to the ThemeProvider (expo-haptics): the platform has no native module. A wheel is an adjustable control for VoiceOver and TalkBack (swipe up or down), named by its label, its value read as words.
Description listYesYesterm is a string; layout="grid" draws two cards per row. No KeyValueGrid: use layout="grid".
DialogYesYesOne component, Sheet: a bottom sheet on React Native's Modal (focus kept inside, the back button and the scrim close it), its grip on top, rising with the theme's ease. It holds what a phone shows over a screen: a choice (Select, Combobox use it), the details of a pin on a map, a short form.
Earnings chartYesYesThe total and the change sit above the chart as a headline (the first thing a phone shows), not in the description. No data table or export: swipe on the chart to hear each period.
Empty stateYesYesThe action is a native Button (with label). Style with style, not className.
FieldYesYesOne component, TextField: the label, the input, the hint or the error together (no Field.* parts, no htmlFor). Every TextInput prop passes through (secureTextEntry, keyboardType, autoComplete, returnKeyType); multiline is the text area; onValueChange gives the text. end holds an adornment (a spinner, a check, a show-password button); inputRef focuses the input. A choice among many is Select: a field that opens a Sheet of options.
Floating action button—YesMobile only
FormYesYesImport createKrizakaForm from @krizaka/ui/native/form: the same definition (schema, defaults, i18n), the same useForm, form.* fields drawn with the native ones. form.Form is a View; form.Submit takes label and announces the first error of a refused submit (no focus to move). DateField is three wheels by default (entry="parts": typed day · month · year); RadioGroup has the native looks (variant list · cards · buttons · segmented); Select and Combobox open a Sheet; Switch is a settings row drawn by the theme; Slider floats its value; Money uses the decimal keypad. Each control plays its haptic when the app passes haptics to the ThemeProvider. No Combobox, TagInput, FileUpload or Slider field yet: a screen of its own (a picker) sets the value, or form.Field draws it.
GaugeYesYesNo zone bands around the arc: the value takes the zone's tone. The summary is the accessible label (no meter role in React Native).
Goal gaugeYesYesThe steps light once on mount (animated), not on scroll. drain keeps the default look's final state: the spent steps do not fade on mobile, except in the arcade flavour.
Goal progressYesYestimeLeft is a string (the app writes it); the facts are written under the gauge.
Header—YesMobile only
Image viewer—YesMobile only
Job throughputYesYesThe total and the success rate are a headline above the chart. No data table or export: swipe on the chart to hear each period.
Latency chartYesYesVertical bars only (no vertical prop): keep the names short. The slowest p95 is a headline above the chart.
Line chartYesYesNo data table or export: the plot is one adjustable element whose label is the title and the summary; swipe up and down to hear each point. A tap selects the nearest point and writes it under the chart; no hover. No markers, no end labels; scheme and theme (from @krizaka/ui/native's useTheme()) follow the app's theme.
ListYesYesIts own entry, @krizaka/ui/native/list (FlashList, an optional peer); rows are rendered by renderItem, not described by row. useInfiniteList loads the next page near the end and refreshes on a pull, through @krizaka/query.
LoaderYesYesproduct (orochia, orazaka, yasakia, yororis, krizaka) draws the product's animated ProductMark; on the web it is the mark slot. Announced with the platform's announcement (and a polite live region) instead of role="status". No LoadingRegion: lists show their own skeleton rows (List loading). overlay and page cover their parent with the theme's surface at 90 %; no backdrop blur.
MapYesYesMapLibre Native (@maplibre/maplibre-react-native, an optional peer, with its Expo config plugin): the same style and tiles as the web — it reads pmtiles:// itself. A marker's details open in a Sheet (@krizaka/ui/native); markers and Near me play a haptic. Near me asks the system's permission through MapLibre's LocationManager when pressed; the app declares the location usage in its config. The map's name lists its places for VoiceOver and TalkBack; the screenshots of these stories are drawn by a stand-in (the markers placed, not the tiles).
MarkdownYesYesDrawn in Text and View from the same AST: no linkAs; onLinkPress receives the address (http(s) links open with the system by default). Code blocks scroll sideways and are coloured by the same grammars, from the theme's text roles; there is no copy button. headingIds and codeLabels do not exist: there is nothing to link to on a phone, and no copy button.
Mascot stateYesYestitle and description are strings; the action is a native Button. No framed and no titleAs: style with style. Only the idle bob and a fade-in: the web gestures (wave, dots, hop) stay on the web.
MascotsYesYesOnly the idle bob and the badges: the wave, the dots and the hop are web gestures. Style with style, not className.
Match dialogYesYesFull screen; the avatars slide in with a spring, the heart pops.
Media captureYesYesIts own entry, @krizaka/ui/native/media-capture, on expo-camera (an optional peer). facing is front or back; onCapture receives a file uri, not a blob; a refusal for good opens the Settings. mode is photo or video; labels is required.
Media picker—YesMobile only
MeterYesYesThe parts' colours are the accent, then warning, success, secondary text and danger: apart in every brand. A group of parts is one element whose name lists each part and its value.
Number tickerYesYestrigger is mount or change (a screen has no viewport to enter). variant and tone pick the type scale and the text role (Txt).
Onboarding—YesMobile only
OTP input—YesMobile only
PaginationYesYesFolded only: previous / next and “Page 3 of 12”, the form a thumb reaches; no numbers, no links, no page size. labels is required (previous, next, compact).
Permission prompt—YesMobile only
Photo gridYesYesA tap or a long press opens the photo's menu (an ActionSheet) instead of drag and drop.
Pie and donut chartYesYesNo tooltip: swipe up and down on the chart to hear each slice and its share. No onSelect, no data table.
Price tickerYesYesThe current price and the change are a headline above the plot. No dots on the steps; no data table or export.
Profile cardYesYesname and caption are strings; no nameAs, no icon. One look: no arcade flavour on mobile. The gauges fill once on mount (animated), not on scroll.
ProgressYesYesThe ring's centre is native text (Txt). Style with style, not className.
Pull to refresh—YesMobile only
Radio groupYesYesOne component with options (value, label, description, hint, disabled) and variant — no Item / Card / Button / Segment parts. Each press plays a haptic when the app passes haptics: impact for a tactile key, selection otherwise. error shows under the group and is announced.
Screen—YesMobile only
Search fieldYesYesNo shortcut and no suggestions: the keyboard's search key submits, and results are a screen of their own. clearLabel is required; role="searchbox" names the input. cancelLabel with onCancel adds the platform's Cancel button beside the field.
Segmented—YesMobile only
ShowcaseYesYesSwipeable pages (a paging FlatList) instead of a crossfade; the bar, the counter and the buttons are the same. No hover or keyboard: the autoplay holds while the finger drags, while the app is in the background and with Reduce Motion on.
SkeletonYesYeswidth and height are props (points or a percentage), not classes.
SliderYesYesDrawn by the theme with a pan responder: drag anywhere on the track, the nearest thumb follows; a selection haptic at each step passed (the app's haptics). Each thumb is an adjustable control for VoiceOver and TalkBack: swipe up or down by a step, its value read as words. floatingValue shows the value over the thumb while it is dragged ("always": at rest too).
SparklineYesYesNo threshold line.
SpinnerYesYesThe platform's ActivityIndicator, in the accent.
Splash hand-off—YesMobile only
Step progressYesYesbackLabel + onBack instead of a back node; it keeps clear of the status bar.
StepperYesYesstatusLabels gives the words read after each step (the web hides them in the markup). A list of listitems, each named by its title and status.
Swipe deckYesYesThe card tilts with the finger and a stamp (LIKE / NOPE) says the decision; a medium tick marks it. PersonCard pages its photos with a tap on a side; screen readers swipe up and down.
Swipeable row—YesMobile only
SwitchYesYesDrawn by the theme, not the system's: the same switch on iOS and Android, the accent when on, a selection haptic when it flips (the app's haptics). showLabel makes it a settings row: the label and its description beside the switch, the whole row pressable, the description read as the hint. error shows under the row and is announced.
Tab bar—YesMobile only
TabsYesYesitems (value, label, count, content) instead of the web's parts. The underlined tab list scrolls sideways when it does not fit; for the app's main sections use TabBar.
Tag selectorYesYesA selection tick on each toggle.
ThemeYesYesThemeProvider takes the product's colour roles (overrides) and fonts; there is no ThemeScript and no toggle. useTheme() returns the resolved theme (colour roles), scheme, radius and motion for StyleSheet. The mode is not persisted: the app stores it from onModeChange.
ToastYesYesToaster takes offset (the safe-area inset) instead of a position; mount it inside ThemeProvider. Actions take onPress; a toast takes onPress to open what it is about. No toast.custom: an icon before the text instead. A sideways swipe dismisses a toast; its tone plays a haptic when the app gives haptics. A snackbar is Toaster position="bottom" with one action.
Txt—YesMobile only
Verified badgeYesYessize is in points; on="media" instead of onMedia.
Vertical videoYesYesIts own entry (@krizaka/ui/native/vertical-video): it plays on expo-video, an optional peer. uri and posterUri instead of src and poster; creator.avatarUri; a long press likes (there is no double click). ShortFeed pages a FlatList: give it the page's height; the slide in view is the viewable one.
Video playerYesYesIts own entry, @krizaka/ui/native/video-player, on expo-video (an optional peer): an app that plays no video installs nothing. The platform's controls (nativeControls, default true): accessible, full screen and picture in picture by the system. source is an object (uri, contentType, headers); paused stops it off screen (a FlatList's viewability).