Reference

Changelog

Every release of @hzblj/kara-ui. All kara packages are versioned together.

0.7.0

MinorPatch

SwipeActions works on Android, and takes its buttons as data. Breaking: SwipeActions.Actions and its Button children are gone — pass leading and/or trailing, each a list of {icon, label, onPress, destructive?, tint?}, and allowsFullSwipe on the row:

tsx <SwipeActions trailing={[ { destructive: true, icon: "trash", label: "Delete", onPress: remove }, ]} > <ListItem title="Order [#1024](https://github.com/hzblj/kara-ui/issues/1024)" /> </SwipeActions>

iOS renders SwiftUI's swipeActions, each action its icon on a button in its tint — round, with the label under it, on iOS 26. Android, where Compose has no swipe actions, gets kara's own SwipeActionsBox (@hzblj/kara-native/jetpack-compose): the row slides on an anchored drag, and filled icon buttons with their labels show in the strip it leaves. One row is open at a time on both, and a tap on an open row closes it.

2a6595f

Breaking: FlashList is gone, and @shopify/flash-list is no longer a peer dependency. kara's list for React Native content is RnFlatList (and RnSectionList): React Native's own virtualized lists, whose cells stay in normal flow, so rows that host native views keep them in place — a recycling list moves its cells, which an @expo/ui host does not survive. An app that wants FlashList for plain data rows installs and imports it itself.

2a6595f

Tooltip is controlled on Android too: visible shows Material's plain tooltip, centred above the anchor and kept inside the window, and onDismiss reports a touch outside it or the anchor scrolling away. It used to open only on a long press and hide itself, ignoring both props — and Material's own placement let it run off the edge of the screen. Nothing opens it on a long press any more; wire one to visible if you want it.

TooltipBox (@hzblj/kara-native/jetpack-compose) takes plain for that style, and hides when isPresented turns false.

2a6595f

ActionSheet on Android renders its rows in a host of its own — they were Compose views straight inside the sheet, which has none, and threw "must be rendered inside a Host". The rows are Material's bottom-sheet menu now: full width, with each action's icon before its label.

SearchBar on iOS centres its text beside the magnifier. The type scale's line height sat the text at the bottom of a taller line in a single-line UITextField.

2a6595f

Android layout fixes:

  • Screen keeps its content clear of the status bar when nothing sits above it, as a SwiftUI host keeps to the safe area — it drew under it. Under a navigation bar nothing changes; the background still runs to the edges.
  • Form is inset from its container on every side, with section titles and footers indented to the cards' content, like SwiftUI's grouped form — in a Screen its cards ran into the screen's edges.
  • A disabled or read-only Checkbox or Switch keeps Material's 48dp touch target, so it lines up with the enabled ones instead of shifting toward the edge.
2a6595f

DatePicker on iOS sizes itself to its value. Its host took the width it was given and laid the compact field out against the far edge of it — past its container's, in a row. The calendar is in the accent now.

2a6595f

Alert and ActionSheet appear on iOS. Both hung their SwiftUI presentation on an EmptyView — @expo/ui uses one when there is no trigger, and SwiftUI never presents from it — so visible changed nothing. Each now has a trigger that takes no room, and ActionSheet passes its buttons through the dialog's Actions slot.

2a6595f

RnFlatList and RnSectionList keep rows that host native views on Android. React Native's Android default, removeClippedSubviews, detached a host measured at zero height before its first layout, and the row stayed empty; it is off unless you turn it on.

2a6595f

SegmentedControl draws its selected segment in the accent on both platforms. iOS renders kara's own UISegmentedControl (SegmentedControl in @hzblj/kara-native/swift-ui), whose pill, labels and track take colours — the system control tints only the pill, SwiftUI's segmented picker not even that. Android colours Material's segmented buttons, equal widths. onChange now fires for a new segment only on Android too.

2a6595f

NavigationBar and Sheet.Header on iOS 26 centre their title and glass items. UIKit's bar is 54 pt with its 44 pt row of items at the top, so centring the bar left the row 5 pt high; it is the row that is centred now.

2a6595f

sx costs less on every render. The style cache, the responsive flattening and the key behind useSxModifiers used to go through every key the surface has, about seventy for a Box, even when a component set two or three of them. Now they go through only the props that are set, and the theme's part of the cache key is worked out once per theme rather than on every render. Without a JIT, as on Hermes, an sx() view resolves its style 2.5–5× faster and a native atom 2–4.5× faster.

2a6595f

0.6.0

Minor

Haptics: kara's own, native on both platforms, named for what happened.

  • haptics.success(), haptics.selection(), … — one function per haptic — and haptics.play(name) for a name that arrives as data. selection, tick, toggleOn/toggleOff, success/warning/error, longPress, dragStart, thresholdActivate/thresholdDeactivate, keyPress, and the impacts soft, light, medium, rigid, heavy (intensity scales them on iOS). Synchronous, nothing to await.
  • iOS: UIKit's feedback generators, kept alive and warmed up with haptics.prepare — Pressable prepares its haptic on press-in. Android: the system's own haptic feedback (View.performHapticFeedback), with Android 14's constants falling back to older ones — never a raw vibration. Both follow the user's system setting.
  • useHapticFeedback(trigger, haptic) plays on every change of a value, never on mount; a function of the previous and next value picks a haptic per change.
  • haptics.setEnabled(false) silences every kara haptic, the components' own included.
  • Pressable's haptic takes a name as well as true (a light impact); Chip plays selection.
  • On Android, where Compose's Material controls play nothing: Switch plays toggleOn/toggleOff, a stepped Slider ticks at every stop, SegmentedControl plays selection. iOS keeps its native controls' own feedback.
  • Slider: step is the increment on Android too — it was passed to Compose as the number of stops.
  • expo-haptics is no longer a peer dependency.
62b7131

0.5.0

Minor

ZoomTransition: a push that grows out of the photo it was opened from and shrinks back into it.

  • iOS 18: UIKit's zoom transition, with the interactive dismissal (swipe down, edge swipe, pinch) gated on the scroll views under the finger. Below iOS 18 the push stays a slide. Android: Material's container transform, both ways.
  • Three pieces from @hzblj/kara-ui/router, tied by one identifier: ZoomTransition.Source on the list, ZoomTransition.Enabler and ZoomTransition.Target on the pushed screen; useZoomTransitionSourceId, ZOOM_TRANSITION_PARAM, useZoomTransitionParam and withZoomTransition (an Android fade under the transform) around them.
  • Settings both platforms honour sit at the top (scrim); the rest is typed apart under ios (dismissGesture, blur, the target's fit) and android (duration, easing, fade, path, corner radii, the target's fit and flex).
  • ContextMenu: with a ZoomTransition.Source in the trigger, a tap on the iOS preview zooms the preview's photo straight into the pushed screen. previewTransition (zoom, pop, dismiss) picks how the preview leaves.
  • DurationSize, the keys of duration.
3b0a6fb

0.4.1

Patch

GlassView always shows its glass. Glass mounted under a React Native view at opacity 0 — the first row of a Legend List opened from cache, content fading in from 0 — used to stay without it, because React Native changes opacity past UIKit, which then kept the subtree marked as hidden. React Native opacity changes that cross UIKit's hidden threshold now go through UIView.alpha, so this holds for every Liquid Glass view in the app. The glass is also set at once instead of polling until every ancestor is fully opaque, and its content no longer waits for it.

d14bdd3

0.4.0

MinorPatch

Android polish, and a new RnListItem.

  • ContextMenu on Android is a proper long-press menu: a ripple and the long-press haptic, then a Material dropdown where the finger is, with the actions' icons and the trigger highlighted while it is open. The ripple and highlight stay inside rounded corners.
  • A pressable HStack, VStack or ZStack ripples across its whole shape, padding included; ListItem and LabeledContent take px so a row in a card can carry the card's padding inside its press area.
  • ListItem keeps its chevron when the subtitle fills the line.
  • Tabs take the theme's colours: on Android the bar, active indicator, icons, labels and ripple come from tokens instead of the wallpaper scheme; on iOS the selected item takes the accent.
  • New RnListItem: ListItem's row in the React Native tier, cheap to mount by the dozen, with a full-row ripple on Android and a highlight on iOS.
6e7903a

npx kara-icons ./assets/icons works without --out — it used to skip the folder and print its usage.

6e7903a

0.3.0

Minor

Native sheets with a native header. Sheet is now a TrueSheet (@lodev09/react-native-true-sheet, a new peer dependency) with <Sheet.Header> — a real navigation bar with a centred, leading or large title that hands over to the bar as it scrolls away, items on either side, and on iOS 26 the content scrolls under it with the soft edge effect — plus <Sheet.ScrollView>, useSheetScroll, detents, a footer and a ref (present/dismiss/resize). It is React Native tier now: no host, native atoms inside go in an Island. fitToContents is replaced by detents (['auto'] by default).

NavigationBar takes leadingItems / trailingItems instead of onBack / onClose: back, close or an app icon, on either side and in any order; on iOS 26 neighbours share a glass capsule unless an item is separated. Also titleAlignment, titleVisible, inverted and an iOS search field. On Android it is now Material's native top app bar.

f84ffd5

0.2.1

Patch

Installable again: 0.2.0 was published with workspace:^ ranges between the kara packages, which no package manager outside this repository resolves. The packages now go out through Yarn, which writes the real version ranges.

be5be81

0.2.0

Minor

Icons are now fully native and the app's own: plugins: [['@hzblj/kara-ui', {icons: {source: './assets/icons'}}]] turns every SVG in the folder into an iOS asset-catalog template image and an Android vector drawable at prebuild (x.ios.svg / x.android.svg for per-platform glyphs), and writes kara-icons.d.ts so name only accepts icons that exist; npx kara-icons does the same for CI. Icon draws them in a host, the new RnIcon anywhere, and Tabs passes them as xcasset / drawable. The built-in SF Symbol / Material icon names and the @expo/vector-icons peer dependency are gone.

c30bef6

Leaner, reusable-only components. Countdown is gone, with its native views. There is one ContextMenu now — the native module's long-press menu on React Native content, with a custom preview on iOS (formerly RnContextMenu); the @expo/ui-based one is removed.

Android, reworked to look and behave like Material while honouring the theme:

  • Button, Badge and Alert render their labels; Button keeps Material's own shape (no iOS ring), takes tint as its fill with a label that contrasts with it, and draws glass as Material's outlined button.
  • Alert is built from AlertDialog's slots — title, message, the confirm action (destructive when asked) and Cancel — instead of drawing empty.
  • Menu presents its actions in Material's dropdown popup, with their icons, instead of laying them out over the trigger.
  • Picker is a themed Material exposed dropdown the width of its container.
  • Switch, Checkbox and RadioGroup are tinted with the accent, and with a label are full-width rows that toggle as a whole; Form sections span the form's width.
  • Surface pads its content instead of its background, and stacks its children in a column.
  • Fab shows its icon, DatePicker opens its dialog on a tap (in the accent colour) instead of on mount, GlassView's fallback is the translucent glass fill, and the List docs spell out that it needs a bounded height.
c30bef6

0.1.0

Minor

First release of the kara-ui design system: theme and tokens, the sx engine, atoms, molecules, organisms and Screen, native tabs (@hzblj/kara-ui/router), the KaraUI native module (Liquid Glass, scroll edge effect, native countdown, context menu with preview, rich tooltip, FAB menu), and KaraProvider with theme overrides — colours, the app's own fonts, the Material seed, and Material You dynamic colour on Android. Text uses the platform's face by default. Install @hzblj/kara-ui; the scoped packages are its building blocks.

f919c7b