v0.9.0
New Features
Slot props for inner Text and View elements
Most components now accept *Props overrides for the inner <Text> / <View> slots they render. Consumers can pass through any TextProps / ViewProps (style, weight, font family, accessibility, etc.) without rewriting the component or fighting children-prop precedence.
- Label slots (
labelProps): Accordion (titleProps), Avatar, Badge, Breadcrumbs (labelProps+separatorProps), Button, Checkbox, Chip, Indicator, Pagination (labelProps+activeLabelProps), Radio, Slider, Stepper, Switch, Tabs, Tooltip - Title / body slots (
titleProps/bodyProps): Dialog, Notice, Toast - Description slots (
descriptionProps): AutoComplete, Avatar, Checkbox, Input, Radio, Stepper, Switch, TimePicker - Section / control slots: AutoComplete + Input + TimePicker (
startSectionProps,endSectionProps), Spoiler (controlProps), DataTable cell text customization mergeSlotPropsis now exported from@platform-blocks/uiso custom components can adopt the same merge semantics (theme defaults → slot props override → explicit props win).
useDisclosure, useDebouncedValue, useDebouncedCallback, useMediaQuery, useHover
Five hooks promoted to the public API. All have tests, demos, and metadata.
import { useDisclosure, useDebouncedValue, useMediaQuery } from '@platform-blocks/ui';
const [opened, { open, close, toggle }] = useDisclosure(false);
const [debounced] = useDebouncedValue(query, 200);
const isCompact = useMediaQuery('(max-width: 640px)');Slider variants
<Slider> and <RangeSlider> accept a new variant prop with six visual treatments:
| Variant | Description |
|---|---|
default |
Standard track, filled active range, solid thumb |
filled |
Thicker, fully opaque inactive track (iOS-style) |
outline |
Transparent track + border; active range is a colored fill |
minimal |
Hairline track and a smaller, flatter thumb for dense UIs |
segmented |
Track is divided at tick boundaries; active region fills whole segments |
unstyled |
Strips all chrome — consumer styles via trackStyle / thumbStyle |
Variant size multipliers are applied at the consumer level so the thumb stays visually aligned with the track ends.
RadioGroup variants
<RadioGroup> accepts a variant prop with four layouts:
| Variant | Description |
|---|---|
default |
Classic stacked radio dots with labels |
card |
Each option is a bordered, padded surface; selected card gets a colored border, tinted background, and a check icon — ideal when options have descriptions |
segmented |
Joined buttons with shared borders, like an iOS/macOS segmented control (always horizontal) |
chip |
Compact rounded pills that wrap onto multiple lines — great for filters and tag pickers |
orientation is honored only by default; segmented is always horizontal and chip always wraps. Keyboard navigation (arrow-key cycling) and accessibilityRole="radio" are preserved across all variants.
Card.Section
Card gains a new <Card.Section> sub-component for full-bleed banners, dividers, and banded rows. Position-aware: the parent walks its children and tags the first/last sections so they only negate the relevant edges.
<Card padding={20} withBorder>
<Card.Section>
<Image source={hero} />
</Card.Section>
<Text>Body content keeps the parent padding.</Text>
<Card.Section withBorder>
<Text>Footer with a top divider.</Text>
</Card.Section>
</Card>Card also gains withBorder, borderColor, borderWidth, bg (palette name or CSS color), and testID. padding is widened from number to SizeValue (token or pixel).
Input variants and slot overrides
BaseInputProps exposes a variant of 'default' | 'filled' | 'outline' | 'unstyled', plus placeholderTextColor, labelProps, descriptionProps, startSectionProps, and endSectionProps. The variant set propagates to every component that extends BaseInputProps (Input, NumberInput, AutoComplete, TimePicker, etc.).
Divider enhancements
Divider is no longer just a line — it now supports:
variant:'solid' | 'dashed' | 'dotted' | 'gradient'colorVariant:'border' | 'subtle' | 'muted' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'gray'label(centered, start, or end content rendered in the middle of the line) +labelPropsopacityshorthandsizeaccepts a token or pixel thickness
Block bg shorthand and Text c / ff shorthands
<Block bg="primary">resolves to the palette's shade-1 tint;<Block bg="primary.6">picks an explicit shade; theme background keys ('surface','subtle','elevated','base') are also supported.<Text c="dimmed">for color shorthand and<Text ff="mono">for font-family shorthand.
Demo coverage
36 new demos shipped across the UI package, including: label-customization / title-customization / text-customization for the components that gained slot props, Slider/variants, Radio/variants + Radio/theming, Card/sections + Card/border-and-bg, Input/variants + Input/slot-styling, Divider/gradient-opacity, Block/bg-shorthand, and Text/c-shorthand + Text/ff.
Improvements
DataTableFilter is now publicly typed
DataTableFilter was already exported from ./components/DataTable but missed the public re-export at the package root. It's now reachable via import type { DataTableFilter } from '@platform-blocks/ui'.
Playground exposes RadioGroup, not just Radio
The Radio playground entry now mounts <RadioGroup> (matching the convention used by Tabs, Select, and SegmentedControl — the playground exposes the parent/group rather than the inner element). Variant and orientation are surfaced as live segmented controls.
Slider playground covers variants
The Slider playground entry surfaces variant as a segmented control across all six values, with valueLabelPosition, valueLabelOffset, valueLabelAlwaysOn, and valueLabelAsCard pinned for live tweaking.
Fixes
Typecheck regressions cleared
The docs app + UI package now typecheck cleanly (down from 71 errors to 0). Touched areas:
- Demo cleanup — removed references to props that no longer exist (
mobileMode,touchOptimized,swipeToClose,floatingPosition, etc.) onTableOfContents;xxssize token replaced withxs;<Row wrap>boolean →wrap="wrap"string;<Column bg=…>→<Block bg=…>(Column doesn't acceptbg);renderExpandedRow→expandableRowRenderon DataTable. - Test infrastructure —
Card.testID(legitimately missing fromCardProps) added;react-test-renderertypes replaced with a structural shim so the Divider rendering test compiles without@types/react-test-renderer;renderHookcallbacks for the debounce hooks now annotate their props parameter so the generic infers correctly. - Wrong import path in
apps/platform-blocks.com/utils/sourceCode.ts(../data/sourceCodeMap→./sourceCodeMap). - Strictness fixes in NumberInput, Rating, Ring, and QRCode demos/tests (typed callback params, palette fallbacks, narrowed reduce).
RadioGroup no longer requires theme.backgrounds for the default variant
Variant-only color tokens (accentTint, surfaceColor, etc.) are now computed lazily and only when variant !== 'default'. The default radio-dot path doesn't depend on theme.backgrounds anymore, which fixes 10 Radio tests that mocked a slim theme.
Migration notes
This release is predominantly additive. A few demos that referenced removed TableOfContents mobile props will need to drop those props if you copied them — the props were never on TableOfContentsProps, so they were silently broken anyway. If you imported DataTableFilter from @platform-blocks/ui/components/DataTable, the type is now also re-exported from the package root.