What
The floating tab bar draws its selection highlight as a Capsule(), hardcoded in the generated <App>.swift:
.background {
if isSelected {
Capsule()
.fill(Color.primary.opacity(0.09))
.matchedGeometryEffect(id: "selection", in: selection)
}
}
.contentShape(Capsule())There is no way to ask for anything else. A tab in the config is { id, title, symbol, badge } — no styling — and the mobile config has no tab-bar appearance options at all. The only lever is tint.
Why it matters
A fully-rounded highlight is a strong stylistic statement, and it is the one piece of app chrome that is always on screen. On an app whose own vocabulary is softer corners (10px cards, 6-10px controls), the capsule reads as borrowed — it does not match anything else the app draws.
It is also not a bug in the sense of being wrong: it matches iOS 26's Liquid Glass tab bar, where the selected indicator is a capsule. That is a reasonable default. The gap is that it is the ONLY option.
Shape of the ask
A config knob for the selection shape, or just its corner radius. Something like:
tabBar: {
selection: { cornerRadius: 6 }, // or: shape: 'capsule' | 'rounded'
}Default to the current capsule so nothing changes for anyone who does not set it.
Verified by patching
Swapping the two lines locally produces exactly what was wanted:
RoundedRectangle(cornerRadius: 6, style: .continuous)
.fill(Color.primary.opacity(0.09))
.matchedGeometryEffect(id: "selection", in: selection)matchedGeometryEffect keeps working — the highlight still slides between tabs, and the animation is unchanged. So the shape is genuinely the only thing coupled here; nothing else in the bar depends on it being a capsule.
contentShape(Capsule()) would want to follow the same shape, or the tappable region keeps the capsule's clipped corners while the drawn highlight does not.
Why this cannot be fixed downstream
storage/framework/mobile/ios/Sources/<App>.swift is generated and gitignored; buddy build:ios rewrites it. The patch above survives exactly as long as nobody rebuilds, which is why it is offered as evidence rather than as a workaround.
Related, same shape of gap: #371 (<Switch> inert), #375 (navigation.open takes no props).
Seen on craft-native@0.0.187, iOS 26.5 simulator, renderer: 'native' with five tabs.