{"schemaVersion":1,"package":"@nannier/canvas","version":"4.2.0","status":"source-snapshot","sourceHash":"1b984bdfad247d053ab7f82ef582b919717b61d8c09c675992bf5d3da2781cec","importFrom":"@nannier/canvas","dependencies":[{"name":"expo-blur","range":"*","optional":true},{"name":"expo-clipboard","range":"*","optional":true},{"name":"expo-glass-effect","range":"*","optional":true},{"name":"expo-modules-core","range":"*","optional":true},{"name":"expo-video","range":"*","optional":true},{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-qrcode-svg","range":">=6","optional":true},{"name":"react-native-safe-area-context","range":">=4","optional":true},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"exports":[{"name":"Accordion","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/accordion"},{"name":"AccordionItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/accordion"},{"name":"AccordionProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/accordion"},{"name":"ActionPanel","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/action-panels"},{"name":"ActionPanelProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/action-panels"},{"name":"ActionSheet","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/action-sheet"},{"name":"ActionSheetAction","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/action-sheet"},{"name":"ActionSheetProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/action-sheet"},{"name":"Alert","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/alert"},{"name":"AlertDialog","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/alert-dialog"},{"name":"AlertDialogProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/alert-dialog"},{"name":"AlertProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/alert"},{"name":"alpha","kind":"utility","deprecated":false,"docs":null},{"name":"AnatomyPart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/button"},{"name":"AnatomyPartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/button"},{"name":"AnatomyProvider","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/button"},{"name":"AnatomyProviderProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/button"},{"name":"AnatomyRect","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/button"},{"name":"AnatomyRects","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/button"},{"name":"AppFrame","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/app-frame"},{"name":"AppFrameProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/app-frame"},{"name":"applyBoardMove","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/components/board"},{"name":"AreaChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/area-chart"},{"name":"AreaChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/area-chart"},{"name":"Autocomplete","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/autocomplete"},{"name":"AutocompleteProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/autocomplete"},{"name":"Avatar","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/avatar"},{"name":"AvatarGroup","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/avatar"},{"name":"AvatarGroupProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/avatar"},{"name":"AvatarMenu","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/avatar"},{"name":"AvatarMenuProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/avatar"},{"name":"AvatarProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/avatar"},{"name":"Badge","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/badge"},{"name":"BadgeGroup","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/badge"},{"name":"BadgeGroupProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/badge"},{"name":"BadgeProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/badge"},{"name":"BarList","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/bar-list"},{"name":"BarListProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/bar-list"},{"name":"baseColors","kind":"token","deprecated":false,"docs":null},{"name":"Board","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/board"},{"name":"BoardColumn","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/board"},{"name":"BoardItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/board"},{"name":"BoardMove","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/board"},{"name":"BoardProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/board"},{"name":"BoxPlot","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/box-plot"},{"name":"BoxPlotProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/box-plot"},{"name":"BoxSample","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/box-plot"},{"name":"Breadcrumb","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/breadcrumb"},{"name":"BreadcrumbItem","kind":"part","deprecated":false,"docs":null},{"name":"BreadcrumbItemProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/breadcrumb"},{"name":"BreadcrumbProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/breadcrumb"},{"name":"BreakdownRow","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/bar-list"},{"name":"BreakpointKey","kind":"type","deprecated":false,"docs":null},{"name":"BreakpointOverride","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/tokens/layout"},{"name":"breakpoints","kind":"token","deprecated":false,"docs":null},{"name":"BulletChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/bullet-chart"},{"name":"BulletChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/bullet-chart"},{"name":"BulletDatum","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/bullet-chart"},{"name":"Button","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/button"},{"name":"ButtonGroup","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/button-group"},{"name":"ButtonGroupItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/button-group"},{"name":"ButtonGroupProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/button-group"},{"name":"ButtonProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/button"},{"name":"Calendar","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/calendar"},{"name":"CalendarProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/calendar"},{"name":"Candle","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/candlestick-chart"},{"name":"CandlestickChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/candlestick-chart"},{"name":"CandlestickChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/candlestick-chart"},{"name":"Card","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardContent","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardContentProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardDescription","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardFooter","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardHeader","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardMedia","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardMediaProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardSectionProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardSeparator","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardTextProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"CardTitle","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/card"},{"name":"Carousel","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/carousel"},{"name":"CarouselProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/carousel"},{"name":"channelsOf","kind":"utility","deprecated":false,"docs":null},{"name":"Chart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/chart"},{"name":"ChartDatum","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chart"},{"name":"ChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chart"},{"name":"ChartSeries","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chart"},{"name":"Chat","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatAttachmentData","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatComposer","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatComposerProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatMessage","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatMessageData","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatMessageProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatQuestionAnswerData","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatQuestionData","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatThread","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"ChatThreadProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"Checkbox","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/checkbox"},{"name":"CheckboxProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/checkbox"},{"name":"Chip","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/chip"},{"name":"ChipGroup","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/chip"},{"name":"ChipGroupProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chip"},{"name":"ChipProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chip"},{"name":"clearStoredDashboardOrder","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/components/dashboard-grid"},{"name":"CodeBlock","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/code-block"},{"name":"CodeBlockProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/code-block"},{"name":"CodeBlockTab","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/code-block"},{"name":"Collapsible","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/collapsible"},{"name":"CollapsibleProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/collapsible"},{"name":"colorsByScheme","kind":"token","deprecated":false,"docs":null},{"name":"ColorScheme","kind":"type","deprecated":false,"docs":null},{"name":"colorsFor","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"ColorTokens","kind":"type","deprecated":false,"docs":null},{"name":"Column","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/row-column"},{"name":"Command","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/command"},{"name":"CommandGroup","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/command"},{"name":"CommandItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/command"},{"name":"CommandProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/command"},{"name":"ComposedChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/composed-chart"},{"name":"ComposedChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/composed-chart"},{"name":"ComposedSeries","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/composed-chart"},{"name":"composite","kind":"utility","deprecated":false,"docs":null},{"name":"Container","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/container"},{"name":"ContainerBreakpoint","kind":"type","deprecated":false,"docs":null},{"name":"ContainerBreakpointOptions","kind":"type","deprecated":false,"docs":null},{"name":"ContainerProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/container"},{"name":"contrastRatio","kind":"utility","deprecated":false,"docs":null},{"name":"darkColors","kind":"token","deprecated":false,"docs":"https://canvas.nannier.com/tokens/colors"},{"name":"darkGlass","kind":"token","deprecated":false,"docs":null},{"name":"DashboardGrid","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/dashboard-grid"},{"name":"DashboardGridProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/dashboard-grid"},{"name":"DashboardWidget","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/dashboard-grid"},{"name":"DataTable","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/data-table"},{"name":"DataTableColumn","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/data-table"},{"name":"DataTableGroup","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/data-table"},{"name":"DataTableProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/data-table"},{"name":"DataTableSort","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/data-table"},{"name":"Density","kind":"type","deprecated":false,"docs":null},{"name":"DepthChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/depth-chart"},{"name":"DepthChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/depth-chart"},{"name":"DepthLevel","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/depth-chart"},{"name":"DescriptionList","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/description-lists"},{"name":"DescriptionListAvatar","kind":"type","deprecated":false,"docs":null},{"name":"DescriptionListItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/description-lists"},{"name":"DescriptionListProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/description-lists"},{"name":"Dialog","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/dialog"},{"name":"DialogProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/dialog"},{"name":"Divider","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/divider"},{"name":"DividerProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/divider"},{"name":"DragDropProvider","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/drag-drop"},{"name":"DragDropProviderProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/drag-drop"},{"name":"Draggable","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/drag-drop"},{"name":"DraggableProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/drag-drop"},{"name":"DragHandle","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/drag-drop"},{"name":"DragHandleProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/drag-drop"},{"name":"Drawer","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/drawer"},{"name":"DrawerProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/drawer"},{"name":"Dropdown","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/dropdown"},{"name":"DropdownItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/dropdown"},{"name":"DropdownProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/dropdown"},{"name":"DropEvent","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/drag-drop"},{"name":"DropZone","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/drag-drop"},{"name":"DropZoneProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/drag-drop"},{"name":"Emblem","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/emblem"},{"name":"EmblemProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/emblem"},{"name":"EmptyState","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/empty-state"},{"name":"EmptyStateProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/empty-state"},{"name":"Feed","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/feeds"},{"name":"FeedItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/feeds"},{"name":"FeedProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/feeds"},{"name":"Field","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/field"},{"name":"FieldProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/field"},{"name":"FilterGroup","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/filter-panel"},{"name":"FilterOption","kind":"type","deprecated":false,"docs":null},{"name":"FilterPanel","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/filter-panel"},{"name":"FilterPanelProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/filter-panel"},{"name":"flagOf","kind":"utility","deprecated":false,"docs":null},{"name":"FlexProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/row-column"},{"name":"FontFaces","kind":"type","deprecated":false,"docs":null},{"name":"FontWeightKey","kind":"type","deprecated":false,"docs":null},{"name":"Form","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/form"},{"name":"formFactor","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/tokens/layout"},{"name":"FormFactor","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/tokens/layout"},{"name":"FormProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/form"},{"name":"FormSection","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/form"},{"name":"FormSectionProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/form"},{"name":"FunnelChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/funnel-chart"},{"name":"FunnelChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/funnel-chart"},{"name":"Gauge","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/gauge"},{"name":"GaugeProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/gauge"},{"name":"GeoMap","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/geo-map"},{"name":"GeoMapPoint","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/geo-map"},{"name":"GeoMapProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/geo-map"},{"name":"getDensity","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"getPalette","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"getSurface","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"getTheme","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"GlassBlurPlane","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"GlassBlurPlaneHandle","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"GlassBlurPlaneProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"GlassBlurScope","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"GlassBlurScopeProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"glassByScheme","kind":"token","deprecated":false,"docs":"https://canvas.nannier.com/tokens/colors"},{"name":"GlassLayer","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"GlassModalBlurTarget","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"GlassSurface","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"GlassSurfaceProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"GlassTokens","kind":"type","deprecated":false,"docs":null},{"name":"Grid","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/grid"},{"name":"GridItem","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/grid"},{"name":"GridItemProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/grid"},{"name":"GridList","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/grid-lists"},{"name":"GridListAction","kind":"type","deprecated":false,"docs":null},{"name":"GridListItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/grid-lists"},{"name":"GridListProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/grid-lists"},{"name":"GridProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/grid"},{"name":"Heatmap","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/heatmap"},{"name":"HeatmapProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/heatmap"},{"name":"Histogram","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/histogram"},{"name":"HistogramProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/histogram"},{"name":"hsl","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"Hue","kind":"type","deprecated":false,"docs":null},{"name":"Icon","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/icon"},{"name":"ICON_CATEGORIES","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/components/icon"},{"name":"ICON_NAMES","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/components/icon"},{"name":"IconCategory","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/icon"},{"name":"IconName","kind":"type","deprecated":false,"docs":null},{"name":"IconProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/icon"},{"name":"Image","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/image"},{"name":"ImageProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/image"},{"name":"ImageStyle","kind":"type","deprecated":false,"docs":null},{"name":"inkOn","kind":"utility","deprecated":false,"docs":null},{"name":"Input","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/input"},{"name":"InputOTP","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/input-otp"},{"name":"InputOTPProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/input-otp"},{"name":"InputProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/input"},{"name":"InteractionOverride","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/pressable"},{"name":"InteractionOverrideProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/pressable"},{"name":"Kbd","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/kbd"},{"name":"KbdProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/kbd"},{"name":"LayoutChangeEvent","kind":"type","deprecated":false,"docs":null},{"name":"LayoutStyle","kind":"type","deprecated":false,"docs":null},{"name":"lightColors","kind":"token","deprecated":false,"docs":"https://canvas.nannier.com/tokens/colors"},{"name":"lightGlass","kind":"token","deprecated":false,"docs":null},{"name":"LineChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/line-chart"},{"name":"LineChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/line-chart"},{"name":"liquidGlassAvailable","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/patterns/glass"},{"name":"Listbox","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/listbox"},{"name":"ListboxItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/listbox"},{"name":"ListboxProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/listbox"},{"name":"Markdown","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"MarkdownProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/chat"},{"name":"MeasuredWidth","kind":"type","deprecated":false,"docs":null},{"name":"MeasureProps","kind":"type","deprecated":false,"docs":null},{"name":"MediaObject","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/media-objects"},{"name":"MediaObjectProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/media-objects"},{"name":"MetricBreakdown","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/metric-breakdown"},{"name":"MetricBreakdownChip","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/metric-breakdown"},{"name":"MetricBreakdownProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/metric-breakdown"},{"name":"mixOklab","kind":"utility","deprecated":false,"docs":null},{"name":"NativeScrollEvent","kind":"type","deprecated":false,"docs":null},{"name":"NativeSyntheticEvent","kind":"type","deprecated":false,"docs":null},{"name":"Navbar","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/navbars"},{"name":"NavbarProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/navbars"},{"name":"OpticalFaces","kind":"type","deprecated":false,"docs":null},{"name":"OverlayHost","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"OverlayProvider","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"OverlayProviderProps","kind":"type","deprecated":false,"docs":null},{"name":"OverlayViewportInsets","kind":"type","deprecated":false,"docs":null},{"name":"Page","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/app-frame"},{"name":"PageProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/app-frame"},{"name":"Pagination","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/pagination"},{"name":"PaginationProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/pagination"},{"name":"palette","kind":"token","deprecated":false,"docs":null},{"name":"Palette","kind":"type","deprecated":false,"docs":null},{"name":"paletteHue","kind":"token","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"PALETTES","kind":"token","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"PHONE_COUNTRIES","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/components/phone-input"},{"name":"PhoneCountry","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/phone-input"},{"name":"PhoneEntryProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/phone-input"},{"name":"PhoneInput","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/phone-input"},{"name":"PhoneInputProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/phone-input"},{"name":"PieChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/pie-chart"},{"name":"PieChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/pie-chart"},{"name":"PlatformKey","kind":"type","deprecated":false,"docs":null},{"name":"Popover","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/popover"},{"name":"PopoverProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/popover"},{"name":"Pressable","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/pressable"},{"name":"PressableProps","kind":"type","deprecated":false,"docs":null},{"name":"PressableStateCallbackType","kind":"type","deprecated":false,"docs":null},{"name":"Progress","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/progress"},{"name":"ProgressProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/progress"},{"name":"ProgressRing","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/progress-ring"},{"name":"ProgressRingProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/progress-ring"},{"name":"QRCode","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/qrcode"},{"name":"QRCodeProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/qrcode"},{"name":"RadarChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/radar-chart"},{"name":"RadarChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/radar-chart"},{"name":"RadialBarChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/radial-bar-chart"},{"name":"RadialBarChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/radial-bar-chart"},{"name":"Radio","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/radio"},{"name":"RadioGroup","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/radio"},{"name":"RadioGroupProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/radio"},{"name":"RadioProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/radio"},{"name":"radius","kind":"token","deprecated":false,"docs":null},{"name":"RangeAreaChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/range-area-chart"},{"name":"RangeAreaChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/range-area-chart"},{"name":"RangePoint","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/range-area-chart"},{"name":"relativeLuminance","kind":"utility","deprecated":false,"docs":null},{"name":"responsive","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/tokens/layout"},{"name":"Responsive","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/tokens/layout"},{"name":"Reveal","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/reveal"},{"name":"RevealGroup","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/reveal"},{"name":"RevealGroupProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/reveal"},{"name":"RevealProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/reveal"},{"name":"Row","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/row-column"},{"name":"RowMenu","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/row-menu"},{"name":"RowMenuItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/row-menu"},{"name":"RowMenuProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/row-menu"},{"name":"ScatterPlot","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/scatter-plot"},{"name":"ScatterPlotProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/scatter-plot"},{"name":"ScatterPoint","kind":"type","deprecated":false,"docs":null},{"name":"ScatterSelection","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/scatter-plot"},{"name":"ScatterSeries","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/scatter-plot"},{"name":"ScrollView","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/scroll-view"},{"name":"ScrollViewProps","kind":"type","deprecated":false,"docs":null},{"name":"Select","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/select"},{"name":"SelectProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/select"},{"name":"ServiceHealthItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/service-health-list"},{"name":"ServiceHealthList","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/service-health-list"},{"name":"ServiceHealthListProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/service-health-list"},{"name":"setDensity","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"setPalette","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"setSurface","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"setTheme","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"shape","kind":"token","deprecated":false,"docs":null},{"name":"ShapeTokens","kind":"type","deprecated":false,"docs":null},{"name":"Sidebar","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/sidebar"},{"name":"SidebarAccount","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/sidebar"},{"name":"SidebarItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/sidebar"},{"name":"SidebarProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/sidebar"},{"name":"SidebarSection","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/sidebar"},{"name":"SizingKey","kind":"type","deprecated":false,"docs":null},{"name":"Skeleton","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/skeleton"},{"name":"SkeletonProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/skeleton"},{"name":"Slider","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/slider"},{"name":"SliderProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/slider"},{"name":"spacing","kind":"token","deprecated":false,"docs":null},{"name":"Sparkline","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/sparkline"},{"name":"SparklineProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/sparkline"},{"name":"Spinner","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/spinner"},{"name":"SpinnerProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/spinner"},{"name":"StackedBar","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/stacked-bar"},{"name":"StackedBarProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/stacked-bar"},{"name":"StackedList","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/stacked-lists"},{"name":"StackedListItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/stacked-lists"},{"name":"StackedListMove","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/stacked-lists"},{"name":"StackedListProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/stacked-lists"},{"name":"StackedSegment","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/pie-chart"},{"name":"StatItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/stats"},{"name":"Stats","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/stats"},{"name":"StatsProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/stats"},{"name":"statusColors","kind":"utility","deprecated":false,"docs":null},{"name":"StatusColors","kind":"type","deprecated":false,"docs":null},{"name":"StatusColorTone","kind":"type","deprecated":false,"docs":null},{"name":"statusHues","kind":"token","deprecated":false,"docs":"https://canvas.nannier.com/tokens/colors"},{"name":"StatusTone","kind":"type","deprecated":false,"docs":null},{"name":"Step","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/steps"},{"name":"Stepper","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/stepper"},{"name":"StepperProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/stepper"},{"name":"Steps","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/steps"},{"name":"StepsProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/steps"},{"name":"StyleProp","kind":"type","deprecated":false,"docs":null},{"name":"Surface","kind":"type","deprecated":false,"docs":null},{"name":"Swatch","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/swatch"},{"name":"SwatchProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/swatch"},{"name":"Switch","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/switch"},{"name":"SwitchProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/switch"},{"name":"TabBar","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/tab-bar"},{"name":"TabBarItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/tab-bar"},{"name":"TabBarProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/tab-bar"},{"name":"TabItem","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/tabs"},{"name":"Tabs","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/tabs"},{"name":"TabsProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/tabs"},{"name":"Text","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/text"},{"name":"Textarea","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/textarea"},{"name":"TextareaProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/textarea"},{"name":"TextInput","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/text-input"},{"name":"TextInputProps","kind":"type","deprecated":false,"docs":null},{"name":"TextProps","kind":"type","deprecated":false,"docs":null},{"name":"TextStyle","kind":"type","deprecated":false,"docs":null},{"name":"Theme","kind":"type","deprecated":false,"docs":null},{"name":"ThemeFonts","kind":"type","deprecated":false,"docs":null},{"name":"ThemeProvider","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"ThemeProviderProps","kind":"type","deprecated":false,"docs":null},{"name":"ThemeTokenOverrides","kind":"type","deprecated":false,"docs":null},{"name":"ThemeValue","kind":"type","deprecated":false,"docs":null},{"name":"Toast","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/toast"},{"name":"ToastAction","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/toast"},{"name":"ToastHandle","kind":"type","deprecated":false,"docs":null},{"name":"ToastOptions","kind":"type","deprecated":false,"docs":null},{"name":"ToastProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/toast"},{"name":"ToastProvider","kind":"part","deprecated":false,"docs":"https://canvas.nannier.com/components/toast"},{"name":"toggleTheme","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"token","kind":"utility","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"Tooltip","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/tooltip"},{"name":"TooltipProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/tooltip"},{"name":"Treemap","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/treemap"},{"name":"TreemapDatum","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/treemap"},{"name":"TreemapProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/treemap"},{"name":"typeface","kind":"token","deprecated":false,"docs":null},{"name":"Typography","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/typography"},{"name":"TypographyProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/typography"},{"name":"UptimeBar","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/uptime-bar"},{"name":"UptimeBarProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/uptime-bar"},{"name":"UptimePeriod","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/uptime-bar"},{"name":"useBreakpoint","kind":"hook","deprecated":false,"docs":"https://canvas.nannier.com/patterns/responsive"},{"name":"useContainerBreakpoint","kind":"hook","deprecated":false,"docs":null},{"name":"useContainerWidth","kind":"hook","deprecated":false,"docs":null},{"name":"useFormFactor","kind":"hook","deprecated":false,"docs":"https://canvas.nannier.com/patterns/responsive"},{"name":"useGlassBlurPlane","kind":"hook","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"useHoverCapable","kind":"hook","deprecated":false,"docs":"https://canvas.nannier.com/patterns/responsive"},{"name":"useIncreasedContrast","kind":"hook","deprecated":false,"docs":null},{"name":"useMeasuredWidth","kind":"hook","deprecated":false,"docs":null},{"name":"useOverlayHost","kind":"hook","deprecated":false,"docs":"https://canvas.nannier.com/integration"},{"name":"usePointerCoarse","kind":"hook","deprecated":false,"docs":"https://canvas.nannier.com/patterns/responsive"},{"name":"useReducedMotion","kind":"hook","deprecated":false,"docs":null},{"name":"useReducedTransparency","kind":"hook","deprecated":false,"docs":null},{"name":"useResponsive","kind":"hook","deprecated":false,"docs":"https://canvas.nannier.com/patterns/responsive"},{"name":"useTheme","kind":"hook","deprecated":false,"docs":"https://canvas.nannier.com/theming"},{"name":"useToast","kind":"hook","deprecated":false,"docs":"https://canvas.nannier.com/components/toast"},{"name":"Video","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/video"},{"name":"VideoProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/video"},{"name":"VideoRadius","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/video"},{"name":"VideoSource","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/video"},{"name":"View","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/view"},{"name":"ViewProps","kind":"type","deprecated":false,"docs":null},{"name":"ViewStyle","kind":"type","deprecated":false,"docs":null},{"name":"WaterfallChart","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/waterfall-chart"},{"name":"WaterfallChartProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/waterfall-chart"},{"name":"WaterfallStep","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/waterfall-chart"},{"name":"WidthKey","kind":"type","deprecated":false,"docs":null},{"name":"widths","kind":"token","deprecated":false,"docs":null},{"name":"Wizard","kind":"component","deprecated":false,"docs":"https://canvas.nannier.com/components/wizard"},{"name":"WizardProps","kind":"type","deprecated":false,"docs":"https://canvas.nannier.com/components/wizard"}],"theme":[{"name":"ThemeProviderProps","props":[{"name":"dark","type":"boolean | undefined","required":false,"description":"Force the dark color scheme.","default":"false","group":0},{"name":"light","type":"boolean | undefined","required":false,"description":"Force the light color scheme.","default":"false","group":0},{"name":"scheme","type":"ColorScheme | undefined","required":false,"description":"Legacy value form of the scheme axis (\"light\" | \"dark\"), kept for back-compat and for config-driven code that already holds a `ColorScheme` value (a stored preference, an <html> hook). The boolean axis above wins when both are passed.","group":0},{"name":"ssrScheme","type":"ColorScheme | undefined","required":false,"description":"The scheme the SERVER rendered, for SSR/SSG apps (Next.js and the like) whose client scheme can differ from it (a stored preference, the OS). Canvas resolves colors in JS and serializes them into the server HTML as literal inline styles, so when the hydration render disagrees with that HTML, React logs a mismatch and keeps the server's colors on any element that never re-renders again: components stay stuck in the server's scheme. With `ssrScheme` set, the provider renders it on the server AND for the hydration render (matching the server HTML exactly), then applies the requested scheme (the boolean axis or the legacy `scheme` prop) right after mount; that switch re-renders every consumer, which writes the real colors to the DOM. Pass the same value the server resolves (e.g. the next-themes `defaultTheme`). Omit in client-only apps and on native.","group":0},{"name":"violet","type":"boolean | undefined","required":false,"description":"Paint the accent violet (hue 285), the default.","default":"false","group":1},{"name":"cyan","type":"boolean | undefined","required":false,"description":"Paint the accent cyan (hue 205).","default":"false","group":1},{"name":"mint","type":"boolean | undefined","required":false,"description":"Paint the accent mint (hue 165).","default":"false","group":1},{"name":"rose","type":"boolean | undefined","required":false,"description":"Paint the accent rose (hue 20).","default":"false","group":1},{"name":"amber","type":"boolean | undefined","required":false,"description":"Paint the accent amber (hue 75).","default":"false","group":1},{"name":"ssrPalette","type":"Palette | undefined","required":false,"description":"The palette the SERVER rendered, for SSR/SSG apps whose client palette can differ from it (a stored preference: `getPalette()` reads one on the web). The `ssrScheme` contract applied to the palette axis: the server render and the hydration render paint this palette, matching the server HTML exactly, and the requested one (`cyan`, `mint` and so on) applies right after mount. Omit in client-only apps and on native.","group":1},{"name":"ssrBreakpoint","type":"BreakpointKey | \"base\" | undefined","required":false,"description":"The breakpoint bucket the SERVER should assume, for SSR/SSG apps (the `ssrScheme` contract applied to the viewport axis). The server cannot measure a window, so `useBreakpoint`/`useResponsive`/`useFormFactor` resolve to the desktop `base` there by default; an app that knows it is serving a narrow client (UA hints) passes the bucket the server should render instead (e.g. \"sm\" for phones). The server render and the hydration render use it, then the real measured bucket re-renders every consumer right after hydration. Omit in client-only apps and on native.","group":1},{"name":"glass","type":"boolean | undefined","required":false,"description":"Request role-appropriate glass: stable content material and functional Liquid Glass where supported. Semantic tokens remain opaque.","default":"false","group":2},{"name":"solid","type":"boolean | undefined","required":false,"description":"Request complete opaque surfaces without glass effects, even on iOS 26+.","default":"false","group":2},{"name":"surface","type":"Surface | undefined","required":false,"description":"Legacy value form of the surface axis (\"solid\" | \"glass\"), kept for back-compat and for config-driven code that already holds a `Surface` value. The boolean axis above wins when both are passed.","group":2},{"name":"tokens","type":"ThemeTokenOverrides | undefined","required":false,"description":"Brand token overrides, merged over the active palette's base tokens so a consumer can rebrand the kit (e.g. `tokens={{ primary: \"#7c3aed\" }}`) without forking the token files. Pass a flat `Partial<ColorTokens>` to apply the same overrides to both schemes, or `{ light, dark }` to override each scheme separately. These are the SEMANTIC tokens only; the glass material carries its own fill (`glassByScheme`) and is never rewritten by a rebrand, so the two are independent. Pass a stable reference (a module constant or a memoized object); an inline literal re-creates the theme value on every render. Unlike `fonts`, a nested ThemeProvider does not inherit a parent's `tokens`: a nested provider is how a subtree shows its own palette or brand, so it paints its palette unbranded unless it is given overrides of its own. Pass the same constant again to carry a rebrand into a nested provider.","group":2},{"name":"fonts","type":"ThemeFonts | undefined","required":false,"description":"The typefaces the app registered, so the kit can paint its labels in the brand faces (`typeface.sans` is Instrument Sans, `typeface.display` Bricolage Grotesque, `typeface.mono` JetBrains Mono). Each entry is either one family name that carries every weight (a variable font, an OS-installed family) or a map from weight to the face registered for that weight (expo-google-fonts style: `{ \"400\": \"InstrumentSans_400Regular\", \"500\": \"InstrumentSans_500Medium\" }`). Pass it once, on the app's root provider: the faces are what the app loaded, not a per-subtree choice, so a nested ThemeProvider that omits `fonts` keeps the nearest parent provider's, and one that passes it uses its own map in place of the parent's (the roles are not merged; a stable empty map, `{}`, returns that subtree to the system face). Omit it on the root and the kit renders in the platform's system face, as it always has. Pass a stable reference (a module constant); an inline literal re-creates the theme value on every render.","group":2},{"name":"children","type":"ReactNode","required":true,"description":"","group":2}],"groups":[{"title":"Scheme axis","pickOne":true,"note":"Scheme axis (pick one; omit both to follow the OS appearance). The color scheme spelled like every other Canvas axis: the prop name is the value. `dark` wins when both are passed."},{"title":"Palette axis","pickOne":true,"note":"Palette axis (pick one; omit for the default, violet). The accent hue, spelled like every other axis: the prop name is the value. It applies in both schemes. When more than one is passed the first in this order wins: cyan, mint, rose, amber, violet."},{"title":"Surface axis","pickOne":true,"note":"Surface axis (pick one; omit for the platform default: glass on iOS 26+, the native system material for that layer, solid elsewhere). The theming-level glass switch, spelled like every other Canvas axis; there is no per-component glass prop. `glass` wins when both are passed."}],"inherits":[]}],"sharedProps":[{"name":"MeasureProps","props":[{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":0}],"groups":[{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":[]}],"components":[{"slug":"accordion","name":"Accordion","category":"molecules","description":"A vertically stacked group of disclosure rows: each `items` entry is a header (its `title` plus a chevron that rotates when the row opens) over a collapsible content panel.","source":"src/molecules/accordion/accordion.md","url":"https://canvas.nannier.com/ai/4.2.0/components/accordion.md","humanUrl":"https://canvas.nannier.com/components/accordion","exports":["Accordion","AccordionItem","AccordionProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"AccordionProps","props":[{"name":"activity","type":"boolean | undefined","required":false,"description":"Original Argus run disclosure surface, header and trace insets.","default":"false"},{"name":"compact","type":"boolean | undefined","required":false,"description":"Compact activity header and trace indentation.","default":"false"},{"name":"renderHeader","type":"((item: AccordionItem, expanded: boolean, indicator: ReactNode) => ReactNode) | undefined","required":false,"description":"Activity header content; the Accordion owns its trigger and indicator."},{"name":"items","type":"AccordionItem[] | undefined","required":false,"description":"The disclosure rows, top to bottom."},{"name":"value","type":"string | string[] | undefined","required":false,"description":"Controlled open state. A single key in single-open mode, an array of keys in `multiple` mode. Pair with `onValueChange`. Omit for uncontrolled."},{"name":"defaultValue","type":"string | string[] | undefined","required":false,"description":"Initial open state for the uncontrolled case (read once)."},{"name":"onValueChange","type":"((value: string | string[]) => void) | undefined","required":false,"description":"Called with the next open value whenever a header toggles."},{"name":"multiple","type":"boolean | undefined","required":false,"description":"Allow more than one panel open at once (default: single-open).","default":"false"},{"name":"card","type":"boolean | undefined","required":false,"description":"Card surface: wraps the group in an outlined card container with inset headers and content (web/Android). On iOS the default Accordion already renders as the inset-grouped card, so `card` is a no-op there.","default":"false"},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Disable the whole group (every row stops toggling and dims).","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"A vertically stacked group of disclosure rows: each `items` entry is a header (its `title` plus a chevron that rotates when the row opens) over a collapsible content panel.\n\nSingle-open by default (opening one row closes the others); pass `multiple` to let any number stay open. Open state is controlled (`value` + `onValueChange`) or uncontrolled (`defaultValue`). An item's `description` adds a muted secondary line under its title;\n`card` wraps the whole group in an outlined card surface on web and Android (on iOS the default look already is the inset-grouped card, so `card` is a no-op there).","ios":"A vertically stacked group of disclosure rows: each `items` entry is a header (its `title` plus a chevron that rotates when the row opens) over a collapsible content panel.\n\nSingle-open by default (opening one row closes the others); pass `multiple` to let any number stay open. Open state is controlled (`value` + `onValueChange`) or uncontrolled (`defaultValue`). An item's `description` adds a muted secondary line under its title;\non iOS the default look already is the inset-grouped card, so `card` is a no-op there.","android":"A vertically stacked group of disclosure rows: each `items` entry is a header (its `title` plus a chevron that rotates when the row opens) over a collapsible content panel.\n\nSingle-open by default (opening one row closes the others); pass `multiple` to let any number stay open. Open state is controlled (`value` + `onValueChange`) or uncontrolled (`defaultValue`). An item's `description` adds a muted secondary line under its title;\n`card` wraps the whole group in an outlined card surface."}},{"slug":"action-panels","name":"ActionPanel","category":"molecules","description":"Section panel with headline, body text, and one action. Used to surface a single decision or call-to-action.","source":"src/molecules/action-panels/action-panels.md","url":"https://canvas.nannier.com/ai/4.2.0/components/action-panels.md","humanUrl":"https://canvas.nannier.com/components/action-panels","exports":["ActionPanel","ActionPanelProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ActionPanelProps","props":[{"name":"title","type":"string | undefined","required":false,"description":"The headline: what the action acts on."},{"name":"description","type":"string | undefined","required":false,"description":"The consequence copy beneath the title: what happens when the action fires."},{"name":"actionLabel","type":"string | undefined","required":false,"description":"The action button label."},{"name":"onAction","type":"(() => void) | undefined","required":false,"description":"Fired when the action button is pressed."},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (omit for the neutral, primary-action default).","default":"false","group":0},{"name":"inline","type":"boolean | undefined","required":false,"description":"Layout (pick one; default stacks the action below the copy).","default":"false","group":1},{"name":"toggle","type":"boolean | undefined","required":false,"description":"Affordance: render the action as an on/off Switch instead of a Button. The panel always lays out inline in this mode.","default":"false","group":2},{"name":"checked","type":"boolean | undefined","required":false,"description":"The Switch on/off state when `toggle` is set (CONTROLLED). Omit for uncontrolled use.","default":"false","group":2},{"name":"defaultChecked","type":"boolean | undefined","required":false,"description":"Initial Switch state for uncontrolled use (the toggle flips itself on press).","default":"false","group":2},{"name":"onToggle","type":"((next: boolean) => void) | undefined","required":false,"description":"Fired with the next checked value when the toggle Switch is flipped.","group":2},{"name":"children","type":"ReactNode","required":false,"description":"Content embedded in the panel under the copy (a block of field rows in a settings panel, say). The Button then closes the panel on the right, under a hairline, as the action that commits it; a toggle stays pinned beside the copy.","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":2}],"groups":[{"title":"Tone","pickOne":false,"note":"Tone (omit for the neutral, primary-action default)."},{"title":"Layout","pickOne":true,"note":"Layout (pick one; default stacks the action below the copy)."},{"title":"Affordance","pickOne":false,"note":"Affordance: render the action as an on/off Switch instead of a Button. The panel always lays out inline in this mode."}],"inherits":[]}],"platformNotes":{"web":"Section panel with headline, body text, and one action. Used to surface a single decision or call-to-action.\n\nThe panel is the v4 hand-off's on every platform (no platform ships an action panel): an 18 px inset at the card corner on a hairline over the card fill, a 600 15 title over a 13 px muted description. The action is an outline Button; `destructive` washes the panel in the danger tint, edges it in the destructive colour and makes the action destructive; `inline` pins the action beside the copy, wrapping it underneath when the panel is narrow. Embedded `children` sit under the copy, and the Button then closes the panel on the right as the primary action that commits them.","ios":"Section panel with headline, body text, and one action. Used to surface a single decision or call-to-action.\n\nThe panel is the v4 hand-off's on every platform (no platform ships an action panel): an 18 px inset at the card corner on a hairline over the card fill, a 600 15 title over a 13 px muted description. The action is an outline Button; `destructive` washes the panel in the danger tint, edges it in the destructive colour and makes the action destructive; `inline` pins the action beside the copy, wrapping it underneath when the panel is narrow. Embedded `children` sit under the copy, and the Button then closes the panel on the right as the primary action that commits them.","android":"Section panel with headline, body text, and one action. Used to surface a single decision or call-to-action.\n\nThe panel is the v4 hand-off's on every platform (no platform ships an action panel): an 18 px inset at the card corner on a hairline over the card fill, a 600 15 title over a 13 px muted description. The action is an outline Button; `destructive` washes the panel in the danger tint, edges it in the destructive colour and makes the action destructive; `inline` pins the action beside the copy, wrapping it underneath when the panel is narrow. Embedded `children` sit under the copy, and the Button then closes the panel on the right as the primary action that commits them."}},{"slug":"action-sheet","name":"ActionSheet","category":"organisms","description":"A modal sheet of contextual actions, the iOS action sheet idiom: a bottom sheet of choices summoned in response to a user action, over a dimmed scrim that glass on the web also blurs.","source":"src/organisms/action-sheet/action-sheet.md","url":"https://canvas.nannier.com/ai/4.2.0/components/action-sheet.md","humanUrl":"https://canvas.nannier.com/components/action-sheet","exports":["ActionSheet","ActionSheetAction","ActionSheetProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ActionSheetProps","props":[{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Omit for uncontrolled (a `trigger` opens it).","default":"false"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes (trigger press, scrim tap, Cancel, an action, back/escape)."},{"name":"trigger","type":"string | undefined","required":false,"description":"Label for an optional trigger button. When set, the sheet renders the button and opens itself on press (uncontrolled). Omit when you drive `open` yourself."},{"name":"title","type":"string | undefined","required":false,"description":"Optional header title (a left-aligned primary-label heading on iOS, a short centered heading on web, left-aligned on Android)."},{"name":"message","type":"string | undefined","required":false,"description":"Optional header message under the title."},{"name":"actions","type":"ActionSheetAction[]","required":true,"description":"The action rows. Each runs its `onPress` then closes the sheet."},{"name":"cancelLabel","type":"string | undefined","required":false,"description":"The Cancel row label (default \"Cancel\").","default":"\"Cancel\""},{"name":"embedded","type":"boolean | undefined","required":false,"description":"Show the open sheet as a non-modal specimen inside its parent, for a catalogue or a showcase: the stack rests against the parent's bottom edge (the parent gives it its height) over the dim, with no Modal, no rise, no focus trap and no close on Escape, native back or a tap on the dim. Its rows still run their actions. Ignored with `trigger`, which always opens a live sheet.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition for the bottom-anchored stack, composed onto the stack container; not a restyle hook. (The device's bottom safe-area inset is applied automatically, so it clears the home indicator without a manual `paddingBottom`.)"}],"groups":[],"inherits":[]}],"platformNotes":{"web":"A modal sheet of contextual actions, the iOS action sheet idiom:\na bottom sheet\nof choices summoned in response to a user action, over a dimmed scrim that glass\non the web also blurs.\n\nIt poses an optional title and message, lists a set of actions (any of which can\nbe destructive), and offers a Cancel. Selecting an action runs it and closes the\nsheet; tapping the scrim or Cancel closes it without acting. Pass a `trigger`\nlabel for a self-contained button that opens the sheet, or drive `open` /\n`onOpenChange` yourself. For a small contextual menu anchored to a control,\nreach for Dropdown or RowMenu instead.\n\nOn the web the sheet is two cards a little off the window's edges: a centered header\nover full-width rows in the accent's ink (a destructive one in the error ink), each under\na hairline, and a separate Cancel card.\niOS keeps its Liquid Glass sheet with detached\ncapsules, and Android the Material 3 bottom sheet with a drag handle and list rows.\n\niOS accessibility escape and Android system back request cancellation without\nrunning an action.\nAn open child overlay handles the request first. Disabled\nactions do not disable cancellation, and a controlled owner can keep the sheet\nopen. The visible Cancel row remains available to assistive technology.","ios":"A modal sheet of contextual actions, the iOS action sheet idiom:\na bottom sheet\nof choices summoned in response to a user action, over a dimmed scrim that glass\non the web also blurs.\n\nIt poses an optional title and message, lists a set of actions (any of which can\nbe destructive), and offers a Cancel. Selecting an action runs it and closes the\nsheet; tapping the scrim or Cancel closes it without acting. Pass a `trigger`\nlabel for a self-contained button that opens the sheet, or drive `open` /\n`onOpenChange` yourself. For a small contextual menu anchored to a control,\nreach for Dropdown or RowMenu instead.\n\nOn the web the sheet is two cards a little off the window's edges: a centered header\nover full-width rows in the accent's ink (a destructive one in the error ink), each under\na hairline, and a separate Cancel card.\niOS keeps its Liquid Glass sheet with detached capsules.\n\niOS accessibility escape requests cancellation without running an action.\nAn open child overlay handles the request first. Disabled\nactions do not disable cancellation, and a controlled owner can keep the sheet\nopen. The visible Cancel row remains available to assistive technology.","android":"A modal sheet of contextual actions, the bottom sheet idiom:\na bottom sheet\nof choices summoned in response to a user action, over a dimmed scrim that glass\non the web also blurs.\n\nIt poses an optional title and message, lists a set of actions (any of which can\nbe destructive), and offers a Cancel. Selecting an action runs it and closes the\nsheet; tapping the scrim or Cancel closes it without acting. Pass a `trigger`\nlabel for a self-contained button that opens the sheet, or drive `open` /\n`onOpenChange` yourself. For a small contextual menu anchored to a control,\nreach for Dropdown or RowMenu instead.\n\nOn the web the sheet is two cards a little off the window's edges: a centered header\nover full-width rows in the accent's ink (a destructive one in the error ink), each under\na hairline, and a separate Cancel card.\nAndroid keeps the Material 3 bottom sheet with a drag handle and list rows.\n\nAndroid system back requests cancellation without running an action.\nAn open child overlay handles the request first. Disabled\nactions do not disable cancellation, and a controlled owner can keep the sheet\nopen. The visible Cancel row remains available to assistive technology."}},{"slug":"alert","name":"Alert","category":"molecules","description":"Inline notification banners: info, success, warning, and destructive, plus a full-width announcement bar. For a blocking confirmation prompt, see Alert Dialog.","source":"src/molecules/alert/alert.md","url":"https://canvas.nannier.com/ai/4.2.0/components/alert.md","humanUrl":"https://canvas.nannier.com/components/alert","exports":["Alert","AlertProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"AlertProps","props":[{"name":"title","type":"string | undefined","required":false,"description":"Content.","group":0},{"name":"description","type":"string | undefined","required":false,"description":"Content.","group":0},{"name":"icon","type":"ReactNode","required":false,"description":"The leading glyph: an element (an `<Icon />`, tinted to the tone's color unless it sets its own, and sized to the banner's glyph) or a single text character. Omitted, the banner draws its tone's own glyph (an info circle on info and neutral, a check on success, an alert circle on warning, a cross on destructive); `null` draws none.","group":0},{"name":"info","type":"boolean | undefined","required":false,"description":"Tone (pick one; omit for the neutral default).","default":"false","group":1},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (pick one; omit for the neutral default).","default":"false","group":1},{"name":"warning","type":"boolean | undefined","required":false,"description":"Tone (pick one; omit for the neutral default).","default":"false","group":1},{"name":"destructive","type":"boolean | undefined","required":false,"description":"The danger tone. This is the name the intent axis uses across the kit (Button, AlertDialog, and every chart) and the one the design hand-off uses here too.","default":"false","group":1},{"name":"announcement","type":"boolean | undefined","required":false,"description":"The announcement bar: one line on the accent gradient (the accent running into the cyan series hue) in the accent's own ink, under its glow, with its `action` inline at the end. For page-wide news (\"v4 is live\"), not for a status. It is its own look, so it ignores the tone axis.","default":"false","group":1},{"name":"action","type":"{ label: string; onPress?: () => void; } | undefined","required":false,"description":"One action, as a label and a handler. On the announcement bar it sits inline at the end of the line, in the bar's ink; on the other looks it is a link Button in the actions region, before any `actions`.","group":1},{"name":"dismissible","type":"boolean | undefined","required":false,"description":"Shows a trailing dismiss control. Pressing it hides the banner out of the box (uncontrolled); pass `dismissed` to own that state instead.","default":"false","group":1},{"name":"dismissed","type":"boolean | undefined","required":false,"description":"Controlled dismissal: `true` hides the banner. Omit to let the Alert manage it.","default":"false","group":1},{"name":"defaultDismissed","type":"boolean | undefined","required":false,"description":"Uncontrolled seed: start hidden. Rarely useful; defaults to false.","default":"false","group":1},{"name":"onDismiss","type":"(() => void) | undefined","required":false,"description":"Fired when the dismiss control is pressed (both modes).","group":1},{"name":"children","type":"ReactNode","required":false,"description":"","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"actions","type":"ReactNode","required":false,"description":"A footer action region rendered under the body. The Alert owns the layout: it separates the actions from the description above and lays the buttons out in a row, so a call site passes the buttons directly (`actions={<Button primary small>Upgrade plan</Button>}`) with no wrapper. Pass a fragment for more than one action.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Content","pickOne":false},{"title":"Tone","pickOne":true,"note":"Tone (pick one; omit for the neutral default)."}],"inherits":[]}],"platformNotes":{"web":"Inline notification banners: info, success, warning, and destructive, plus a full-width announcement bar. For a blocking confirmation prompt, see Alert Dialog.\n\nA banner fills the parent it is given, so a column of alerts is the same measure top to bottom and a banner over a form lines up with the fields; a Container step sets the measure when the layout calls for one.\n\nA banner is a soft callout: the tone's wash under a 1px edge of the tone's color, the tone's own glyph in that color, a foreground title and a muted body, from `statusColors` (the helper Badge and every toned surface read). The neutral banner is the quiet muted surface with an info glyph in the muted ink. Pass `icon` to draw another glyph (an `<Icon />` takes the tone's color and the banner's 18px size), or `icon={null}` to draw none.","ios":"Inline notification banners: info, success, warning, and destructive, plus a full-width announcement bar. For a blocking confirmation prompt, see Alert Dialog.\n\nA banner fills the parent it is given, so a column of alerts is the same measure top to bottom and a banner over a form lines up with the fields; a Container step sets the measure when the layout calls for one.\n\nA banner is a soft callout: the tone's wash under a 1px edge of the tone's color, the tone's own glyph in that color, a foreground title and a muted body, from `statusColors` (the helper Badge and every toned surface read). The neutral banner is the quiet muted surface with an info glyph in the muted ink. Pass `icon` to draw another glyph (an `<Icon />` takes the tone's color and the banner's 18px size), or `icon={null}` to draw none.","android":"Inline notification banners: info, success, warning, and destructive, plus a full-width announcement bar. For a blocking confirmation prompt, see Alert Dialog.\n\nA banner fills the parent it is given, so a column of alerts is the same measure top to bottom and a banner over a form lines up with the fields; a Container step sets the measure when the layout calls for one.\n\nA banner is a soft callout: the tone's wash under a 1px edge of the tone's color, the tone's own glyph in that color, a foreground title and a muted body, from `statusColors` (the helper Badge and every toned surface read). The neutral banner is the quiet muted surface with an info glyph in the muted ink. Pass `icon` to draw another glyph (an `<Icon />` takes the tone's color and the banner's 18px size), or `icon={null}` to draw none."}},{"slug":"alert-dialog","name":"AlertDialog","category":"molecules","description":"Catalyst-style confirmation dialog: a centered panel over a dimmed backdrop, which glass on the web also blurs, with a title, description, optional body, and action buttons. Reserve it for decisions that must block the rest of the app.","source":"src/molecules/alert-dialog/alert-dialog.md","url":"https://canvas.nannier.com/ai/4.2.0/components/alert-dialog.md","humanUrl":"https://canvas.nannier.com/components/alert-dialog","exports":["AlertDialog","AlertDialogProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"AlertDialogProps","props":[{"name":"title","type":"string | undefined","required":false,"description":"Content (strings).","group":0},{"name":"description","type":"string | undefined","required":false,"description":"Content (strings).","group":0},{"name":"trigger","type":"string | undefined","required":false,"description":"Trigger button label. When set, the dialog renders the button and opens itself on press (uncontrolled). Omit when you drive `open` yourself.","group":1},{"name":"confirmLabel","type":"string | undefined","required":false,"description":"Action labels.","default":"\"Continue\"","group":2},{"name":"cancelLabel","type":"string | undefined","required":false,"description":"Action labels.","default":"\"Cancel\"","group":2},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Omit for uncontrolled (the trigger opens it).","default":"false","group":3},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes (trigger press, confirm, cancel).","group":4},{"name":"narrow","type":"boolean | undefined","required":false,"description":"Width (pick one; default is the medium panel).","default":"false","group":5},{"name":"small","type":"boolean | undefined","required":false,"description":"Width (pick one; default is the medium panel).","default":"false","group":5},{"name":"large","type":"boolean | undefined","required":false,"description":"Width (pick one; default is the medium panel).","default":"false","group":5},{"name":"withInput","type":"boolean | undefined","required":false,"description":"Body: render a confirmation field that gates confirm. The user must type the `confirmText` token (default \"DELETE\") for the confirm action to enable; until it matches exactly, confirm is disabled and `handleConfirm` is a no-op. This is a real safety gate, not a decorative field.","default":"false","group":6},{"name":"confirmText","type":"string | undefined","required":false,"description":"The token the confirmation field must match to enable confirm (default \"DELETE\"). Only used when `withInput` is set; drives the placeholder (\"type DELETE to confirm\"), the field's accessible name, and the gate.","default":"\"DELETE\"","group":6},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Confirm intent (default is a primary confirm).","default":"false","group":7},{"name":"onConfirm","type":"(() => void) | undefined","required":false,"description":"Action handlers.","group":8},{"name":"onCancel","type":"(() => void) | undefined","required":false,"description":"Action handlers.","group":8},{"name":"overlay","type":"boolean | undefined","required":false,"description":"Presents the confirm OVER the page instead of inline where it is mounted. The default is a contained overlay, which the docs catalogue needs to show one inside an example stage. An application asking to confirm a destructive action needs the opposite: inline, the scrim appears wherever the component happens to sit, the page behind stays scrollable and clickable, and the dialog still claims `aria-modal`. Teleports into the nearest `OverlayProvider`; with none in the tree it renders in place.","default":"false","group":8},{"name":"embedded","type":"boolean | undefined","required":false,"description":"Show the open dialog as a non-modal specimen in the page, for a catalogue or a showcase: it keeps its look, its alertdialog role and its labelling, but does not take focus when it opens, trap Tab, return focus, claim `aria-modal`, or cancel on Escape or native back. Ignored with `trigger`, which always opens a live modal.","default":"false","group":8},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":8},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook.","group":8}],"groups":[{"title":"Content","pickOne":false,"note":"Content (strings)."},{"title":"Trigger button label","pickOne":false,"note":"Trigger button label. When set, the dialog renders the button and opens itself on press (uncontrolled). Omit when you drive `open` yourself."},{"title":"Action labels","pickOne":false},{"title":"Controlled open state","pickOne":false,"note":"Controlled open state. Omit for uncontrolled (the trigger opens it)."},{"title":"Fired when the open state changes","pickOne":false,"note":"Fired when the open state changes (trigger press, confirm, cancel)."},{"title":"Width","pickOne":true,"note":"Width (pick one; default is the medium panel)."},{"title":"Body","pickOne":false,"note":"Body: render a confirmation field that gates confirm. The user must type the `confirmText` token (default \"DELETE\") for the confirm action to enable; until it matches exactly, confirm is disabled and `handleConfirm` is a no-op. This is a real safety gate, not a decorative field."},{"title":"Confirm intent","pickOne":false,"note":"Confirm intent (default is a primary confirm)."},{"title":"Action handlers","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"Catalyst-style confirmation dialog: a centered panel over a dimmed backdrop, which glass on the web also blurs, with a title, description, optional body, and action buttons. Reserve it for decisions that must block the rest of the app.\n\nOn the web and Android the panel leads with a tone tile (a trash glyph on the\ndestructive wash, otherwise an info glyph on the accent's), then a display title over\nits description, and closes on two equal buttons: a secondary Cancel and the primary or\ndestructive confirm.\nOn iOS it is the system alert: centered text over a two-cell action\nrow under a hairline, the confirm in the error ink when destructive.\n\nBrowser Escape and iOS accessibility escape cancel the dialog,\nclear its\nconfirmation field and request `open=false`. The confirmation text gates only\nthe confirm action; cancellation remains available while confirm is disabled.\nAn open child overlay handles dismissal first. A controlled owner can refuse\nclosure without passing that request to a parent or calling `onConfirm`.\n\nAdd `embedded` to show an open alert dialog in a page as a specimen, the way a\ncatalogue or a showcase does: it keeps its look, its alertdialog role and its\nlabelling, but it is not modal. It does not take focus when it opens, trap Tab,\nreturn focus, set `aria-modal`, or cancel on Escape or native back, so the page\naround it keeps its scroll position and its keyboard order. `embedded` is ignored\nwith `trigger`, which always opens a live modal.","ios":"Catalyst-style confirmation dialog: a centered panel over a dimmed backdrop, which glass on the web also blurs, with a title, description, optional body, and action buttons. Reserve it for decisions that must block the rest of the app.\n\nOn iOS it is the system alert: centered text over a two-cell action\nrow under a hairline, the confirm in the error ink when destructive.\n\nBrowser Escape and iOS accessibility escape cancel the dialog,\nclear its\nconfirmation field and request `open=false`. The confirmation text gates only\nthe confirm action; cancellation remains available while confirm is disabled.\nAn open child overlay handles dismissal first. A controlled owner can refuse\nclosure without passing that request to a parent or calling `onConfirm`.\n\nAdd `embedded` to show an open alert dialog in a page as a specimen, the way a\ncatalogue or a showcase does: it keeps its look, its alertdialog role and its\nlabelling, but it is not modal. It does not take focus when it opens, trap Tab,\nreturn focus, set `aria-modal`, or cancel on Escape or native back, so the page\naround it keeps its scroll position and its keyboard order. `embedded` is ignored\nwith `trigger`, which always opens a live modal.","android":"Catalyst-style confirmation dialog: a centered panel over a dimmed backdrop, which glass on the web also blurs, with a title, description, optional body, and action buttons. Reserve it for decisions that must block the rest of the app.\n\nOn Android the panel leads with a tone tile (a trash glyph on the destructive wash, otherwise an info glyph on the accent's), then a display title over its description, and closes on two equal buttons: a secondary Cancel and the primary or destructive confirm.\n\nBrowser Escape and the system back cancel the dialog,\nclear its\nconfirmation field and request `open=false`. The confirmation text gates only\nthe confirm action; cancellation remains available while confirm is disabled.\nAn open child overlay handles dismissal first. A controlled owner can refuse\nclosure without passing that request to a parent or calling `onConfirm`.\n\nAdd `embedded` to show an open alert dialog in a page as a specimen, the way a\ncatalogue or a showcase does: it keeps its look, its alertdialog role and its\nlabelling, but it is not modal. It does not take focus when it opens, trap Tab,\nreturn focus, set `aria-modal`, or cancel on Escape or native back, so the page\naround it keeps its scroll position and its keyboard order. `embedded` is ignored\nwith `trigger`, which always opens a live modal."}},{"slug":"app-frame","name":"AppFrame","category":"organisms","description":"The app's root frame and its scrolling screens. `AppFrame` mounts the safe-area context and the app-root overlay host, pads all four safe-area edges over the theme background, renders the app's top chrome in a banner region and lets its body (a router's Stack) fill the height left. `Page` is one screen inside it: the main region, a scroller with page gutters whose content is capped and centered at a step of the width scale.","source":"src/organisms/app-frame/app-frame.md","url":"https://canvas.nannier.com/ai/4.2.0/components/app-frame.md","humanUrl":"https://canvas.nannier.com/components/app-frame","exports":["AppFrame","AppFrameProps","Page","PageProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"AppFrameProps","props":[{"name":"header","type":"ReactNode","required":false,"description":"The app's top chrome (a Navbar), rendered in a `role=\"banner\"` region above the body."},{"name":"children","type":"ReactNode","required":false,"description":"The body, typically a router's Stack: it fills the height the header leaves."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the frame."}],"groups":[],"inherits":[]},{"name":"PageProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"The page content, stacked in a Column at the loose (24) rhythm."},{"name":"fluid","type":"boolean | undefined","required":false,"description":"No cap: the content spans the page between its gutters. Wins over every step.","default":"false"},{"name":"inheritOverlays","type":"boolean | undefined","required":false,"description":"A plain content box instead of the page's own overlay host, so overlays opened in the page go to an enclosing host (a viewport-measured OverlayProvider around the page).","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the page's scroller."},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":0}],"groups":[{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"The app's root frame and its scrolling screens. `AppFrame` mounts the safe-area context and the app-root overlay host, pads all four safe-area edges over the theme background, renders the app's top chrome in a banner region and lets its body (a router's Stack) fill the height left. `Page` is one screen inside it: the main region, a scroller with page gutters whose content is capped and centered at a step of the width scale.\n\nMount `AppFrame` once, inside `ThemeProvider`, at the root of the app. It is the app-root `OverlayProvider` itself, so menus, sheets and toasts render above the whole window and keep clear of the status bar, the Dynamic Island and the home indicator; do not mount a second root host around it. The safe-area context comes from `react-native-safe-area-context` when the app installs it (Expo Router apps already do); without it the frame keeps its layout and the insets resolve to 0.\n\nEach screen renders a `Page`. Its content stacks at the loose rhythm and is capped at `widest` (1152) by default, the reading width of an app page on a desktop window; below the cap it fills the window between its gutters, which is all a phone is. A measure step (`xxxs` through `page`) narrows or widens it, `start` pins it to the leading edge, and `fluid` removes the cap. The page is also an overlay host of its own, so an anchored menu opened in it is framed by the page.","ios":"The app's root frame and its scrolling screens. `AppFrame` mounts the safe-area context and the app-root overlay host, pads all four safe-area edges over the theme background, renders the app's top chrome in a banner region and lets its body (a router's Stack) fill the height left. `Page` is one screen inside it: the main region, a scroller with page gutters whose content is capped and centered at a step of the width scale.\n\nMount `AppFrame` once, inside `ThemeProvider`, at the root of the app. It is the app-root `OverlayProvider` itself, so menus, sheets and toasts render above the whole window and keep clear of the status bar, the Dynamic Island and the home indicator; do not mount a second root host around it. The safe-area context comes from `react-native-safe-area-context` when the app installs it (Expo Router apps already do); without it the frame keeps its layout and the insets resolve to 0.\n\nEach screen renders a `Page`. Its content stacks at the loose rhythm and is capped at `widest` (1152) by default, the reading width of an app page on a desktop window; below the cap it fills the window between its gutters, which is all a phone is. A measure step (`xxxs` through `page`) narrows or widens it, `start` pins it to the leading edge, and `fluid` removes the cap. The page is also an overlay host of its own, so an anchored menu opened in it is framed by the page.","android":"The app's root frame and its scrolling screens. `AppFrame` mounts the safe-area context and the app-root overlay host, pads all four safe-area edges over the theme background, renders the app's top chrome in a banner region and lets its body (a router's Stack) fill the height left. `Page` is one screen inside it: the main region, a scroller with page gutters whose content is capped and centered at a step of the width scale.\n\nMount `AppFrame` once, inside `ThemeProvider`, at the root of the app. It is the app-root `OverlayProvider` itself, so menus, sheets and toasts render above the whole window and keep clear of the status bar, the Dynamic Island and the home indicator; do not mount a second root host around it. The safe-area context comes from `react-native-safe-area-context` when the app installs it (Expo Router apps already do); without it the frame keeps its layout and the insets resolve to 0.\n\nEach screen renders a `Page`. Its content stacks at the loose rhythm and is capped at `widest` (1152) by default, the reading width of an app page on a desktop window; below the cap it fills the window between its gutters, which is all a phone is. A measure step (`xxxs` through `page`) narrows or widens it, `start` pins it to the leading edge, and `fluid` removes the cap. The page is also an overlay host of its own, so an anchored menu opened in it is framed by the page."}},{"slug":"area-chart","name":"AreaChart","category":"charts","description":"Categorical-x series fills: overlapping translucent areas by default, or running-sum bands with `stacked`. Shares the line chart's curve, density, furniture, and scrub-to-inspect axes.","source":"src/charts/area-chart/area-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/area-chart.md","humanUrl":"https://canvas.nannier.com/components/area-chart","exports":["AreaChart","AreaChartProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"AreaChartProps","props":[{"name":"stacked","type":"boolean | undefined","required":false,"description":"Stack the series (running sums) instead of overlapping translucent fills.","default":"false"},{"name":"labels","type":"string[]","required":true,"description":"Category labels along the x axis, one per data column."},{"name":"series","type":"ChartSeries[]","required":true,"description":"The series to plot; colors follow the chart-1..8 tokens in fixed order, or a series' own `success`/`destructive` tone."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"max","type":"number | undefined","required":false,"description":"Y-axis maximum override. Defaults to a nice bound above the data max."},{"name":"min","type":"number | undefined","required":false,"description":"Y-axis minimum override. Defaults to 0 (or the data min when negative)."},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (single-series only; pick one; default is the primary fill).","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (single-series only; pick one; default is the primary fill).","default":"false","group":0},{"name":"curved","type":"boolean | undefined","required":false,"description":"Curve (omit for straight segments).","default":"false","group":1},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":2},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":2},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"hideAxes","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats tick labels and accessible values (data formatting, not styling).","group":3},{"name":"selected","type":"number | null | undefined","required":false,"description":"Scrub-to-inspect: the selected category index (controlled). Pass null for none.","group":3},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Scrub-to-inspect: the initially selected category (uncontrolled).","group":3},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press/scrub selects a category (or clears it with null).","group":3},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":3},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":3}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (single-series only; pick one; default is the primary fill)."},{"title":"Curve","pickOne":false,"note":"Curve (omit for straight segments)."},{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."},{"title":"Furniture visibility","pickOne":false}],"inherits":["CartesianSeriesProps"]}],"platformNotes":{"web":"Categorical-x series fills: overlapping translucent areas by default, or running-sum bands with `stacked`. Shares the line chart's curve, density, furniture, and scrub-to-inspect axes.","ios":"Categorical-x series fills: overlapping translucent areas by default, or running-sum bands with `stacked`. Shares the line chart's curve, density, furniture, and scrub-to-inspect axes.","android":"Categorical-x series fills: overlapping translucent areas by default, or running-sum bands with `stacked`. Shares the line chart's curve, density, furniture, and scrub-to-inspect axes."}},{"slug":"autocomplete","name":"Autocomplete","category":"atoms","description":"Text input + dropdown: searchable single-select.","source":"src/atoms/autocomplete/autocomplete.md","url":"https://canvas.nannier.com/ai/4.2.0/components/autocomplete.md","humanUrl":"https://canvas.nannier.com/components/autocomplete","exports":["Autocomplete","AutocompleteProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"AutocompleteProps","props":[{"name":"query","type":"string | undefined","required":false,"description":"The text typed into the field (controlled). Filters the option list. Omit and use `defaultQuery` for uncontrolled use: a bare Autocomplete is typeable out of the box."},{"name":"defaultQuery","type":"string | undefined","required":false,"description":"Initial query for uncontrolled use."},{"name":"onQueryChange","type":"((query: string) => void) | undefined","required":false,"description":"Fired with the new query on each keystroke, and with \"\" when a select resets the filter (both modes)."},{"name":"options","type":"(string | AutocompleteOption)[] | undefined","required":false,"description":"The full list of selectable options: bare labels, or `{ label, detail }` objects whose `detail` sits muted at the row's end (a version, a platform). The label is what the query matches and what `value` holds."},{"name":"value","type":"string | undefined","required":false,"description":"The selected option label (CONTROLLED), or \"\" for no selection. Omit for uncontrolled use."},{"name":"defaultValue","type":"string | undefined","required":false,"description":"Initial selected option for uncontrolled use (selecting a row updates it)."},{"name":"onValueChange","type":"((value: string) => void) | undefined","required":false,"description":"Fired on selection and with \"\" when the field is cleared, in both controlled and uncontrolled modes."},{"name":"placeholder","type":"string | undefined","required":false,"description":"Prompt shown in the field when there is no query or value.","default":"\"Search…\""},{"name":"open","type":"boolean | undefined","required":false,"description":"Whether the option list is open (CONTROLLED). Uncontrolled and closed by default; focusing or typing in the field opens it, the chevron toggles it. Pass `open` to pin it open, or `defaultOpen` to render it open initially while staying interactive. A disabled control stays closed regardless.","default":"false"},{"name":"defaultOpen","type":"boolean | undefined","required":false,"description":"Render the list open initially for uncontrolled use (selecting or the chevron closes it).","default":"false"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes (focus, typing, chevron, select)."},{"name":"label","type":"string | undefined","required":false,"description":"The field's persistent label. Its placement is platform-adaptive: iOS and web render it ABOVE the field; Android renders the Material 3 in-container FLOATING label (centered like a placeholder at rest, floating to the top once the list opens or a value fills the field). The label names the field for assistive tech."},{"name":"required","type":"boolean | undefined","required":false,"description":"Marks the field as required: appends a destructive \"*\" to the label (decorative, never in the accessible name) and announces the field as required, through aria-required on the web and with the word in its name (\"Assigned to, required\") on iOS and Android. The star and the spoken word take effect only alongside `label`.","default":"false"},{"name":"helperText","type":"string | undefined","required":false,"description":"Optional muted helper line rendered below the option list."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Dims the control and blocks interaction.","default":"false"},{"name":"onSelect","type":"((option: string) => void) | undefined","required":false,"description":"Called when an option is chosen by touch, pointer, or keyboard. Clearing only fires onValueChange."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the text field."},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium field, matching Input's h-9).","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium field, matching Input's h-9).","default":"false","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0},{"name":"ref","type":"React.Ref<RNTextInput>","required":false,"description":"Ref to the underlying React Native host. Supports object refs and callback refs; native methods follow the platform's behavior."},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":1}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default is the medium field, matching Input's h-9)."},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"Text input + dropdown: searchable single-select.\n\nPass `label` (and `required`) to name the field:\niOS and web render the label\nabove the field, while Android floats the Material 3 in-container label once the\nlist opens or a value fills the field. On Android the field grows with the\nuser's text size, and a label longer than the field truncates on one line clear\nof the toggle while the field's accessible name stays the whole label.\nThe required\nstar is decorative: a screen reader hears the field as required,\nfrom\n`aria-required` on the web and from its name (\"Assigned to, required\") on iOS and\nAndroid.\nThe field fills the parent it is given; a\nstep of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a\nContainer step sets its measure.\n\nOn web the field is the Canvas v4 search field: 40px tall (32 small, 48 large) on\nthe sunken fill behind the `field-border` hairline, a leading 16px search glyph, a\n400 14px value (13 small) and a 15px chevrons-up-down 10px from its end. The\npointer darkens the edge to the subtle ink, and focus rings it in the accent with a\n4px halo. The suggestions are a card 6px under the field with a 4px inset and 34px\nrows; the typed letters are marked in each suggestion on the accent's soft wash, and\nthe chosen suggestion sits on the `muted` wash.\niOS ships no combo box, so it draws\nthe same field and card at the iOS corners.\nAndroid keeps the Material 3 exposed\ndropdown: the filled field with its active indicator and drop-down triangle, and the\nMaterial menu whose active and chosen rows take the state layer.\n\nIn glass mode the suggestion list is a dense-layer glass card under the field (or\nabove it when it fits there); the field, its caret and its toggle stay in place,\nand picking a suggestion commits the value at once. Solid mode paints the skin's\nown list.\n\nArrow Down and Arrow Up open the list and highlight an option while focus stays in the text field. Navigation stops at the first and last matches. Home and End jump to those limits once an option is highlighted; otherwise they retain their text-editing behavior. Enter chooses the highlighted option, Escape closes the list without changing the query, and Tab closes it while moving focus. Typing resets the highlight. Confirming an input-method candidate does not select an option or submit a surrounding Form.\n\nUse `value` with `onValueChange` to control the selection, and use `\"\"` for a controlled empty value. The callback reports selections and clearing the field. `onSelect` remains a selection-only notification. The independent `query`/`onQueryChange` pair controls filtering; choosing an option resets the query to `\"\"`.\n\nThe disclosure button has a real target of at least 24px on web, 44pt on iOS, and 48dp on Android.\nThe small iOS field keeps a 44pt height so its touch target fits inside the field; its typography remains compact.\n\nAn option can carry a short `detail` (a version, a platform, a count): pass\n`{ label, detail }` objects in place of strings, and the detail sits at the row's end\nin the 11px mono face in the subtle ink.\nAndroid sets it in the row's type and muted ink.\nThe label is what the query matches and what `value` holds; the row is announced as\n\"label, detail\".","ios":"Text input + dropdown: searchable single-select.\n\nPass `label` (and `required`) to name the field:\niOS renders the label above the field.\nThe required\nstar is decorative: a screen reader hears the field as required,\nfrom its name (\"Assigned to, required\").\nThe field fills the parent it is given; a\nstep of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a\nContainer step sets its measure.\n\nOn web the field is the Canvas v4 search field: 40px tall (32 small, 48 large) on\nthe sunken fill behind the `field-border` hairline, a leading 16px search glyph, a\n400 14px value (13 small) and a 15px chevrons-up-down 10px from its end. The\npointer darkens the edge to the subtle ink, and focus rings it in the accent with a\n4px halo. The suggestions are a card 6px under the field with a 4px inset and 34px\nrows; the typed letters are marked in each suggestion on the accent's soft wash, and\nthe chosen suggestion sits on the `muted` wash.\niOS ships no combo box, so it draws\nthe same field and card at the iOS corners.\n\nIn glass mode the suggestion list is a dense-layer glass card under the field (or\nabove it when it fits there); the field, its caret and its toggle stay in place,\nand picking a suggestion commits the value at once. Solid mode paints the skin's\nown list.\n\nArrow Down and Arrow Up open the list and highlight an option while focus stays in the text field. Navigation stops at the first and last matches. Home and End jump to those limits once an option is highlighted; otherwise they retain their text-editing behavior. Enter chooses the highlighted option, Escape closes the list without changing the query, and Tab closes it while moving focus. Typing resets the highlight. Confirming an input-method candidate does not select an option or submit a surrounding Form.\n\nUse `value` with `onValueChange` to control the selection, and use `\"\"` for a controlled empty value. The callback reports selections and clearing the field. `onSelect` remains a selection-only notification. The independent `query`/`onQueryChange` pair controls filtering; choosing an option resets the query to `\"\"`.\n\nThe disclosure button has a real target of at least 44pt.\nThe small iOS field keeps a 44pt height so its touch target fits inside the field; its typography remains compact.\n\nAn option can carry a short `detail` (a version, a platform, a count): pass\n`{ label, detail }` objects in place of strings, and the detail sits at the row's end\nin the 11px mono face in the subtle ink.\nThe label is what the query matches and what `value` holds; the row is announced as\n\"label, detail\".","android":"Text input + dropdown: searchable single-select.\n\nPass `label` (and `required`) to name the field:\nAndroid floats the Material 3 in-container label once the list opens or a value fills the field. The field grows with the user's text size, and a label longer than the field truncates on one line clear of the toggle while the field's accessible name stays the whole label.\nThe required\nstar is decorative: a screen reader hears the field as required,\nfrom its name (\"Assigned to, required\").\nThe field fills the parent it is given; a\nstep of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a\nContainer step sets its measure.\n\nOn web the field is the Canvas v4 search field: 40px tall (32 small, 48 large) on\nthe sunken fill behind the `field-border` hairline, a leading 16px search glyph, a\n400 14px value (13 small) and a 15px chevrons-up-down 10px from its end. The\npointer darkens the edge to the subtle ink, and focus rings it in the accent with a\n4px halo. The suggestions are a card 6px under the field with a 4px inset and 34px\nrows; the typed letters are marked in each suggestion on the accent's soft wash, and\nthe chosen suggestion sits on the `muted` wash.\nAndroid keeps the Material 3 exposed\ndropdown: the filled field with its active indicator and drop-down triangle, and the\nMaterial menu whose active and chosen rows take the state layer.\n\nIn glass mode the suggestion list is a dense-layer glass card under the field (or\nabove it when it fits there); the field, its caret and its toggle stay in place,\nand picking a suggestion commits the value at once. Solid mode paints the skin's\nown list.\n\nArrow Down and Arrow Up open the list and highlight an option while focus stays in the text field. Navigation stops at the first and last matches. Home and End jump to those limits once an option is highlighted; otherwise they retain their text-editing behavior. Enter chooses the highlighted option, Escape closes the list without changing the query, and Tab closes it while moving focus. Typing resets the highlight. Confirming an input-method candidate does not select an option or submit a surrounding Form.\n\nUse `value` with `onValueChange` to control the selection, and use `\"\"` for a controlled empty value. The callback reports selections and clearing the field. `onSelect` remains a selection-only notification. The independent `query`/`onQueryChange` pair controls filtering; choosing an option resets the query to `\"\"`.\n\nThe disclosure button has a real target of at least 48dp.\n\nAn option can carry a short `detail` (a version, a platform, a count): pass\n`{ label, detail }` objects in place of strings, and the detail sits at the row's end\nin the 11px mono face in the subtle ink.\nAndroid sets it in the row's type and muted ink.\nThe label is what the query matches and what `value` holds; the row is announced as\n\"label, detail\"."}},{"slug":"avatar","name":"Avatar","category":"atoms","description":"A photo when the account has one, falling back to one or two initials on an identity disc: the name resolves to one of ten hues (or `hue` picks one), and the disc is that hue's soft wash under initials in the same hue, so one person keeps one colour on every platform and stays distinct in a stack or list. The initials sit at weight 600, 38% of the disc, and their ink is held to 4.5:1 on the wash in both schemes.","source":"src/atoms/avatar/avatar.md","url":"https://canvas.nannier.com/ai/4.2.0/components/avatar.md","humanUrl":"https://canvas.nannier.com/components/avatar","exports":["Avatar","AvatarGroup","AvatarGroupProps","AvatarMenu","AvatarMenuProps","AvatarProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"AvatarMenuProps","props":[{"name":"account","type":"boolean | undefined","required":false,"description":"Original Argus account control with a 32px orchid disc and compact role menu.","default":"false"},{"name":"triggerLabel","type":"string | undefined","required":false,"description":"Explicit name for the trigger."},{"name":"menuLabel","type":"string | undefined","required":false,"description":"Menu heading and accessible name, independent of the account's identity lines."},{"name":"menuWidth","type":"number | undefined","required":false,"description":""},{"name":"maxHeight","type":"number | undefined","required":false,"description":""},{"name":"name","type":"string | undefined","required":false,"description":"The account holder's full name: the pill's first line, the avatar's initials fallback and colour identity, and the menu header's title."},{"name":"email","type":"string | undefined","required":false,"description":"The secondary line under the name in the pill, and the menu header's description (typically the account's email address)."},{"name":"src","type":"string | undefined","required":false,"description":"The account photo. Falls back to the initials exactly like `Avatar`."},{"name":"initials","type":"string | undefined","required":false,"description":"Ready-made initials for the avatar, used verbatim when there is no photo."},{"name":"items","type":"DropdownItem[]","required":true,"description":"The menu rows, top to bottom. Same rows as `Dropdown` (icon, shortcut, destructive, disabled, separatorBefore)."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Avatar and chevron only, no name block: the topbar form of the pill.","default":"false"},{"name":"alignStart","type":"boolean | undefined","required":false,"description":"Hang the menu from the pill's LEADING edge instead of its trailing one.","default":"false","group":0},{"name":"alignEnd","type":"boolean | undefined","required":false,"description":"The default, spelled out: the menu's trailing edge meets the pill's.","default":"false","group":0},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Dimmed, non-opening pill: the menu never opens and the press is inert.","default":"false","group":0},{"name":"inline","type":"boolean | undefined","required":false,"description":"Draw the menu open and in flow under the pill instead of floating it over the page, a specimen of the account menu (Dropdown's `inline`): the pill reads as open and its press is inert, a row still fires `onSelect`, and `open` / `onOpenChange` have no effect.","default":"false","group":0},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Omit for uncontrolled (the pill opens/closes it).","default":"false","group":0},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes (pill press, row select, dismissal).","group":0},{"name":"onSelect","type":"((item: DropdownItem, index: number) => void) | undefined","required":false,"description":"Fired with the selected row and its index when a menu row is pressed.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Outer layout composition only (placement within a parent), never a restyle hook.","group":0}],"groups":[{"title":"Menu alignment","pickOne":false,"note":"Menu alignment (pick at most one). The pill's menu hangs from the TRAILING edge by default, which is where an account pill lives in a topbar and the only edge a right-parked trigger can open from without running off the surface. (Plain `Dropdown` defaults the other way, to its leading edge.) Precedence when both are passed: `alignEnd` > `alignStart`, so the explicit spelling of the default wins."}],"inherits":[]},{"name":"AvatarProps","props":[{"name":"logo","type":"boolean | undefined","required":false,"description":"Original 30px rounded brand mark with its action-to-selection gradient.","default":"false"},{"name":"annotation","type":"boolean | undefined","required":false,"description":"Reference identity geometry, smallest first in precedence.","default":"false"},{"name":"compact","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"account","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"row","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"person","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"profile","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"detail","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"hero","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"featured","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"spotlight","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"hue","type":"number | undefined","required":false,"description":"Stage identity hue, independent of the display name."},{"name":"whiteInk","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"bold","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"inverse","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"orchid","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"glow","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"sheen","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"mediumSheen","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"strongSheen","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"src","type":"string | number | undefined","required":false,"description":"The photo. A remote/URI string, or a bundled image module from `require(...)` / `import`. When set (and it loads), the image fills the circle and the initials fallback is hidden; if the image fails to load, it falls back to the initials."},{"name":"uri","type":"string | number | undefined","required":false,"description":"Alias for `src`, for callers that think in terms of a native image uri."},{"name":"name","type":"string | undefined","required":false,"description":"Full name. Drives the initials fallback AND the accessible label/alt text."},{"name":"initials","type":"string | undefined","required":false,"description":"Ready-made initials, used verbatim as the glyph (overrides `name`/`children`)."},{"name":"children","type":"ReactNode","required":false,"description":"Same as `name`; the rendered initials when no photo is supplied."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the avatar (the photo's alt text and, when pressable, the button's label). Falls back to `name`, then string `children`. Set it for a photo-only or pressable avatar that has no `name`."},{"name":"tiny","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the 40px row avatar, `tiny` the 20px disc, `small` 28, `large` 56). Precedence: `tiny` > `small` > `large`.","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the 40px row avatar, `tiny` the 20px disc, `small` 28, `large` 56). Precedence: `tiny` > `small` > `large`.","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the 40px row avatar, `tiny` the 20px disc, `small` 28, `large` 56). Precedence: `tiny` > `small` > `large`.","default":"false","group":0},{"name":"circle","type":"boolean | undefined","required":false,"description":"Shape (pick one; default is a circle).","default":"false","group":1},{"name":"rounded","type":"boolean | undefined","required":false,"description":"Shape (pick one; default is a circle).","default":"false","group":1},{"name":"ring","type":"boolean | undefined","required":false,"description":"Separator outline, for avatars that overlap in a stack.","default":"false","group":1},{"name":"online","type":"boolean | undefined","required":false,"description":"A presence dot: the `success` disc in a 2px ring of the card, at the bottom right, one pixel past the disc's edge. It is decoration (hidden from assistive tech), so name the presence in the label where it matters.","default":"false","group":1},{"name":"onPress","type":"(() => void) | undefined","required":false,"description":"When set, the avatar becomes pressable (e.g. a topbar account trigger).","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"For layout composition only; overlap/stacking is owned by AvatarGroup, not this prop.","group":1}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default is the 40px row avatar, `tiny` the 20px disc, `small` 28, `large` 56). Precedence: `tiny` > `small` > `large`."},{"title":"Shape","pickOne":true,"note":"Shape (pick one; default is a circle)."}],"inherits":[]},{"name":"AvatarGroupProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"Avatar elements to stack."},{"name":"max","type":"number | undefined","required":false,"description":"Cap the visible avatars; the remainder collapses into a \"+N\" chip."},{"name":"total","type":"number | undefined","required":false,"description":"Override the total behind the \"+N\" chip (e.g. a server-known member count)."},{"name":"tiny","type":"boolean | undefined","required":false,"description":"Size (pick one; forwarded to every child so the whole stack is uniform). Precedence: `tiny` > `small` > `large`.","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; forwarded to every child so the whole stack is uniform). Precedence: `tiny` > `small` > `large`.","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; forwarded to every child so the whole stack is uniform). Precedence: `tiny` > `small` > `large`.","default":"false","group":0},{"name":"tight","type":"boolean | undefined","required":false,"description":"Overlap tightness (pick one; default `tight`). Precedence loose > snug > tight.","default":"false","group":1},{"name":"snug","type":"boolean | undefined","required":false,"description":"Overlap tightness (pick one; default `tight`). Precedence loose > snug > tight.","default":"false","group":1},{"name":"loose","type":"boolean | undefined","required":false,"description":"Overlap tightness (pick one; default `tight`). Precedence loose > snug > tight.","default":"false","group":1},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the whole group (e.g. \"8 members\").","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; forwarded to every child so the whole stack is uniform). Precedence: `tiny` > `small` > `large`."},{"title":"Overlap tightness","pickOne":true,"note":"Overlap tightness (pick one; default `tight`). Precedence loose > snug > tight."}],"inherits":[]}],"platformNotes":{"web":"A photo when the account has one, falling back to one or two initials on an identity disc: the name resolves to one of ten hues (or `hue` picks one), and the disc is that hue's soft wash under initials in the same hue, so one person keeps one colour on every platform and stays distinct in a stack or list. The initials sit at weight 600, 38% of the disc, and their ink is held to 4.5:1 on the wash in both schemes.\n\nLike a photo, the disc is identity content: it keeps its colours under glass, where only the neutral tile of an avatar with no name or initials takes the control material. `AvatarMenu` builds the signed-in account control on the same circle: one capsule trigger carrying the avatar, the name, and the email, opening the account menu under that same identity.\n\nArgus identity sizes are available as `annotation` (16), `compact` (30), `account`\n(32), `row` (36), `person` (38), `profile` (44), `detail` (52), `hero` (58),\n`featured` (60), and `spotlight` (74), in that precedence order. These retain their\nreference initials metrics, including the existing 9px annotation glyph.\n\n`hue` selects a stage identity independently of its name. `whiteInk` preserves\nwhite reference initials; `bold` uses the 700 weight. `sheen`, `mediumSheen`, and\n`strongSheen` add the 2, 2.5 and 3px conic ring (strongest wins). `inverse` is the\ntranslucent white identity disc, `orchid` the account gradient, and `glow` its\nselected account ring. These reference discs keep the identity gradient. On the four\nstock sizes, `glow` is a 2px gap in the page colour inside the accent's soft glow, and\n`ring` stays the separator ring a stack draws between discs.","ios":"A photo when the account has one, falling back to one or two initials on an identity disc: the name resolves to one of ten hues (or `hue` picks one), and the disc is that hue's soft wash under initials in the same hue, so one person keeps one colour on every platform and stays distinct in a stack or list. The initials sit at weight 600, 38% of the disc, and their ink is held to 4.5:1 on the wash in both schemes.\n\nLike a photo, the disc is identity content: it keeps its colours under glass, where only the neutral tile of an avatar with no name or initials takes the control material. `AvatarMenu` builds the signed-in account control on the same circle: one capsule trigger carrying the avatar, the name, and the email, opening the account menu under that same identity.\n\nArgus identity sizes are available as `annotation` (16), `compact` (30), `account`\n(32), `row` (36), `person` (38), `profile` (44), `detail` (52), `hero` (58),\n`featured` (60), and `spotlight` (74), in that precedence order. These retain their\nreference initials metrics, including the existing 9px annotation glyph.\n\n`hue` selects a stage identity independently of its name. `whiteInk` preserves\nwhite reference initials; `bold` uses the 700 weight. `sheen`, `mediumSheen`, and\n`strongSheen` add the 2, 2.5 and 3px conic ring (strongest wins). `inverse` is the\ntranslucent white identity disc, `orchid` the account gradient, and `glow` its\nselected account ring. These reference discs keep the identity gradient. On the four\nstock sizes, `glow` is a 2px gap in the page colour inside the accent's soft glow, and\n`ring` stays the separator ring a stack draws between discs.","android":"A photo when the account has one, falling back to one or two initials on an identity disc: the name resolves to one of ten hues (or `hue` picks one), and the disc is that hue's soft wash under initials in the same hue, so one person keeps one colour on every platform and stays distinct in a stack or list. The initials sit at weight 600, 38% of the disc, and their ink is held to 4.5:1 on the wash in both schemes.\n\nLike a photo, the disc is identity content: it keeps its colours under glass, where only the neutral tile of an avatar with no name or initials takes the control material. `AvatarMenu` builds the signed-in account control on the same circle: one capsule trigger carrying the avatar, the name, and the email, opening the account menu under that same identity.\n\nArgus identity sizes are available as `annotation` (16), `compact` (30), `account`\n(32), `row` (36), `person` (38), `profile` (44), `detail` (52), `hero` (58),\n`featured` (60), and `spotlight` (74), in that precedence order. These retain their\nreference initials metrics, including the existing 9px annotation glyph.\n\n`hue` selects a stage identity independently of its name. `whiteInk` preserves\nwhite reference initials; `bold` uses the 700 weight. `sheen`, `mediumSheen`, and\n`strongSheen` add the 2, 2.5 and 3px conic ring (strongest wins). `inverse` is the\ntranslucent white identity disc, `orchid` the account gradient, and `glow` its\nselected account ring. These reference discs keep the identity gradient. On the four\nstock sizes, `glow` is a 2px gap in the page colour inside the accent's soft glow, and\n`ring` stays the separator ring a stack draws between discs."}},{"slug":"badge","name":"Badge","category":"atoms","description":"Two families on one Badge component, picked by boolean props. The metadata badge labels a schema, role, or tag: with no tone it is the accent's soft pill, and the tones give `default` the solid call-to-action pill, `secondary` the quiet surface pill, `outline` a hairline pill and `destructive` the soft red pill; add `mono` for token names. A status tone (`success`, `warning`, `error`, `info`, `neutral`) paints the pill in that tone's wash and ink and leads it with a dot. The status badge (`status`) has no pill: a dot in the tone's color, ringed in its wash, beside a muted label, for live state like active, pending, or failed.","source":"src/atoms/badge/badge.md","url":"https://canvas.nannier.com/ai/4.2.0/components/badge.md","humanUrl":"https://canvas.nannier.com/components/badge","exports":["Badge","BadgeGroup","BadgeGroupProps","BadgeProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"BadgeProps","props":[{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"status","type":"boolean | undefined","required":false,"description":"Family: metadata badge (default) vs. status badge (with a dot).","default":"false","group":0},{"name":"soft","type":"boolean | undefined","required":false,"description":"Soft intent fill with matching ink (every toned pill is soft; kept for the intent grammar).","default":"false","group":0},{"name":"solid","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"action","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"primary","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"inverse","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"neutralFill","type":"boolean | undefined","required":false,"description":"Neutral border-colored fill.","default":"false","group":0},{"name":"foreground","type":"boolean | undefined","required":false,"description":"Foreground ink on the quiet surface.","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"The small pill: 18 px tall, 11 px label.","default":"false","group":0},{"name":"tiny","type":"boolean | undefined","required":false,"description":"The tiny pill: 18 px tall under a 10 px label on the pill's own 18 px line, at the regular weight even when solid (a navigation row's \"New\" tag beside its count).","default":"false","group":0},{"name":"count","type":"boolean | undefined","required":false,"description":"A count at the small size with the heavier label.","default":"false","group":0},{"name":"navigationCount","type":"boolean | undefined","required":false,"description":"Solid count used in navigation.","default":"false","group":0},{"name":"notification","type":"boolean | undefined","required":false,"description":"Compact counter carried by a notification control.","default":"false","group":0},{"name":"reference","type":"boolean | undefined","required":false,"description":"A linked reference key at the key corner, in the code face.","default":"false","group":0},{"name":"token","type":"boolean | undefined","required":false,"description":"A code token chip: the 22 px pill with its 8 px inset under the small 11 px label in the code face, for a role, a state or an attribute name beside its term.","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"The large pill: 26 px tall.","default":"false","group":0},{"name":"marker","type":"boolean | undefined","required":false,"description":"An anatomy figure's numbered marker: a 22 px disc on the accent with its number in the code face, set off from the stage by a ring of the stage's fill and a shadow (Component.dc.html line 220).","default":"false","group":0},{"name":"disc","type":"boolean | undefined","required":false,"description":"A legend's numbered disc: the marker's 22 px disc with its number in the code face, in the tone axis's fill (the solid accent as `default`, the quiet surface as `secondary`) with no ring and no shadow (Component.dc.html line 222, the anatomy legend's part numbers).","default":"false","group":0},{"name":"tier","type":"boolean | undefined","required":false,"description":"A tier pill (Atom, Molecule, Organism beside a page title): 24 px tall with a 10 px inset and a 500 11 px label on its own line (Component.dc.html line 139), tracked in caps with `uppercase` and in the code face with `mono`, as the page sets it.","default":"false","group":0},{"name":"band","type":"boolean | undefined","required":false,"description":"A group band's pill (the props table's \"pick one\" beside an axis's title): 20 px tall with a 7 px inset and a 500 11 px label (Component.dc.html line 237), in the code face with `mono` as the page sets it, in the tone axis's fill (the accent's soft pill with none). It sits between `tier` and `small` in precedence.","default":"false","group":0},{"name":"tick","type":"boolean | undefined","required":false,"description":"A ruler tick's pill (the Layout page's \"this window\" readout under its marker): 20 px tall with an 8 px inset and a 500 10 px label in the code face on the pill's own 20 px line, with no border and no tone dot. Usually with `contrast`. After `band` in precedence.","default":"false","group":0},{"name":"step","type":"boolean | undefined","required":false,"description":"A numbered step mark (the Layout page's \"try in this order\" list): a 32 px square at the step mark's corner with its number 600 13 px in the code face, centred. In the tone axis's fill: `default` the solid accent with its glow, none the accent's soft wash, `secondary` the quiet surface inside the `field-border` edge in the second ink. Pass it as a MediaObject's `icon` with `bareIcon`. After `disc` in precedence.","default":"false","group":0},{"name":"keyCorners","type":"boolean | undefined","required":false,"description":"The key cap's corner in place of the round pill's, on any size: the sizing legend's mode tags and the primitive names under a Grid (Layout.dc.html). The corner axis has this one member; `reference` and `step` keep their own corners.","default":"false","group":0},{"name":"dot","type":"boolean | undefined","required":false,"description":"Show the intent dot without switching to the status family. With no children it is the bare 8 px dot in the tone's ink, with no pill (a marker beside text that names it).","default":"false","group":0},{"name":"signal","type":"boolean | undefined","required":false,"description":"Standalone 10px signal marker, retaining its status label.","default":"false","group":0},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin to the start when embedded in an unmeasured host layout.","default":"false","group":0},{"name":"uppercase","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"href","type":"string | undefined","required":false,"description":"A reference can open its source in the system browser.","group":0},{"name":"default","type":"boolean | undefined","required":false,"description":"Metadata tone (pick one; default is the accent's soft pill).","default":"false","group":1},{"name":"secondary","type":"boolean | undefined","required":false,"description":"Metadata tone (pick one; default is the accent's soft pill).","default":"false","group":1},{"name":"outline","type":"boolean | undefined","required":false,"description":"Metadata tone (pick one; default is the accent's soft pill).","default":"false","group":1},{"name":"dashed","type":"boolean | undefined","required":false,"description":"The placeholder outline: no fill inside a dashed `field-border` edge, the label in the second ink (the Layout page's primitive names). On the tone axis after `outline`.","default":"false","group":1},{"name":"contrast","type":"boolean | undefined","required":false,"description":"The contrast pill: the scheme's ink (`foreground`) as the fill under the page colour (`background`) as the label, the most prominent neutral (the Layout ruler's \"this window\" readout). On the tone axis after `default`; under glass the ink at the dense alpha, as the Tooltip bubble's, so its label keeps its contrast.","default":"false","group":1},{"name":"destructive","type":"boolean | undefined","required":false,"description":"","default":"false","group":1},{"name":"mono","type":"boolean | undefined","required":false,"description":"Metadata modifier: monospace face for tokens, scopes, event names.","default":"false","group":2},{"name":"success","type":"boolean | undefined","required":false,"description":"Status tone (pick one; on a metadata pill it paints the tone and adds the dot).","default":"false","group":3},{"name":"warning","type":"boolean | undefined","required":false,"description":"Status tone (pick one; on a metadata pill it paints the tone and adds the dot).","default":"false","group":3},{"name":"error","type":"boolean | undefined","required":false,"description":"Status tone (pick one; on a metadata pill it paints the tone and adds the dot).","default":"false","group":3},{"name":"info","type":"boolean | undefined","required":false,"description":"Status tone (pick one; on a metadata pill it paints the tone and adds the dot).","default":"false","group":3},{"name":"neutral","type":"boolean | undefined","required":false,"description":"Status tone (pick one; on a metadata pill it paints the tone and adds the dot).","default":"false","group":3},{"name":"cyan","type":"boolean | undefined","required":false,"description":"The fixed cyan series hue (the hand-off's `--cyan`, `chart-2`) as a soft pill, whatever the palette: its 16% wash under its ink, solved to 4.5:1 on the wash. No dot. On the intent axis, after the status tones.","default":"false","group":3},{"name":"mint","type":"boolean | undefined","required":false,"description":"The fixed mint series hue (the hand-off's `--mint`, `chart-3`) as a soft pill, like `cyan`.","default":"false","group":3},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the badge. Most useful for the status family: the bare-dot status form (`<Badge status error />` with no children) is otherwise color-only and silent to screen readers. When omitted on a childless status badge, the status tone word (e.g. \"error\") is announced as a fallback. Mirrors the Spinner/Progress `accessibilityLabel` contract.","group":3},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":3},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":3}],"groups":[{"title":"Family","pickOne":false,"note":"Family: metadata badge (default) vs. status badge (with a dot)."},{"title":"Metadata tone","pickOne":true,"note":"Metadata tone (pick one; default is the accent's soft pill)."},{"title":"Metadata modifier","pickOne":false,"note":"Metadata modifier: monospace face for tokens, scopes, event names."},{"title":"Status tone","pickOne":true,"note":"Status tone (pick one; on a metadata pill it paints the tone and adds the dot)."}],"inherits":[]},{"name":"BadgeGroupProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"The Badge elements to lay out in a wrapping row."},{"name":"tight","type":"boolean | undefined","required":false,"description":"Inter-badge gap (pick one; default `compact`, the hand-off's 6). Precedence: cozy > snug > compact > tight.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Inter-badge gap (pick one; default `compact`, the hand-off's 6). Precedence: cozy > snug > compact > tight.","default":"false","group":0},{"name":"snug","type":"boolean | undefined","required":false,"description":"Inter-badge gap (pick one; default `compact`, the hand-off's 6). Precedence: cozy > snug > compact > tight.","default":"false","group":0},{"name":"cozy","type":"boolean | undefined","required":false,"description":"Inter-badge gap (pick one; default `compact`, the hand-off's 6). Precedence: cozy > snug > compact > tight.","default":"false","group":0},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the whole group (e.g. \"Rachel Chen's roles\").","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Inter-badge gap","pickOne":true,"note":"Inter-badge gap (pick one; default `compact`, the hand-off's 6). Precedence: cozy > snug > compact > tight."}],"inherits":[]}],"platformNotes":{"web":"Two families on one Badge component, picked by boolean props. The metadata badge labels a schema, role, or tag: with no tone it is the accent's soft pill, and the tones give `default` the solid call-to-action pill, `secondary` the quiet surface pill, `outline` a hairline pill and `destructive` the soft red pill; add `mono` for token names. A status tone (`success`, `warning`, `error`, `info`, `neutral`) paints the pill in that tone's wash and ink and leads it with a dot. The status badge (`status`) has no pill: a dot in the tone's color, ringed in its wash, beside a muted label, for live state like active, pending, or failed.\n\nThe tone colors come from `statusColors`, the helper every toned surface in the kit reads, so a warning badge and a warning alert are the same state, and every ink is the solved text role that keeps 4.5:1 on its wash.\n\n`contrast` is the most prominent neutral: the scheme's ink (`foreground`) as the fill under the page colour as the label (under glass, the ink at the dense alpha, as the Tooltip bubble's). `dashed` is the placeholder outline: no fill inside a dashed `field-border` edge, the label in the second ink.\n\nIf more than one tone is passed, Badge resolves the highest-precedence one: `default` > `contrast` > `destructive` > `secondary` > `outline` > `dashed` for metadata (the accent's soft pill when none is passed), and `success` > `error` > `warning` > `info` > `neutral` for status (`neutral` when none is passed). The metadata tones win over a status tone's colors; the status tone's dot stays.\n\n`cyan` and `mint` paint a metadata pill in a fixed series hue, the same whatever the palette (the hand-off's `--cyan` and `--mint`, the `chart-2` and `chart-3` tokens): the hue's 16% wash under its ink, solved to 4.5:1 on the wash, with no dot. They sit after the status tones in precedence (`success` > `warning` > `error` > `info` > `cyan` > `mint`), so a section can name three tiers mint, cyan and the accent and keep them apart under every palette.\n\nLay out a series of badges with `BadgeGroup`, a wrapping row that owns the gap (`tight` 4 / `compact` 6 / `snug` 8 / `cozy` 12, default `compact`, the hand-off's 6; the largest gap passed wins: `cozy` > `snug` > `compact` > `tight`) and centers its badges, so a call site never hand-rolls a flex row around them. Give it an `accessibilityLabel` (say, \"Rachel Chen's roles\") and it is announced as a named group that keeps its badges' text; without one it is a plain row.\n\nThe pill is 22 px tall with a 12 px label; `small` is 18 px with an 11 px label and `large` 26 px. `count` is the small pill with the heavier label, `navigationCount` the small solid count, and `reference` a linked key at the 6 px key corner in the code face, underlined, with an arrow when it has an `href`. `token` is a code token chip, the 22 px pill under the small 11 px label in the code face, for a role, a state or an attribute name listed beside its term; `tier` is a tier tag, a 24 px pill with a 10 px inset under an 11 px mono label in caps on its own line, the tag that names a component's tier beside its title, in whichever tone the tier takes. `tiny` is the 18 px pill under a 10 px label on its own line, at the regular weight even when `solid` (a navigation row's \"New\" tag). The metric precedence is `notification` > `marker` > `disc` > `step` > `reference` > `navigationCount` > `count` > `tier` > `band` > `tick` > `token` > `tiny` > `small`. `primary` and `action` take the accent's wash, `soft` names the soft wash every toned pill already has, `neutralFill` fills with the border color, `foreground` overrides the label ink, `dot` adds the leading dot without a status tone, and `inverse` and `solid` supply branded surfaces. `uppercase` tracks caps; `start` pins a badge in a host layout.\n\n`notification` is a destructive count: a 20 px pill with a 600 11 px label, soft by default and solid with `solid`, set off from the page by a ring of the background; `action` adds a halo of the destructive wash. Button carries its own count when passed a `count`.\n\n`signal` is the original standalone 10px status marker. It uses the existing\nstatus-tone precedence and announces its supplied status label.\n\n`marker` is an anatomy figure's numbered disc: a 22 px pill with no inset, its number 600 11 px in the code face on the accent (the solid call-to-action fill under its ink), set off from the stage by a 3 px ring of the stage well's fill (`surface-sunken`) and a drop shadow, the way the component page's Anatomy section numbers a specimen's parts. It wins over the other metrics but `notification`.\n\n`disc` is the same 22 px numbered disc in a legend: the marker's disc and 600 11 px code-face number, in the tone axis's fill (`default` the solid accent for a part the figure draws, `secondary` the quiet surface for one it does not) with no ring and no shadow, the way the Anatomy legend numbers its rows. It sits below `marker` in precedence and above the pills.\n\n`tier` is the tier pill beside a page title (Atom, Molecule, Organism): 24 px tall with a 10 px inset and a 500 11 px label on its own line, tracked in caps with `uppercase` and in the code face with `mono`, in the tone axis's fill. It sits above `small` in precedence.\n\n`band` is a group band's pill, the \"pick one\" beside an axis's title in a props table: 20 px tall with a 7 px inset, no border, and a 500 11 px label, in the code face with `mono`, in the tone axis's fill (the accent's soft pill with none). It sits between `tier` and `small` in precedence; like `tick`, it never leads with a tone's dot.\n\n`tick` is a ruler tick's readout: 20 px tall with an 8 px inset, no border and a 500 10 px label in the code face on the pill's own 20 px line, usually `contrast` (the Layout page's \"this window\" pill under its marker).\n\n`step` is a numbered step mark: a 32 px square at the 10 px step corner with its number 600 13 px in the code face, centred, in the tone axis's fill: `default` the solid accent with the accent's glow beneath, none the accent's soft wash, `secondary` the quiet surface inside the `field-border` edge in the second ink. Pass it as a MediaObject's `icon` with `bareIcon` to number a list of steps.\n\n`keyCorners` sets any pill at the key cap's 6 px corner in place of the round one (the corner axis has this one member); `reference` and `step` keep their own corners.","ios":"Two families on one Badge component, picked by boolean props. The metadata badge labels a schema, role, or tag: with no tone it is the accent's soft pill, and the tones give `default` the solid call-to-action pill, `secondary` the quiet surface pill, `outline` a hairline pill and `destructive` the soft red pill; add `mono` for token names. A status tone (`success`, `warning`, `error`, `info`, `neutral`) paints the pill in that tone's wash and ink and leads it with a dot. The status badge (`status`) has no pill: a dot in the tone's color, ringed in its wash, beside a muted label, for live state like active, pending, or failed.\n\nThe tone colors come from `statusColors`, the helper every toned surface in the kit reads, so a warning badge and a warning alert are the same state, and every ink is the solved text role that keeps 4.5:1 on its wash.\n\n`contrast` is the most prominent neutral: the scheme's ink (`foreground`) as the fill under the page colour as the label (under glass, the ink at the dense alpha, as the Tooltip bubble's). `dashed` is the placeholder outline: no fill inside a dashed `field-border` edge, the label in the second ink.\n\nIf more than one tone is passed, Badge resolves the highest-precedence one: `default` > `contrast` > `destructive` > `secondary` > `outline` > `dashed` for metadata (the accent's soft pill when none is passed), and `success` > `error` > `warning` > `info` > `neutral` for status (`neutral` when none is passed). The metadata tones win over a status tone's colors; the status tone's dot stays.\n\n`cyan` and `mint` paint a metadata pill in a fixed series hue, the same whatever the palette (the hand-off's `--cyan` and `--mint`, the `chart-2` and `chart-3` tokens): the hue's 16% wash under its ink, solved to 4.5:1 on the wash, with no dot. They sit after the status tones in precedence (`success` > `warning` > `error` > `info` > `cyan` > `mint`), so a section can name three tiers mint, cyan and the accent and keep them apart under every palette.\n\nLay out a series of badges with `BadgeGroup`, a wrapping row that owns the gap (`tight` 4 / `compact` 6 / `snug` 8 / `cozy` 12, default `compact`, the hand-off's 6; the largest gap passed wins: `cozy` > `snug` > `compact` > `tight`) and centers its badges, so a call site never hand-rolls a flex row around them. Give it an `accessibilityLabel` (say, \"Rachel Chen's roles\") and it is announced as a named group that keeps its badges' text; without one it is a plain row.\n\nThe pill is 22 px tall with a 12 px label; `small` is 18 px with an 11 px label and `large` 26 px. `count` is the small pill with the heavier label, `navigationCount` the small solid count, and `reference` a linked key at the 6 px key corner in the code face, underlined, with an arrow when it has an `href`. `token` is a code token chip, the 22 px pill under the small 11 px label in the code face, for a role, a state or an attribute name listed beside its term; `tier` is a tier tag, a 24 px pill with a 10 px inset under an 11 px mono label in caps on its own line, the tag that names a component's tier beside its title, in whichever tone the tier takes. `tiny` is the 18 px pill under a 10 px label on its own line, at the regular weight even when `solid` (a navigation row's \"New\" tag). The metric precedence is `notification` > `marker` > `disc` > `step` > `reference` > `navigationCount` > `count` > `tier` > `band` > `tick` > `token` > `tiny` > `small`. `primary` and `action` take the accent's wash, `soft` names the soft wash every toned pill already has, `neutralFill` fills with the border color, `foreground` overrides the label ink, `dot` adds the leading dot without a status tone, and `inverse` and `solid` supply branded surfaces. `uppercase` tracks caps; `start` pins a badge in a host layout.\n\n`notification` is a destructive count: a 20 px pill with a 600 11 px label, soft by default and solid with `solid`, set off from the page by a ring of the background; `action` adds a halo of the destructive wash. Button carries its own count when passed a `count`.\n\n`signal` is the original standalone 10px status marker. It uses the existing\nstatus-tone precedence and announces its supplied status label.\n\n`marker` is an anatomy figure's numbered disc: a 22 px pill with no inset, its number 600 11 px in the code face on the accent (the solid call-to-action fill under its ink), set off from the stage by a 3 px ring of the stage well's fill (`surface-sunken`) and a drop shadow, the way the component page's Anatomy section numbers a specimen's parts. It wins over the other metrics but `notification`.\n\n`disc` is the same 22 px numbered disc in a legend: the marker's disc and 600 11 px code-face number, in the tone axis's fill (`default` the solid accent for a part the figure draws, `secondary` the quiet surface for one it does not) with no ring and no shadow, the way the Anatomy legend numbers its rows. It sits below `marker` in precedence and above the pills.\n\n`tier` is the tier pill beside a page title (Atom, Molecule, Organism): 24 px tall with a 10 px inset and a 500 11 px label on its own line, tracked in caps with `uppercase` and in the code face with `mono`, in the tone axis's fill. It sits above `small` in precedence.\n\n`band` is a group band's pill, the \"pick one\" beside an axis's title in a props table: 20 px tall with a 7 px inset, no border, and a 500 11 px label, in the code face with `mono`, in the tone axis's fill (the accent's soft pill with none). It sits between `tier` and `small` in precedence; like `tick`, it never leads with a tone's dot.\n\n`tick` is a ruler tick's readout: 20 px tall with an 8 px inset, no border and a 500 10 px label in the code face on the pill's own 20 px line, usually `contrast` (the Layout page's \"this window\" pill under its marker).\n\n`step` is a numbered step mark: a 32 px square at the 10 px step corner with its number 600 13 px in the code face, centred, in the tone axis's fill: `default` the solid accent with the accent's glow beneath, none the accent's soft wash, `secondary` the quiet surface inside the `field-border` edge in the second ink. Pass it as a MediaObject's `icon` with `bareIcon` to number a list of steps.\n\n`keyCorners` sets any pill at the key cap's 6 px corner in place of the round one (the corner axis has this one member); `reference` and `step` keep their own corners.","android":"Two families on one Badge component, picked by boolean props. The metadata badge labels a schema, role, or tag: with no tone it is the accent's soft pill, and the tones give `default` the solid call-to-action pill, `secondary` the quiet surface pill, `outline` a hairline pill and `destructive` the soft red pill; add `mono` for token names. A status tone (`success`, `warning`, `error`, `info`, `neutral`) paints the pill in that tone's wash and ink and leads it with a dot. The status badge (`status`) has no pill: a dot in the tone's color, ringed in its wash, beside a muted label, for live state like active, pending, or failed.\n\nThe tone colors come from `statusColors`, the helper every toned surface in the kit reads, so a warning badge and a warning alert are the same state, and every ink is the solved text role that keeps 4.5:1 on its wash.\n\n`contrast` is the most prominent neutral: the scheme's ink (`foreground`) as the fill under the page colour as the label (under glass, the ink at the dense alpha, as the Tooltip bubble's). `dashed` is the placeholder outline: no fill inside a dashed `field-border` edge, the label in the second ink.\n\nIf more than one tone is passed, Badge resolves the highest-precedence one: `default` > `contrast` > `destructive` > `secondary` > `outline` > `dashed` for metadata (the accent's soft pill when none is passed), and `success` > `error` > `warning` > `info` > `neutral` for status (`neutral` when none is passed). The metadata tones win over a status tone's colors; the status tone's dot stays.\n\n`cyan` and `mint` paint a metadata pill in a fixed series hue, the same whatever the palette (the hand-off's `--cyan` and `--mint`, the `chart-2` and `chart-3` tokens): the hue's 16% wash under its ink, solved to 4.5:1 on the wash, with no dot. They sit after the status tones in precedence (`success` > `warning` > `error` > `info` > `cyan` > `mint`), so a section can name three tiers mint, cyan and the accent and keep them apart under every palette.\n\nLay out a series of badges with `BadgeGroup`, a wrapping row that owns the gap (`tight` 4 / `compact` 6 / `snug` 8 / `cozy` 12, default `compact`, the hand-off's 6; the largest gap passed wins: `cozy` > `snug` > `compact` > `tight`) and centers its badges, so a call site never hand-rolls a flex row around them. Give it an `accessibilityLabel` (say, \"Rachel Chen's roles\") and it is announced as a named group that keeps its badges' text; without one it is a plain row.\n\nThe pill is 22 px tall with a 12 px label; `small` is 18 px with an 11 px label and `large` 26 px. `count` is the small pill with the heavier label, `navigationCount` the small solid count, and `reference` a linked key at the 6 px key corner in the code face, underlined, with an arrow when it has an `href`. `token` is a code token chip, the 22 px pill under the small 11 px label in the code face, for a role, a state or an attribute name listed beside its term; `tier` is a tier tag, a 24 px pill with a 10 px inset under an 11 px mono label in caps on its own line, the tag that names a component's tier beside its title, in whichever tone the tier takes. `tiny` is the 18 px pill under a 10 px label on its own line, at the regular weight even when `solid` (a navigation row's \"New\" tag). The metric precedence is `notification` > `marker` > `disc` > `step` > `reference` > `navigationCount` > `count` > `tier` > `band` > `tick` > `token` > `tiny` > `small`. `primary` and `action` take the accent's wash, `soft` names the soft wash every toned pill already has, `neutralFill` fills with the border color, `foreground` overrides the label ink, `dot` adds the leading dot without a status tone, and `inverse` and `solid` supply branded surfaces. `uppercase` tracks caps; `start` pins a badge in a host layout.\n\n`notification` is a destructive count: a 20 px pill with a 600 11 px label, soft by default and solid with `solid`, set off from the page by a ring of the background; `action` adds a halo of the destructive wash. Button carries its own count when passed a `count`.\n\n`signal` is the original standalone 10px status marker. It uses the existing\nstatus-tone precedence and announces its supplied status label.\n\n`marker` is an anatomy figure's numbered disc: a 22 px pill with no inset, its number 600 11 px in the code face on the accent (the solid call-to-action fill under its ink), set off from the stage by a 3 px ring of the stage well's fill (`surface-sunken`) and a drop shadow, the way the component page's Anatomy section numbers a specimen's parts. It wins over the other metrics but `notification`.\n\n`disc` is the same 22 px numbered disc in a legend: the marker's disc and 600 11 px code-face number, in the tone axis's fill (`default` the solid accent for a part the figure draws, `secondary` the quiet surface for one it does not) with no ring and no shadow, the way the Anatomy legend numbers its rows. It sits below `marker` in precedence and above the pills.\n\n`tier` is the tier pill beside a page title (Atom, Molecule, Organism): 24 px tall with a 10 px inset and a 500 11 px label on its own line, tracked in caps with `uppercase` and in the code face with `mono`, in the tone axis's fill. It sits above `small` in precedence.\n\n`band` is a group band's pill, the \"pick one\" beside an axis's title in a props table: 20 px tall with a 7 px inset, no border, and a 500 11 px label, in the code face with `mono`, in the tone axis's fill (the accent's soft pill with none). It sits between `tier` and `small` in precedence; like `tick`, it never leads with a tone's dot.\n\n`tick` is a ruler tick's readout: 20 px tall with an 8 px inset, no border and a 500 10 px label in the code face on the pill's own 20 px line, usually `contrast` (the Layout page's \"this window\" pill under its marker).\n\n`step` is a numbered step mark: a 32 px square at the 10 px step corner with its number 600 13 px in the code face, centred, in the tone axis's fill: `default` the solid accent with the accent's glow beneath, none the accent's soft wash, `secondary` the quiet surface inside the `field-border` edge in the second ink. Pass it as a MediaObject's `icon` with `bareIcon` to number a list of steps.\n\n`keyCorners` sets any pill at the key cap's 6 px corner in place of the round one (the corner axis has this one member); `reference` and `step` keep their own corners."}},{"slug":"bar-list","name":"BarList","category":"charts","description":"Ranked label and value rows: each row is a proportional tone wash behind a truncating label, with a right-aligned mono value and an optional delta.","source":"src/charts/bar-list/bar-list.md","url":"https://canvas.nannier.com/ai/4.2.0/components/bar-list.md","humanUrl":"https://canvas.nannier.com/components/bar-list","exports":["BarList","BarListProps","BreakdownRow"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"BarListProps","props":[{"name":"items","type":"BreakdownRow[]","required":true,"description":"The rows to render, in order."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the rows."},{"name":"share","type":"boolean | undefined","required":false,"description":"Bars proportional to the sum of all rows, with percent readouts, instead of relative to the largest row.","default":"false"},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (single-hue lists; pick one; default is the ramp by index). Precedence: success > destructive; a row's chartN slot beats the tone.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (single-hue lists; pick one; default is the ramp by index). Precedence: success > destructive; a row's chartN slot beats the tone.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default row spacing).","default":"false","group":1},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":1},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats row values (data formatting, not styling).","group":1},{"name":"onPressItem","type":"((index: number) => void) | undefined","required":false,"description":"Rows become tappable drill-in targets when set.","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (single-hue lists; pick one; default is the ramp by index). Precedence: success > destructive; a row's chartN slot beats the tone."},{"title":"Density","pickOne":false,"note":"Density (omit for the default row spacing)."}],"inherits":[]}],"platformNotes":{"web":"Ranked label and value rows: each row is a proportional tone wash behind a truncating label, with a right-aligned mono value and an optional delta.\n\nBars size against the largest row by default (the ranking idiom); `share` sizes them against the sum of the rows and appends percent readouts (the composition idiom). Rows become drill-in buttons with `onPressItem`. For comparing magnitudes on a shared axis without deltas or shares, reach for the bar `Chart` and its `horizontal` mode instead.","ios":"Ranked label and value rows: each row is a proportional tone wash behind a truncating label, with a right-aligned mono value and an optional delta.\n\nBars size against the largest row by default (the ranking idiom); `share` sizes them against the sum of the rows and appends percent readouts (the composition idiom). Rows become drill-in buttons with `onPressItem`. For comparing magnitudes on a shared axis without deltas or shares, reach for the bar `Chart` and its `horizontal` mode instead.","android":"Ranked label and value rows: each row is a proportional tone wash behind a truncating label, with a right-aligned mono value and an optional delta.\n\nBars size against the largest row by default (the ranking idiom); `share` sizes them against the sum of the rows and appends percent readouts (the composition idiom). Rows become drill-in buttons with `onPressItem`. For comparing magnitudes on a shared axis without deltas or shares, reach for the bar `Chart` and its `horizontal` mode instead."}},{"slug":"board","name":"Board","category":"organisms","description":"A data-driven kanban board: columns scroll horizontally, each column is a drop zone in a sunken well headed by its label and item count, and every card carries a drag grip, an optional trailing badge, a two-line description, a free-form chips slot, and an optional kebab menu.","source":"src/organisms/board/board.md","url":"https://canvas.nannier.com/ai/4.2.0/components/board.md","humanUrl":"https://canvas.nannier.com/components/board","exports":["Board","BoardColumn","BoardItem","BoardMove","BoardProps","applyBoardMove"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"BoardProps","props":[{"name":"plain","type":"boolean | undefined","required":false,"description":"Unframed work lanes with custom domain cards.","default":"false"},{"name":"pageScroll","type":"boolean | undefined","required":false,"description":"Let the surrounding page own horizontal overflow instead of an inner scroller.","default":"false"},{"name":"draggable","type":"boolean | undefined","required":false,"description":"Enable drag handles and drop targets in plain lanes.","default":"false"},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Temporarily prevent moves, for example while the consumer saves a drop.","default":"false"},{"name":"renderItem","type":"((item: BoardItem, controls: { dragHandle: ReactNode; }) => ReactNode) | undefined","required":false,"description":"Custom plain card; place the supplied dragHandle alongside its domain actions."},{"name":"bleed","type":"number | undefined","required":false,"description":"Extend the scroller through its parent's horizontal inset."},{"name":"columns","type":"BoardColumn[]","required":true,"description":"The columns (lanes), left to right."},{"name":"items","type":"BoardItem[] | undefined","required":false,"description":"CONTROLLED list; order within a column is array order filtered by `columnId`. The kit never mutates it: apply each `onMove` yourself (`applyBoardMove` is the standard reducer). Omit it (optionally passing `defaultItems`) for uncontrolled use."},{"name":"defaultItems","type":"BoardItem[] | undefined","required":false,"description":"Initial list for UNCONTROLLED use; Board then applies each move internally."},{"name":"onItemsChange","type":"((items: BoardItem[]) => void) | undefined","required":false,"description":"Fired with the would-be next list after a drop, in both modes."},{"name":"onMove","type":"((move: BoardMove) => void) | undefined","required":false,"description":"Fired on every completed drop with the computed move (source, target, index, neighbors)."},{"name":"onPressItem","type":"((item: BoardItem) => void) | undefined","required":false,"description":"Makes each card body pressable and reports the pressed item."},{"name":"onSelectItemMenu","type":"((item: BoardItem, menuItem: RowMenuItem, menuIndex: number) => void) | undefined","required":false,"description":"Fired when a row of a card's kebab menu (`item.menu`) is selected."},{"name":"columnWidth","type":"number | undefined","required":false,"description":"Column width in px (default 300).","default":"300"},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density axis (pass none for the default density).","default":"false","group":0},{"name":"emptyLabel","type":"string | undefined","required":false,"description":"Message shown in an empty column (default \"No items\").","default":"\"No items\"","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex), never a restyle hook.","group":0}],"groups":[{"title":"Density axis","pickOne":false,"note":"Density axis (pass none for the default density)."}],"inherits":[]}],"platformNotes":{"web":"A data-driven kanban board: columns scroll horizontally, each column is a drop zone in a sunken well headed by its label and item count, and every card carries a drag grip, an optional trailing badge, a two-line description, a free-form chips slot, and an optional kebab menu.\n\nDragging is the kit's own drag-and-drop family,\nso it runs on iOS, Android, and the web from one code path\nand stays keyboard- and screen-reader-operable: press Space on a grip to grab, the arrow keys to move between positions and columns, Space to drop, Escape to cancel. The list stays controlled: a drop reports a `BoardMove` (source, target, insertion index, and the new neighbor ids) through `onMove`, and `applyBoardMove` is the standard reducer to apply it. Pass `defaultItems` instead of `items` for uncontrolled use, where the board applies each move itself.\n\nFor an action-driven work board, `plain` drops the lane wells and keeps the lane\nheaders and dashed empty slots. `renderItem` supplies the domain card with its\nown controls. Add `draggable` to enable drag grips and drop targets while retaining\nthe plain layout. A custom `renderItem` receives `{ dragHandle }` as its second\nargument; place that supplied grip in the card's header. `disabled` prevents moves\nwhile a consumer saves a change. `bleed`\nextends horizontal scrolling through the owning container's inset.\nPlain lanes share the Board's measured width equally, with a 168px minimum per\nlane. Narrow containers scroll horizontally; long card text stays within its lane.\n\nAdd `pageScroll` when the surrounding page or content pane owns horizontal scrolling.\nThe Board then renders an overflow-visible lane row without an inner scrollport.\nPlain lanes still fill the available content width equally down to their 168px\nminimum; standard lanes keep their configured width. The surrounding scroll area\nmust allow horizontal overflow and keyboard scrolling. Card actions and drag grips\nretain their keyboard behavior. Omit `pageScroll` to keep the default local scroller.","ios":"A data-driven kanban board: columns scroll horizontally, each column is a drop zone in a sunken well headed by its label and item count, and every card carries a drag grip, an optional trailing badge, a two-line description, a free-form chips slot, and an optional kebab menu.\n\nDragging is the kit's own drag-and-drop family,\nso it runs on every platform Canvas supports from one code path\nand stays keyboard- and screen-reader-operable: press Space on a grip to grab, the arrow keys to move between positions and columns, Space to drop, Escape to cancel. The list stays controlled: a drop reports a `BoardMove` (source, target, insertion index, and the new neighbor ids) through `onMove`, and `applyBoardMove` is the standard reducer to apply it. Pass `defaultItems` instead of `items` for uncontrolled use, where the board applies each move itself.\n\nFor an action-driven work board, `plain` drops the lane wells and keeps the lane\nheaders and dashed empty slots. `renderItem` supplies the domain card with its\nown controls. Add `draggable` to enable drag grips and drop targets while retaining\nthe plain layout. A custom `renderItem` receives `{ dragHandle }` as its second\nargument; place that supplied grip in the card's header. `disabled` prevents moves\nwhile a consumer saves a change. `bleed`\nextends horizontal scrolling through the owning container's inset.\nPlain lanes share the Board's measured width equally, with a 168px minimum per\nlane. Narrow containers scroll horizontally; long card text stays within its lane.\n\nAdd `pageScroll` when the surrounding page or content pane owns horizontal scrolling.\nThe Board then renders an overflow-visible lane row without an inner scrollport.\nPlain lanes still fill the available content width equally down to their 168px\nminimum; standard lanes keep their configured width. The surrounding scroll area\nmust allow horizontal overflow and keyboard scrolling. Card actions and drag grips\nretain their keyboard behavior. Omit `pageScroll` to keep the default local scroller.","android":"A data-driven kanban board: columns scroll horizontally, each column is a drop zone in a sunken well headed by its label and item count, and every card carries a drag grip, an optional trailing badge, a two-line description, a free-form chips slot, and an optional kebab menu.\n\nDragging is the kit's own drag-and-drop family,\nso it runs on every platform Canvas supports from one code path\nand stays keyboard- and screen-reader-operable: press Space on a grip to grab, the arrow keys to move between positions and columns, Space to drop, Escape to cancel. The list stays controlled: a drop reports a `BoardMove` (source, target, insertion index, and the new neighbor ids) through `onMove`, and `applyBoardMove` is the standard reducer to apply it. Pass `defaultItems` instead of `items` for uncontrolled use, where the board applies each move itself.\n\nFor an action-driven work board, `plain` drops the lane wells and keeps the lane\nheaders and dashed empty slots. `renderItem` supplies the domain card with its\nown controls. Add `draggable` to enable drag grips and drop targets while retaining\nthe plain layout. A custom `renderItem` receives `{ dragHandle }` as its second\nargument; place that supplied grip in the card's header. `disabled` prevents moves\nwhile a consumer saves a change. `bleed`\nextends horizontal scrolling through the owning container's inset.\nPlain lanes share the Board's measured width equally, with a 168px minimum per\nlane. Narrow containers scroll horizontally; long card text stays within its lane.\n\nAdd `pageScroll` when the surrounding page or content pane owns horizontal scrolling.\nThe Board then renders an overflow-visible lane row without an inner scrollport.\nPlain lanes still fill the available content width equally down to their 168px\nminimum; standard lanes keep their configured width. The surrounding scroll area\nmust allow horizontal overflow and keyboard scrolling. Card actions and drag grips\nretain their keyboard behavior. Omit `pageScroll` to keep the default local scroller."}},{"slug":"box-plot","name":"BoxPlot","category":"charts","description":"Quartile boxes, whiskers, and outlier dots per category, computed by the chart from raw samples: quartiles by linear interpolation, whiskers at the most extreme data inside the 1.5 IQR fences, outliers beyond them. Scrub a category to flag its five-number summary; each category's summary also folds into the accessible name.","source":"src/charts/box-plot/box-plot.md","url":"https://canvas.nannier.com/ai/4.2.0/components/box-plot.md","humanUrl":"https://canvas.nannier.com/components/box-plot","exports":["BoxPlot","BoxPlotProps","BoxSample"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"BoxPlotProps","props":[{"name":"data","type":"BoxSample[]","required":true,"description":"One box per category, in order."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (pick one; default primary). Precedence: success > destructive.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (pick one; default primary). Precedence: success > destructive.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":1},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":1},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":2},{"name":"hideAxes","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":2},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats tick labels, the flag, and the accessible name.","group":2},{"name":"selected","type":"number | null | undefined","required":false,"description":"Scrub-to-inspect: the selected category index (controlled). Pass null for none.","group":2},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Scrub-to-inspect: the initially selected category (uncontrolled).","group":2},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press/scrub selects a category (or clears it with null).","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":2}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (pick one; default primary). Precedence: success > destructive."},{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."},{"title":"Furniture visibility","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"Quartile boxes, whiskers, and outlier dots per category, computed by the chart from raw samples: quartiles by linear interpolation, whiskers at the most extreme data inside the 1.5 IQR fences, outliers beyond them. Scrub a category to flag its five-number summary; each category's summary also folds into the accessible name.","ios":"Quartile boxes, whiskers, and outlier dots per category, computed by the chart from raw samples: quartiles by linear interpolation, whiskers at the most extreme data inside the 1.5 IQR fences, outliers beyond them. Scrub a category to flag its five-number summary; each category's summary also folds into the accessible name.","android":"Quartile boxes, whiskers, and outlier dots per category, computed by the chart from raw samples: quartiles by linear interpolation, whiskers at the most extreme data inside the 1.5 IQR fences, outliers beyond them. Scrub a category to flag its five-number summary; each category's summary also folds into the accessible name."}},{"slug":"breadcrumb","name":"Breadcrumb","category":"atoms","description":"Hierarchical navigation showing where you are.","source":"src/atoms/breadcrumb/breadcrumb.md","url":"https://canvas.nannier.com/ai/4.2.0/components/breadcrumb.md","humanUrl":"https://canvas.nannier.com/components/breadcrumb","exports":["Breadcrumb","BreadcrumbItem","BreadcrumbItemProps","BreadcrumbProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"BreadcrumbProps","props":[{"name":"items","type":"string[] | undefined","required":false,"description":"The trail, ancestor-first. The last entry renders as the current page (plain emphasized text); the rest render as muted links."},{"name":"chevron","type":"boolean | undefined","required":false,"description":"Separator style (pick one; default is the chevron glyph).","default":"false","group":0},{"name":"slash","type":"boolean | undefined","required":false,"description":"Separator style (pick one; default is the chevron glyph).","default":"false","group":0},{"name":"dot","type":"boolean | undefined","required":false,"description":"Separator style (pick one; default is the chevron glyph).","default":"false","group":0},{"name":"homeIcon","type":"boolean | undefined","required":false,"description":"Leading affordance: prepend a muted home-icon crumb (aria-labelled \"Home\") before the trail, followed by the separator. Off by default.","default":"false","group":0},{"name":"subtle","type":"boolean | undefined","required":false,"description":"A quieter trail for a page header: the ancestors (and the home glyph) in the subtle ink and the current page at the regular weight, so the trail recedes under the title.","default":"false","group":0},{"name":"maxItems","type":"number | undefined","required":false,"description":"Collapse a long trail: when the trail has more than `maxItems` crumbs, keep the first crumb and the last `maxItems - 1` (so `maxItems` crumbs in all), and replace the middle with a single \"…\" crumb, so a deep path stays on one scannable line. Takes effect from 2.","group":0},{"name":"onItemPress","type":"((item: string, index: number) => void) | undefined","required":false,"description":"Fired with the crumb label and its index when a link (non-last) is pressed.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Separator style","pickOne":true,"note":"Separator style (pick one; default is the chevron glyph)."}],"inherits":[]},{"name":"BreadcrumbItemProps","props":[{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"current","type":"boolean | undefined","required":false,"description":"Render as the current page: emphasized foreground text, non-interactive.","default":"false"},{"name":"subtle","type":"boolean | undefined","required":false,"description":"The quieter trail's type (see Breadcrumb's `subtle`).","default":"false"},{"name":"onPress","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"style","type":"StyleProp<TextStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"Hierarchical navigation showing where you are.","ios":"Hierarchical navigation showing where you are.","android":"Hierarchical navigation showing where you are."}},{"slug":"bullet-chart","name":"BulletChart","category":"charts","description":"Goal-attainment rows: each datum is a leading label, a track holding qualitative background bands (`ranges`, ascending bounds in fading washes), the tone-colored measure bar, an optional vertical target tick, and the trailing formatted value.","source":"src/charts/bullet-chart/bullet-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/bullet-chart.md","humanUrl":"https://canvas.nannier.com/components/bullet-chart","exports":["BulletChart","BulletChartProps","BulletDatum"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"BulletChartProps","props":[{"name":"data","type":"BulletDatum[]","required":true,"description":"The rows to render, in order, each on its own scale."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the rows."},{"name":"max","type":"number | undefined","required":false,"description":"Force one scale maximum shared by every row (only when the rows share a unit). Omit for the default per-row scale: each row's largest value, target, or range bound."},{"name":"success","type":"boolean | undefined","required":false,"description":"Measure tone (pick one; default primary). Precedence: success > destructive.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Measure tone (pick one; default primary). Precedence: success > destructive.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default row spacing).","default":"false","group":1},{"name":"detailed","type":"boolean | undefined","required":false,"description":"Expanded goal rows with inset markers and a qualitative-band key.","default":"false","group":1},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":1},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats row values (data formatting, not styling).","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Measure tone","pickOne":true,"note":"Measure tone (pick one; default primary). Precedence: success > destructive."},{"title":"Density","pickOne":false,"note":"Density (omit for the default row spacing)."}],"inherits":[]}],"platformNotes":{"web":"Goal-attainment rows: each datum is a leading label, a track holding qualitative background bands (`ranges`, ascending bounds in fading washes), the tone-colored measure bar, an optional vertical target tick, and the trailing formatted value.\n\nFollowing the classic bullet-graph anatomy each row carries its own scale, since goals rarely share units; pass `max` to force one shared scale when they do. The compact alternative to a dashboard of gauges: five goals read in five rows.\n\n`detailed` expands each track, keeps its target marker inside the band and adds the target/ranges key.","ios":"Goal-attainment rows: each datum is a leading label, a track holding qualitative background bands (`ranges`, ascending bounds in fading washes), the tone-colored measure bar, an optional vertical target tick, and the trailing formatted value.\n\nFollowing the classic bullet-graph anatomy each row carries its own scale, since goals rarely share units; pass `max` to force one shared scale when they do. The compact alternative to a dashboard of gauges: five goals read in five rows.\n\n`detailed` expands each track, keeps its target marker inside the band and adds the target/ranges key.","android":"Goal-attainment rows: each datum is a leading label, a track holding qualitative background bands (`ranges`, ascending bounds in fading washes), the tone-colored measure bar, an optional vertical target tick, and the trailing formatted value.\n\nFollowing the classic bullet-graph anatomy each row carries its own scale, since goals rarely share units; pass `max` to force one shared scale when they do. The compact alternative to a dashboard of gauges: five goals read in five rows.\n\n`detailed` expands each track, keeps its target marker inside the band and adds the target/ranges key."}},{"slug":"button","name":"Button","category":"atoms","description":"Six intents × three sizes (plus the icon square) × disabled / focus / hover states. Always semantic: the intent communicates what the button does (default = the primary action, destructive = irreversible, ghost = chrome).","source":"src/atoms/button/button.md","url":"https://canvas.nannier.com/ai/4.2.0/components/button.md","humanUrl":"https://canvas.nannier.com/components/button","exports":["AnatomyPart","AnatomyPartProps","AnatomyProvider","AnatomyProviderProps","AnatomyRect","AnatomyRects","Button","ButtonProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ButtonProps","props":[{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"iconLeft","type":"ReactNode","required":false,"description":"An icon element rendered before the label (e.g. a lucide or Canvas `Icon`). It renders directly (not wrapped in the label `Text`, which cannot host an SVG), spaced from the label by the skin's gap. Pass `iconLeft` alone with the `icon` size prop for an icon-only square button. The caller sizes the icon; a Canvas `Icon` with no tone of its own takes the button's label ink (the primary's contrast ink on a primary button, the muted ink on a quiet one, dimmed with the label while disabled), and an explicit tone keeps it."},{"name":"iconRight","type":"ReactNode","required":false,"description":"An icon element rendered after the label (e.g. a trailing chevron/arrow)."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessibility label, required for an icon-only button (no text to read)."},{"name":"onPress","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"href","type":"string | undefined","required":false,"description":"Renders the button as a REAL link on the web: react-native-web gives the root Pressable an `<a href>`, so middle-click, cmd-click, open-in-new-tab, and crawlers all see the destination, and assistive tech hears a link. Native platforms have no anchors and ignore it, so pair `href` with an `onPress` that runs the same navigation through the host's router. While `disabled` or `loading` the anchor is suppressed, exactly like `onPress`."},{"name":"hrefAttrs","type":"{ target?: \"_blank\" | \"_self\"; rel?: string; download?: boolean | string; } | undefined","required":false,"description":"Anchor attributes forwarded with `href` on the web (react-native-web's `hrefAttrs`): `target`, `rel`, `download`. Ignored without `href`, and everywhere natively."},{"name":"onHoverIn","type":"((event: MouseEvent) => void) | undefined","required":false,"description":"Called when a pointer starts hovering the button. Fires on pointer devices only (web via react-native-web, pointer-equipped iPads/desktops natively); touch never triggers it. For hover-driven disclosure such as Tooltip."},{"name":"onHoverOut","type":"((event: MouseEvent) => void) | undefined","required":false,"description":"Called when the pointer stops hovering the button (see `onHoverIn`)."},{"name":"onFocus","type":"((event: NativeSyntheticEvent<TargetedEvent>) => void) | undefined","required":false,"description":"Called when the button gains focus (keyboard tab, or click on web)."},{"name":"onBlur","type":"((event: NativeSyntheticEvent<TargetedEvent>) => void) | undefined","required":false,"description":"Called when the button loses focus."},{"name":"primary","type":"boolean | undefined","required":false,"description":"Intent (pick one; default is the primary action).","default":"false","group":0},{"name":"secondary","type":"boolean | undefined","required":false,"description":"Intent (pick one; default is the primary action).","default":"false","group":0},{"name":"inverse","type":"boolean | undefined","required":false,"description":"White outlined action over a dark or branded surface.","default":"false","group":0},{"name":"quiet","type":"boolean | undefined","required":false,"description":"Muted outlined action for a low-emphasis operation.","default":"false","group":0},{"name":"softHover","type":"boolean | undefined","required":false,"description":"The reference link hover dims to 85% while keeping its normal ink.","default":"false","group":0},{"name":"scopeTrigger","type":"boolean | undefined","required":false,"description":"A bare project-scope menu trigger: its label set in 600, a hover wash, the chevron through `iconRight`.","default":"false","group":0},{"name":"identityAction","type":"boolean | undefined","required":false,"description":"An identity action: a 28-tall hairline pill around a leading avatar and its name.","default":"false","group":0},{"name":"pageLink","type":"boolean | undefined","required":false,"description":"A page header's link: a 34-tall hairline box around a muted label (a source path, the page's section).","default":"false","group":0},{"name":"jumpLink","type":"boolean | undefined","required":false,"description":"A page's jump to one of its sections: a 28-tall hairline pill around a muted 12px label.","default":"false","group":0},{"name":"mono","type":"boolean | undefined","required":false,"description":"A `pageLink` whose label is a path or code: the 400 12px mono face.","default":"false","group":0},{"name":"referenceLink","type":"boolean | undefined","required":false,"description":"A reference-key link: an underlined monospace key in the link ink.","default":"false","group":0},{"name":"inlineIcon","type":"boolean | undefined","required":false,"description":"An unboxed 22px icon action.","default":"false","group":0},{"name":"themeChoice","type":"boolean | undefined","required":false,"description":"A theme choice pill whose `selected` state is the accent edge and a soft accent halo.","default":"false","group":0},{"name":"selected","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"filterTrigger","type":"boolean | undefined","required":false,"description":"A bare filter-menu trigger: a muted label, a hover wash, the chevron through `iconRight`.","default":"false","group":0},{"name":"inlineLink","type":"boolean | undefined","required":false,"description":"Inline text action: an underlined link label with no box, read as a link, washed on hover.","default":"false","group":0},{"name":"plainLink","type":"boolean | undefined","required":false,"description":"A plain accent text action with no box and no underline, still read as a button: a panel's Reset, a table's show-all row. On the web a 500 13 px label in the accent text ink (12 px with `small`) that brightens to the foreground ink under the pointer; natively the platform's own tint-coloured text button.","default":"false","group":0},{"name":"foreground","type":"boolean | undefined","required":false,"description":"Foreground ink on an inline text action.","default":"false","group":0},{"name":"extraBold","type":"boolean | undefined","required":false,"description":"Extra-bold inline text action label.","default":"false","group":0},{"name":"external","type":"boolean | undefined","required":false,"description":"Open href in the system browser on every platform.","default":"false","group":0},{"name":"consistent","type":"boolean | undefined","required":false,"description":"Align a row of short workflow actions on the same minimum measure.","default":"false","group":0},{"name":"comfortable","type":"boolean | undefined","required":false,"description":"A roomier hit surround for a compact featured action.","default":"false","group":0},{"name":"testOnly_hovered","type":"boolean | undefined","required":false,"description":"Visual reference harness only; pointer hover remains the production source.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"outline","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"ghost","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"link","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one).","default":"false","group":1},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one).","default":"false","group":1},{"name":"icon","type":"boolean | undefined","required":false,"description":"Size (pick one).","default":"false","group":1},{"name":"compactIcon","type":"boolean | undefined","required":false,"description":"Compact utility icon box (28px).","default":"false","group":1},{"name":"mediumIcon","type":"boolean | undefined","required":false,"description":"Medium utility icon box (32px).","default":"false","group":1},{"name":"largeIcon","type":"boolean | undefined","required":false,"description":"Large utility icon box (34px).","default":"false","group":1},{"name":"wideIcon","type":"boolean | undefined","required":false,"description":"Give a compact icon box two extra pixels of horizontal room.","default":"false","group":1},{"name":"circle","type":"boolean | undefined","required":false,"description":"Round a utility icon box into a circle.","default":"false","group":1},{"name":"rounded","type":"boolean | undefined","required":false,"description":"Fully rounded ends: the control's corner becomes the pill (an `icon` square a circle). The special bodies (the links, the triggers, the utility boxes) keep their own corners; a utility box rounds with `circle`. The pill's ends sit 2 px wider at each side (18 at the default size).","default":"false","group":1},{"name":"dashed","type":"boolean | undefined","required":false,"description":"A dashed edge in place of the solid one: an add-a-row or drop-here affordance. It shows on the intents that draw an edge (`secondary`, `outline`); the filled, ghost and link looks have no visible edge to dash.","default":"false","group":1},{"name":"unread","type":"boolean | undefined","required":false,"description":"An unread mark: the accent dot inside the box's upper trailing corner, ringed in the card colour. A quieter sibling of `count` for \"something new\" without a number; name the state in `accessibilityLabel` (the dot is decorative). `count` wins when both are passed.","default":"false","group":1},{"name":"inset","type":"boolean | undefined","required":false,"description":"Quiet inset fill for a utility icon action.","default":"false","group":1},{"name":"steadyPress","type":"boolean | undefined","required":false,"description":"Keep the resting look while pressed (no dim, no press scale).","default":"false","group":1},{"name":"count","type":"string | number | undefined","required":false,"description":"Notification count carried in the upper trailing corner.","group":1},{"name":"block","type":"boolean | undefined","required":false,"description":"Layout and state. A Button is HUG (src/style/sizing.ts): it keeps its content width inside a stretching Column and sits content-sized in a Row; `block` makes it FILL (full width in a Column, an equal share in a Row), and a measure step (`sm`, `lg`, …, from MeasureProps) makes it FILL up to that width of the scale.","default":"false","group":2},{"name":"shrink","type":"boolean | undefined","required":false,"description":"Keep the content-sized button in a tight row, allowing its label to wrap within the available width.","default":"false","group":2},{"name":"loading","type":"boolean | undefined","required":false,"description":"","default":"false","group":2},{"name":"disabled","type":"boolean | undefined","required":false,"description":"","default":"false","group":2},{"name":"raised","type":"boolean | undefined","required":false,"description":"Lifts a primary button off the page with a soft glow in its own colour: the page's main call to action. Other intents, and a disabled button, ignore it.","default":"false","group":2},{"name":"attention","type":"boolean | undefined","required":false,"description":"An outward red glow for an action requiring attention. Static under Reduce Motion; hidden while disabled or loading.","default":"false","group":2},{"name":"expanded","type":"boolean | undefined","required":false,"description":"Marks the Button as a disclosure/menu trigger and announces its open state to assistive tech (aria-expanded, which react-native-web forwards and RN maps back to the native expanded state). Pass the live open boolean; omit for a plain button. So a Button that toggles a Dropdown/Popover stays accessible.","default":"false","group":2},{"name":"haspopup","type":"true | \"menu\" | \"dialog\" | \"grid\" | \"tree\" | \"listbox\" | undefined","required":false,"description":"Announces that the button opens a popup of this kind (aria-haspopup), for a menu / dialog / listbox trigger. Pair it with `expanded` so assistive tech reads both the popup relationship and its open state. Web-only; a no-op natively.","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: `block`, the measure steps, and the parent layout container own the width.","group":2},{"name":"ref","type":"React.Ref<View>","required":false,"description":"Ref to the interactive Pressable, including link buttons. Typed as a React Native View. On web, React Native Web exposes its DOM host; focus() and blur() move browser focus. Native host behavior depends on the platform and React Native version. Calling focus() does not activate the control or call accessibility focus APIs."},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":3},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":3}],"groups":[{"title":"Intent","pickOne":true,"note":"Intent (pick one; default is the primary action)."},{"title":"Size","pickOne":true,"note":"Size (pick one)."},{"title":"Layout and state","pickOne":false,"note":"Layout and state. A Button is HUG (src/style/sizing.ts): it keeps its content width inside a stretching Column and sits content-sized in a Row; `block` makes it FILL (full width in a Column, an equal share in a Row), and a measure step (`sm`, `lg`, …, from MeasureProps) makes it FILL up to that width of the scale."},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"Six intents × three sizes (plus the icon square) × disabled / focus / hover states. Always semantic: the intent communicates what the button does (default = the primary action, destructive = irreversible, ghost = chrome).\n\nOn the web a button is 32, 40 or 48 tall (`small`, default, `large`) with the 10 px control corner, a 500-weight label at 13, 14 or 16 px, and an 8 px gap beside its icons. The call to action fills with the accent, `destructive` with the status red, both under a lit top edge; `secondary` is the quiet well with a boundary, `outline` the boundary alone, `ghost` and `link` bare (the link underlined). A filled button brightens and rises 1 px under the pointer over 150 ms and settles back when it leaves; the other looks take the well's wash at once. A press scales the button to 96% and darkens it, unless `steadyPress`. A disabled button fades to 40%; a loading one keeps its full look while its spinner runs. A disabled or loading button stays put, and Reduce Motion makes the lift instant.\nOn iOS the button is the 50 pt capsule with a semibold 17 pt label, on Android the 40 dp Material 3 stadium, both in the same colours.\n\nPass `ref` to access the interactive Pressable, including link buttons. Use `useRef<ComponentRef<typeof Button>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\n`softHover` dims a link to 85% on hover in place of the wash. Inverse actions use\na translucent white hover wash over a branded surface.\n\nUtility icon actions use `icon` with `compactIcon` (28), `mediumIcon` (32), or\n`largeIcon` (34). `wideIcon` gives the compact box two extra pixels of\nhorizontal room; `circle` rounds it fully. Pair with `ghost` for a plain surface,\n`outline` for a boundary, or `ghost inset` for a quiet fill. `steadyPress` keeps\nthe resting look while pressed, and `count` carries a notification badge over the\nupper trailing corner. The button still owns its accessible name, hover wash, and\nnative touch-target extension.\n\nUse `inlineLink link small` for an inline text action: an underlined 13-pixel\nlabel with no box, read as a link and washed on hover. The default size is 14\npixels; `large` is 16. `extraBold`, `foreground`, and `inverse` set its weight and\nink. `external` opens `href` through the system browser on every platform, while\nkeeping its browser link semantics.\n\n`plainLink` is a plain accent text action with no box and no underline, still read\nas a button: a panel's Reset, a table's show-all row. On the web it is a 500 13 px\nlabel in the accent text ink (12 px with `small`) that brightens to the foreground ink\nunder the pointer; natively it is the platform's own tint-coloured text button. Among\nthe bodies, `inlineLink` wins over `plainLink` when both are passed.\n\n`scopeTrigger ghost steadyPress` is a bare 32 px menu trigger with a 600-weight\n14px label; `filterTrigger ghost steadyPress` the same with a muted 13px label. Both\ntake the well's wash on hover. Supply the trailing chevron through `iconRight`, and\nannounce the menu with `expanded` and `haspopup`.\n\n`identityAction` is a 28 px hairline pill around a leading avatar and its name;\n`referenceLink` an underlined monospace key in the link ink; `inlineIcon` an unboxed\n22 px icon action; `themeChoice` a 32 px pill around the theme's colour disc, a\n`<Swatch tiny ring circle decorative>` passed through `iconLeft`, whose `selected` state is the\naccent edge with a soft accent halo. `pageLink` is a page header's link, a 34 px hairline box\naround a muted 13 px label (a page's section, its source); add `mono` when the label is a\npath, which sets it in the 400 12 px mono face. `jumpLink` is a page's jump to one of its sections, a 28 px\nhairline pill around a muted 500 12 px label. Both header links brighten their label to the\nfull ink and take the `secondary` wash under the pointer.","ios":"Six intents × three sizes (plus the icon square) × disabled / focus / hover states. Always semantic: the intent communicates what the button does (default = the primary action, destructive = irreversible, ghost = chrome).\n\nOn the web a button is 32, 40 or 48 tall (`small`, default, `large`) with the 10 px control corner, a 500-weight label at 13, 14 or 16 px, and an 8 px gap beside its icons. The call to action fills with the accent, `destructive` with the status red, both under a lit top edge; `secondary` is the quiet well with a boundary, `outline` the boundary alone, `ghost` and `link` bare (the link underlined). A filled button brightens and rises 1 px under the pointer over 150 ms and settles back when it leaves; the other looks take the well's wash at once. A press scales the button to 96% and darkens it, unless `steadyPress`. A disabled button fades to 40%; a loading one keeps its full look while its spinner runs. A disabled or loading button stays put, and Reduce Motion makes the lift instant.\nOn iOS the button is the 50 pt capsule with a semibold 17 pt label, in the same colours.\n\nPass `ref` to access the interactive Pressable, including link buttons. Use `useRef<ComponentRef<typeof Button>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\n`softHover` dims a link to 85% on hover in place of the wash. Inverse actions use\na translucent white hover wash over a branded surface.\n\nUtility icon actions use `icon` with `compactIcon` (28), `mediumIcon` (32), or\n`largeIcon` (34). `wideIcon` gives the compact box two extra pixels of\nhorizontal room; `circle` rounds it fully. Pair with `ghost` for a plain surface,\n`outline` for a boundary, or `ghost inset` for a quiet fill. `steadyPress` keeps\nthe resting look while pressed, and `count` carries a notification badge over the\nupper trailing corner. The button still owns its accessible name, hover wash, and\nnative touch-target extension.\n\nUse `inlineLink link small` for an inline text action: an underlined 13-pixel\nlabel with no box, read as a link and washed on hover. The default size is 14\npixels; `large` is 16. `extraBold`, `foreground`, and `inverse` set its weight and\nink. `external` opens `href` through the system browser on every platform, while\nkeeping its browser link semantics.\n\n`plainLink` is a plain accent text action with no box and no underline, still read\nas a button: a panel's Reset, a table's show-all row. On the web it is a 500 13 px\nlabel in the accent text ink (12 px with `small`) that brightens to the foreground ink\nunder the pointer; natively it is the platform's own tint-coloured text button. Among\nthe bodies, `inlineLink` wins over `plainLink` when both are passed.\n\n`scopeTrigger ghost steadyPress` is a bare 32 px menu trigger with a 600-weight\n14px label; `filterTrigger ghost steadyPress` the same with a muted 13px label. Both\ntake the well's wash on hover. Supply the trailing chevron through `iconRight`, and\nannounce the menu with `expanded` and `haspopup`.\n\n`identityAction` is a 28 px hairline pill around a leading avatar and its name;\n`referenceLink` an underlined monospace key in the link ink; `inlineIcon` an unboxed\n22 px icon action; `themeChoice` a 32 px pill around the theme's colour disc, a\n`<Swatch tiny ring circle decorative>` passed through `iconLeft`, whose `selected` state is the\naccent edge with a soft accent halo. `pageLink` is a page header's link, a 34 px hairline box\naround a muted 13 px label (a page's section, its source); add `mono` when the label is a\npath, which sets it in the 400 12 px mono face. `jumpLink` is a page's jump to one of its sections, a 28 px\nhairline pill around a muted 500 12 px label. Both header links brighten their label to the\nfull ink and take the `secondary` wash under the pointer.","android":"Six intents × three sizes (plus the icon square) × disabled / focus / hover states. Always semantic: the intent communicates what the button does (default = the primary action, destructive = irreversible, ghost = chrome).\n\nOn the web a button is 32, 40 or 48 tall (`small`, default, `large`) with the 10 px control corner, a 500-weight label at 13, 14 or 16 px, and an 8 px gap beside its icons. The call to action fills with the accent, `destructive` with the status red, both under a lit top edge; `secondary` is the quiet well with a boundary, `outline` the boundary alone, `ghost` and `link` bare (the link underlined). A filled button brightens and rises 1 px under the pointer over 150 ms and settles back when it leaves; the other looks take the well's wash at once. A press scales the button to 96% and darkens it, unless `steadyPress`. A disabled button fades to 40%; a loading one keeps its full look while its spinner runs. A disabled or loading button stays put, and Reduce Motion makes the lift instant.\nOn Android the button is the 40 dp Material 3 stadium, in the same colours.\n\nPass `ref` to access the interactive Pressable, including link buttons. Use `useRef<ComponentRef<typeof Button>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\n`softHover` dims a link to 85% on hover in place of the wash. Inverse actions use\na translucent white hover wash over a branded surface.\n\nUtility icon actions use `icon` with `compactIcon` (28), `mediumIcon` (32), or\n`largeIcon` (34). `wideIcon` gives the compact box two extra pixels of\nhorizontal room; `circle` rounds it fully. Pair with `ghost` for a plain surface,\n`outline` for a boundary, or `ghost inset` for a quiet fill. `steadyPress` keeps\nthe resting look while pressed, and `count` carries a notification badge over the\nupper trailing corner. The button still owns its accessible name, hover wash, and\nnative touch-target extension.\n\nUse `inlineLink link small` for an inline text action: an underlined 13-pixel\nlabel with no box, read as a link and washed on hover. The default size is 14\npixels; `large` is 16. `extraBold`, `foreground`, and `inverse` set its weight and\nink. `external` opens `href` through the system browser on every platform, while\nkeeping its browser link semantics.\n\n`plainLink` is a plain accent text action with no box and no underline, still read\nas a button: a panel's Reset, a table's show-all row. On the web it is a 500 13 px\nlabel in the accent text ink (12 px with `small`) that brightens to the foreground ink\nunder the pointer; natively it is the platform's own tint-coloured text button. Among\nthe bodies, `inlineLink` wins over `plainLink` when both are passed.\n\n`scopeTrigger ghost steadyPress` is a bare 32 px menu trigger with a 600-weight\n14px label; `filterTrigger ghost steadyPress` the same with a muted 13px label. Both\ntake the well's wash on hover. Supply the trailing chevron through `iconRight`, and\nannounce the menu with `expanded` and `haspopup`.\n\n`identityAction` is a 28 px hairline pill around a leading avatar and its name;\n`referenceLink` an underlined monospace key in the link ink; `inlineIcon` an unboxed\n22 px icon action; `themeChoice` a 32 px pill around the theme's colour disc, a\n`<Swatch tiny ring circle decorative>` passed through `iconLeft`, whose `selected` state is the\naccent edge with a soft accent halo. `pageLink` is a page header's link, a 34 px hairline box\naround a muted 13 px label (a page's section, its source); add `mono` when the label is a\npath, which sets it in the 400 12 px mono face. `jumpLink` is a page's jump to one of its sections, a 28 px\nhairline pill around a muted 500 12 px label. Both header links brighten their label to the\nfull ink and take the `secondary` wash under the pointer."}},{"slug":"button-group","name":"ButtonGroup","category":"atoms","description":"Segmented controls, split buttons, attached groups.","source":"src/atoms/button-group/button-group.md","url":"https://canvas.nannier.com/ai/4.2.0/components/button-group.md","humanUrl":"https://canvas.nannier.com/components/button-group","exports":["ButtonGroup","ButtonGroupItem","ButtonGroupProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ButtonGroupProps","props":[{"name":"items","type":"ButtonGroupItem[] | undefined","required":false,"description":"Segments for segmented/spaced: a label string, or `{ label, icon }` for a leading kit glyph. The stepper cycles the labels (icons ignored there)."},{"name":"active","type":"number | undefined","required":false,"description":"Selected segment index (segmented, CONTROLLED), or the stepper's initial index. Omit for uncontrolled use."},{"name":"defaultActive","type":"number | undefined","required":false,"description":"Initial selected segment index for uncontrolled use (a bare segmented control selects on press)."},{"name":"onSelect","type":"((index: number, item: string, event: GestureResponderEvent) => void) | undefined","required":false,"description":"Called with the pressed/selected index and item (and, for the stepper, the new index)."},{"name":"segmented","type":"boolean | undefined","required":false,"description":"Kind (pick one; default is segmented).","default":"false","group":0},{"name":"split","type":"boolean | undefined","required":false,"description":"Kind (pick one; default is segmented).","default":"false","group":0},{"name":"stepper","type":"boolean | undefined","required":false,"description":"Kind (pick one; default is segmented).","default":"false","group":0},{"name":"spaced","type":"boolean | undefined","required":false,"description":"Kind (pick one; default is segmented).","default":"false","group":0},{"name":"attached","type":"boolean | undefined","required":false,"description":"Buttons joined in one hairline box on the raised fill, divided by full-height rules, the selected one on the raised step (an alignment or a view picker drawn as buttons rather than a track and thumb). It selects as `segmented` does and takes `active`, `defaultActive` and `block`.","default":"false","group":0},{"name":"decrementIcon","type":"ReactNode","required":false,"description":"The stepper's decrement end, in place of its built-in glyph (a `zoomOut` Icon for a zoom control). The stepper kind only.","group":0},{"name":"incrementIcon","type":"ReactNode","required":false,"description":"The stepper's increment end, in place of its built-in glyph (a `zoomIn` Icon).","group":0},{"name":"menu","type":"string[] | undefined","required":false,"description":"Related actions shown in the split kind's chevron dropdown.","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium size).","default":"false","group":1},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium size).","default":"false","group":1},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density of the segmented row: the segments keep their size's height and take the small label on a 12 px inset (the hand-off component page's platform switch, a default-height track of 12 px labels). On the web only: a platform that ships the control keeps its one density. The split, stepper and spaced kinds ignore it.","default":"false","group":1},{"name":"rounded","type":"boolean | undefined","required":false,"description":"A capsule segmented track with equal cells and a sliding selection thumb.","default":"false","group":1},{"name":"iconsOnly","type":"boolean | undefined","required":false,"description":"Segmented/spaced only: each segment renders its `icon` alone and the item's `label` becomes the segment's ACCESSIBLE name (an icon-only view or form-factor switcher). An item without an icon keeps its visible label, with a dev-only warning. Split and stepper ignore it (dev-only warning).","default":"false","group":1},{"name":"steadyPress","type":"boolean | undefined","required":false,"description":"Keep segmented and spaced cells at their resting opacity during a press.","default":"false","group":1},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the segmented row (the `tablist`), announcing what the group switches (e.g. \"Preview form factor\"). Segmented kind only: spaced peers are independent buttons with no group role.","group":1},{"name":"block","type":"boolean | undefined","required":false,"description":"Stretch the group to the container width, the segments sharing the space equally. An orthogonal layout modifier for the segmented and spaced kinds; split and stepper ignore it (their cells are fixed-width chrome) with a dev-only warning. A measure step (`sm`, `lg`, …) does the same up to that width of the scale.","default":"false","group":1},{"name":"disabled","type":"boolean | undefined","required":false,"description":"","default":"false","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":2}],"groups":[{"title":"Kind","pickOne":true,"note":"Kind (pick one; default is segmented)."},{"title":"Size","pickOne":true,"note":"Size (pick one; default is the medium size)."},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"Segmented controls, split buttons, attached groups.\n\nOn the web the segmented control is the v4 hand-off's: the options sit in a rounded track on the raised fill, and the selected one rides a flat card thumb with a small shadow, the rest in the muted ink. It is 30, 36 or 44 px tall at the small, default and large sizes. The split button is the green call-to-action pill with its chevron half, and the stepper and the spaced peers are hairline pills the height of a Button beside them.\n\nPass `rounded` for a capsule segmented track with equal cells and one sliding selection thumb. The small capsule is 32 px tall, as in the docs appearance picker. Its spring transition follows Reduce Motion.\nOn iOS and Android the groups keep their platform shapes (the iOS segmented control, the Material 3 segmented button) in the theme's colours.\n\nAll four kinds follow the theme's surface mode.\nToggle Liquid Glass in the docs,\nor use `<ThemeProvider glass>` in an app:\nsegmented groups paint a glass\nselection puck, in the segment's own corners, on the selected segment, a split group is its call to action's\nbrand-tinted glass (the action colour under the material, as a primary Button), a\nstepper shares a glass capsule, and spaced peers get individual glass surfaces. Every\nkind keeps its solid size under glass: the material covers the track or cell's whole\nfootprint and a hairline border gives way to the material's edge, so switching the surface\nmode never moves the page. Solid mode keeps each platform's existing skin.\nThe material uses native Liquid Glass on supported iOS\nversions, the native blur or tint fallback on Android and older iOS, and\nthe hand-off's frost in the browser.\nReduce Transparency and Increase Contrast use the\nshared material's opaque fallbacks.\n\nA web segment is 8 px shorter than its track, padded 14 px a side (8 px for an icon\nalone) with a 500 label of 12 px at the small size and 13 px otherwise. `compact` is the\nhand-off component page's platform switch: the segments keep their size's height and take\nthe 12 px label on a 12 px inset, on the web alone (a platform that ships the control keeps\nits one density; the split, stepper and spaced kinds ignore it). `steadyPress` preserves the resting opacity of a\nsegment while pressed; `start` pins the group in an app-owned host arrangement.","ios":"Segmented controls, split buttons, attached groups.\n\nOn the web the segmented control is the v4 hand-off's: the options sit in a rounded track on the raised fill, and the selected one rides a flat card thumb with a small shadow, the rest in the muted ink. It is 30, 36 or 44 px tall at the small, default and large sizes. The split button is the green call-to-action pill with its chevron half, and the stepper and the spaced peers are hairline pills the height of a Button beside them.\n\nPass `rounded` for a capsule segmented track with equal cells and one sliding selection thumb. The small capsule is 32 px tall, as in the docs appearance picker. Its spring transition follows Reduce Motion.\nOn iOS the groups keep their platform shapes (the iOS segmented control) in the theme's colours.\n\nAll four kinds follow the theme's surface mode.\nToggle Liquid Glass in the docs,\nor use `<ThemeProvider glass>` in an app:\nsegmented groups paint a glass\nselection puck, in the segment's own corners, on the selected segment, a split group is its call to action's\nbrand-tinted glass (the action colour under the material, as a primary Button), a\nstepper shares a glass capsule, and spaced peers get individual glass surfaces. Every\nkind keeps its solid size under glass: the material covers the track or cell's whole\nfootprint and a hairline border gives way to the material's edge, so switching the surface\nmode never moves the page. Solid mode keeps each platform's existing skin.\nThe material uses native Liquid Glass on supported iOS versions and the native blur or tint fallback on older ones.\nReduce Transparency and Increase Contrast use the\nshared material's opaque fallbacks.\n\nA web segment is 8 px shorter than its track, padded 14 px a side (8 px for an icon\nalone) with a 500 label of 12 px at the small size and 13 px otherwise. `compact` is the\nhand-off component page's platform switch: the segments keep their size's height and take\nthe 12 px label on a 12 px inset, on the web alone (a platform that ships the control keeps\nits one density; the split, stepper and spaced kinds ignore it). `steadyPress` preserves the resting opacity of a\nsegment while pressed; `start` pins the group in an app-owned host arrangement.","android":"Segmented controls, split buttons, attached groups.\n\nOn the web the segmented control is the v4 hand-off's: the options sit in a rounded track on the raised fill, and the selected one rides a flat card thumb with a small shadow, the rest in the muted ink. It is 30, 36 or 44 px tall at the small, default and large sizes. The split button is the green call-to-action pill with its chevron half, and the stepper and the spaced peers are hairline pills the height of a Button beside them.\n\nPass `rounded` for a capsule segmented track with equal cells and one sliding selection thumb. The small capsule is 32 px tall, as in the docs appearance picker. Its spring transition follows Reduce Motion.\nOn Android the groups keep their platform shapes (the Material 3 segmented button) in the theme's colours.\n\nAll four kinds follow the theme's surface mode.\nToggle glass in the docs,\nor use `<ThemeProvider glass>` in an app:\nsegmented groups paint a glass\nselection puck, in the segment's own corners, on the selected segment, a split group is its call to action's\nbrand-tinted glass (the action colour under the material, as a primary Button), a\nstepper shares a glass capsule, and spaced peers get individual glass surfaces. Every\nkind keeps its solid size under glass: the material covers the track or cell's whole\nfootprint and a hairline border gives way to the material's edge, so switching the surface\nmode never moves the page. Solid mode keeps each platform's existing skin.\nThe material uses the native blur, or a tint fallback where the blur is unavailable.\nReduce Transparency and Increase Contrast use the\nshared material's opaque fallbacks.\n\nA web segment is 8 px shorter than its track, padded 14 px a side (8 px for an icon\nalone) with a 500 label of 12 px at the small size and 13 px otherwise. `compact` is the\nhand-off component page's platform switch: the segments keep their size's height and take\nthe 12 px label on a 12 px inset, on the web alone (a platform that ships the control keeps\nits one density; the split, stepper and spaced kinds ignore it). `steadyPress` preserves the resting opacity of a\nsegment while pressed; `start` pins the group in an app-owned host arrangement."}},{"slug":"calendar","name":"Calendar","category":"organisms","description":"Month grid, week timeline, and day timeline in one component. Events mark their days with a dot in the month grid and week strip, and timed events render as blocks on the week/day hour timelines.","source":"src/organisms/calendar/calendar.md","url":"https://canvas.nannier.com/ai/4.2.0/components/calendar.md","humanUrl":"https://canvas.nannier.com/components/calendar","exports":["Calendar","CalendarProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"CalendarProps","props":[{"name":"month","type":"string | undefined","required":false,"description":"Month + year label shown in the header, e.g. \"June 2026\".","default":"\"June 2026\""},{"name":"selected","type":"number | undefined","required":false,"description":"The day number currently selected (CONTROLLED, primary highlight). Omit for uncontrolled use."},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Initial selected day for uncontrolled use (a bare calendar highlights the day on press)."},{"name":"today","type":"number | undefined","required":false,"description":"The day number that is today (primary highlight when unselected)."},{"name":"daysInMonth","type":"number | undefined","required":false,"description":"Number of days in the month.","default":"30"},{"name":"startWeekday","type":"number | undefined","required":false,"description":"Weekday (0=Sun .. 6=Sat) the 1st falls on; sets leading blank cells.","default":"0"},{"name":"events","type":"CalendarEvent[] | undefined","required":false,"description":"Events to mark: dots on their days in the month grid and week strip, timed blocks in the week/day timelines."},{"name":"onSelect","type":"((day: number) => void) | undefined","required":false,"description":"Fired with the day number when a day cell is pressed (and when week/day chevron paging moves the selection)."},{"name":"onEventPress","type":"((event: CalendarEvent) => void) | undefined","required":false,"description":"Fired with the event when a timed block in the week/day timeline is pressed."},{"name":"onPrev","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Fired when the previous chevron is pressed in the month view, or when week/day paging would cross into the previous month."},{"name":"onNext","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Fired when the next chevron is pressed in the month view, or when week/day paging would cross into the next month."},{"name":"week","type":"boolean | undefined","required":false,"description":"Seven-day strip over an hour timeline; chevrons page by week.","default":"false","group":0},{"name":"day","type":"boolean | undefined","required":false,"description":"Single-day hour timeline; chevrons page by day.","default":"false","group":0},{"name":"dayPeek","type":"boolean | undefined","required":false,"description":"Month view: pressing a day that has events also opens that day's hour timeline in an anchored overlay (a tooltip-style day peek) beside the cell, at its trailing side (the right in a left-to-right layout), at its leading side when that lacks room, and above or below it when neither side fits; dismissed by an outside tap or Escape.","default":"false","group":0},{"name":"range","type":"boolean | undefined","required":false,"description":"Month view: two-tap range selection — the first press sets the start day, the second (later) press the end; a press before the start restarts. Days between carry a tinted band.","default":"false","group":1},{"name":"rangeStart","type":"number | undefined","required":false,"description":"The range's start day (CONTROLLED with `rangeEnd`). Omit both for uncontrolled use.","group":1},{"name":"rangeEnd","type":"number | undefined","required":false,"description":"The range's end day (CONTROLLED with `rangeStart`).","group":1},{"name":"defaultRangeStart","type":"number | undefined","required":false,"description":"Initial range start for uncontrolled use.","group":1},{"name":"defaultRangeEnd","type":"number | undefined","required":false,"description":"Initial range end for uncontrolled use.","group":1},{"name":"onRangeChange","type":"((start?: number, end?: number) => void) | undefined","required":false,"description":"Fired as the range is picked: with (start, undefined) after the first press, (start, end) after the second.","group":1},{"name":"startHour","type":"number | undefined","required":false,"description":"First hour of the week/day timeline (0-24; default 0, the full day).","group":1},{"name":"endHour","type":"number | undefined","required":false,"description":"Last hour of the week/day timeline (0-24; default 24). The scroller initially windows 8 AM–5 PM and scrolls to the rest.","group":1},{"name":"hour24","type":"boolean | undefined","required":false,"description":"Timeline labels in 24-hour format (CONTROLLED). Omit to let the built-in 12h/24h toggle manage it.","default":"false","group":2},{"name":"defaultHour24","type":"boolean | undefined","required":false,"description":"Initial hour format for uncontrolled use (default false = 12-hour AM/PM).","default":"false","group":2},{"name":"onHour24Change","type":"((hour24: boolean) => void) | undefined","required":false,"description":"Fired when the hour format changes (true = 24-hour).","group":2},{"name":"compact","type":"boolean | undefined","required":false,"description":"Tighter cells and smaller type, for dense surfaces.","default":"false","group":3},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":3},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":3}],"groups":[{"title":"View","pickOne":true,"note":"View (pick one; default is the month grid). Precedence: day, then week."},{"title":"Range selection","pickOne":false,"note":"Range selection (month view): a travel-site check-in/check-out picker."},{"title":"Hour format","pickOne":false,"note":"Hour format (12-hour by default; the timeline's built-in segmented toggle flips it)."},{"title":"Density","pickOne":true,"note":"Density (pick one; default is the comfortable cell)."}],"inherits":[]}],"platformNotes":{"web":"Month grid, week timeline, and day timeline in one component. Events mark their\ndays with a dot in the month grid and week strip, and timed events render as\nblocks on the week/day hour timelines.\n\nThe view is a semantic boolean axis: pass `week` or `day`, or neither for the\nmonth grid (`day` wins over `week` when both are set).\n\nIn glass mode the selected day is a brand-tinted control-layer puck behind its\nnumber and event dot, in the month grid and along the week strip; in `range`\nmode both endpoints carry the puck over the range band. The day peek and the\nhover card are functional-layer glass cards beside their day. Solid mode keeps the\nskin's own filled day.","ios":"Month grid, week timeline, and day timeline in one component. Events mark their\ndays with a dot in the month grid and week strip, and timed events render as\nblocks on the week/day hour timelines.\n\nThe view is a semantic boolean axis: pass `week` or `day`, or neither for the\nmonth grid (`day` wins over `week` when both are set).\n\nIn glass mode the selected day is a brand-tinted control-layer puck behind its\nnumber and event dot, in the month grid and along the week strip; in `range`\nmode both endpoints carry the puck over the range band. The day peek and the\nhover card are functional-layer glass cards beside their day. Solid mode keeps the\nskin's own filled day.","android":"Month grid, week timeline, and day timeline in one component. Events mark their\ndays with a dot in the month grid and week strip, and timed events render as\nblocks on the week/day hour timelines.\n\nThe view is a semantic boolean axis: pass `week` or `day`, or neither for the\nmonth grid (`day` wins over `week` when both are set).\n\nIn glass mode the selected day is a brand-tinted control-layer puck behind its\nnumber and event dot, in the month grid and along the week strip; in `range`\nmode both endpoints carry the puck over the range band. The day peek and the\nhover card are functional-layer glass cards beside their day. Solid mode keeps the\nskin's own filled day."}},{"slug":"candlestick-chart","name":"CandlestickChart","category":"charts","description":"The trading instrument view: OHLC candles colored by direction from the success/destructive tokens, an optional docked volume pane, and optional overlay series (moving averages) in the series tokens. Press or scrub a candle to read its Open/High/Low/Close and volume.","source":"src/charts/candlestick-chart/candlestick-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/candlestick-chart.md","humanUrl":"https://canvas.nannier.com/components/candlestick-chart","exports":["Candle","CandlestickChart","CandlestickChartProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"CandlestickChartProps","props":[{"name":"labels","type":"string[]","required":true,"description":"Period labels along the x axis, one per candle."},{"name":"candles","type":"Candle[]","required":true,"description":"One OHLC candle per label."},{"name":"volume","type":"number[] | undefined","required":false,"description":"Optional volume per candle, drawn as a docked pane under the price plot."},{"name":"overlays","type":"ChartSeries[] | undefined","required":false,"description":"Optional overlay series (e.g. moving averages), colored from `chart-2` on (the candles own the status pair and the lead accent), or by an overlay's own `success`/`destructive` tone. A `dashed` overlay draws dashed."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"max","type":"number | undefined","required":false,"description":"Y-axis overrides. Defaults to nice bounds around the lows/highs (not zero-based)."},{"name":"min","type":"number | undefined","required":false,"description":""},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":0},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":0},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Furniture visibility (the legend names the up and down candles, then the overlays).","default":"false","group":1},{"name":"legendCaption","type":"string | undefined","required":false,"description":"A note at the end of the legend's row, pushed to its right edge (what the colours mean, a data source).","group":1},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"","default":"false","group":1},{"name":"hideAxes","type":"boolean | undefined","required":false,"description":"","default":"false","group":1},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats tick labels and accessible values (data formatting, not styling).","group":1},{"name":"selected","type":"number | null | undefined","required":false,"description":"Scrub-to-inspect: the selected candle index (controlled). Pass null for none.","group":1},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Scrub-to-inspect: the initially selected candle (uncontrolled).","group":1},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press/scrub selects a candle (or clears it with null).","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."},{"title":"Furniture visibility","pickOne":false,"note":"Furniture visibility (the legend names the up and down candles, then the overlays)."}],"inherits":[]}],"platformNotes":{"web":"The trading instrument view: OHLC candles colored by direction from the success/destructive tokens, an optional docked volume pane, and optional overlay series (moving averages) in the series tokens. Press or scrub a candle to read its Open/High/Low/Close and volume.","ios":"The trading instrument view: OHLC candles colored by direction from the success/destructive tokens, an optional docked volume pane, and optional overlay series (moving averages) in the series tokens. Press or scrub a candle to read its Open/High/Low/Close and volume.","android":"The trading instrument view: OHLC candles colored by direction from the success/destructive tokens, an optional docked volume pane, and optional overlay series (moving averages) in the series tokens. Press or scrub a candle to read its Open/High/Low/Close and volume."}},{"slug":"card","name":"Card","category":"molecules","description":"A content surface, used three ways: a stat card (a single metric, a big number and a delta), a section card (a labeled surface with an optional eyebrow, header and footer), and the generic card that brings its own structure. It is the Canvas v4 panel: the card fill under a hairline at the card corner (16 px on the web, 12 natively), the small shadow at rest and the large one `raised`; `flat` drops the shadow and steps the fill up a surface, `sunken` drops the shadow and sinks the fill to the well beneath the page (`surface-sunken`, the hand-off's `--bg2` tiles, stages and panels set into a card) under the hairline, and `outlined` drops the shadow and keeps the card fill under the hairline (the hand-off's page cards; a platform whose card control draws an outline instead of a shadow draws both the same), and `heroShadow` is the medium shadow (the hand-off's `--sh-md`, its section hero's stage), between the resting card and the raised one. Precedence is `raised`, `flat`, `sunken`, `outlined`, `heroShadow`. On Android `sunken` is the Material 3 filled card: the well's fill with no outline. A pressable card lifts 2 px on hover and takes the raised shadow. `selected` draws the primary border with a ring of the accent's soft wash around it.","source":"src/molecules/card/card.md","url":"https://canvas.nannier.com/ai/4.2.0/components/card.md","humanUrl":"https://canvas.nannier.com/components/card","exports":["Card","CardContent","CardContentProps","CardDescription","CardFooter","CardHeader","CardMedia","CardMediaProps","CardProps","CardSectionProps","CardSeparator","CardTextProps","CardTitle"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"CardProps","props":[{"name":"featured","type":"boolean | undefined","required":false,"description":"Original illustrated approval banner.","default":"false"},{"name":"artwork","type":"boolean | undefined","required":false,"description":"Show only the authored artwork, filling bounds supplied by the parent.","default":"false"},{"name":"illustration","type":"boolean | undefined","required":false,"description":"Inset an illustration in authored artwork.","default":"false"},{"name":"controls","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"promo","type":"boolean | undefined","required":false,"description":"Original promotional gradient card.","default":"false"},{"name":"stacked","type":"boolean | undefined","required":false,"description":"Stack the featured illustration above its content.","default":"false"},{"name":"hue","type":"number | undefined","required":false,"description":""},{"name":"initials","type":"string | undefined","required":false,"description":""},{"name":"eyebrow","type":"string | undefined","required":false,"description":""},{"name":"badge","type":"string | undefined","required":false,"description":""},{"name":"caption","type":"string | undefined","required":false,"description":""},{"name":"metadata","type":"string | undefined","required":false,"description":""},{"name":"referenceInline","type":"boolean | undefined","required":false,"description":"A compact unframed reference summary in a row.","default":"false"},{"name":"referenceStacked","type":"boolean | undefined","required":false,"description":"A reference key/status row above its summary.","default":"false"},{"name":"referenceTile","type":"boolean | undefined","required":false,"description":"A compact inset reference panel.","default":"false"},{"name":"referenceDetail","type":"boolean | undefined","required":false,"description":"A roomy reference panel with context and source.","default":"false"},{"name":"referenceKey","type":"string | undefined","required":false,"description":""},{"name":"referenceSource","type":"string | undefined","required":false,"description":""},{"name":"href","type":"string | undefined","required":false,"description":"Open the reference through the system browser."},{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"title","type":"string | undefined","required":false,"description":"Simple content props for the children-less / data-driven case.","group":0},{"name":"icon","type":"ReactNode","required":false,"description":"A glyph rendered before the title, for a section panel that names itself with an icon. Takes effect on the data-driven path (a card given `title` rather than raw children).","group":0},{"name":"actions","type":"ReactNode","required":false,"description":"Trailing header content, typically a button. Sits opposite the title so the header reads as one row: name on the left, action on the right.","group":0},{"name":"description","type":"string | undefined","required":false,"description":"","group":0},{"name":"body","type":"string | undefined","required":false,"description":"","group":0},{"name":"footer","type":"string | undefined","required":false,"description":"","group":0},{"name":"raised","type":"boolean | undefined","required":false,"description":"Elevation (pick one; default is a soft resting shadow).","default":"false","group":1},{"name":"flat","type":"boolean | undefined","required":false,"description":"Elevation (pick one; default is a soft resting shadow).","default":"false","group":1},{"name":"sunken","type":"boolean | undefined","required":false,"description":"The sunken well: the `surface-sunken` fill under the hairline with no shadow, the hand-off's `--bg2` tiles, stages and panels set into a card. On Android it is the Material 3 filled card (the well's fill, no outline).","default":"false","group":1},{"name":"outlined","type":"boolean | undefined","required":false,"description":"The hairline on the card fill with no shadow (the hand-off component page's cards).","default":"false","group":1},{"name":"heroShadow","type":"boolean | undefined","required":false,"description":"The section hero's stage shadow: the medium step of the ladder (the hand-off's `--sh-md`, canvas-hero.js `.st`), between the resting card and the raised one.","default":"false","group":1},{"name":"sample","type":"boolean | undefined","required":false,"description":"An elevation sample: an empty card 72 px tall on the popover fill (the hand-off's `--sf2`) that shows the elevation it is given, its edge the field border at the `heroShadow` and `raised` steps (the Foundations page's depth tiles). Composes with the elevation and corner axes; it takes no children.","default":"false","group":1},{"name":"floating","type":"boolean | undefined","required":false,"description":"The card floats over the page: under glass on the web it takes the floating material (the functional layer's tint over the backdrop blur, design-language item 7), where a resting card keeps its solid skin. Native glass and solid mode are unchanged.","default":"false","group":1},{"name":"padded","type":"boolean | undefined","required":false,"description":"Padding (orthogonal booleans). A card with raw children is padded by default, and the data-driven string path (no children) pads through its self-padding sections instead, so neither prop moves the surface inset there. `flush` strips the raw-children inset (edge-to-edge content, or composing the self-padding CardHeader/CardContent); `padded` is the explicit form of the padded-by-default.","default":"false","group":2},{"name":"flush","type":"boolean | undefined","required":false,"description":"Padding (orthogonal booleans). A card with raw children is padded by default, and the data-driven string path (no children) pads through its self-padding sections instead, so neither prop moves the surface inset there. `flush` strips the raw-children inset (edge-to-edge content, or composing the self-padding CardHeader/CardContent); `padded` is the explicit form of the padded-by-default.","default":"false","group":2},{"name":"onPress","type":"(() => void) | undefined","required":false,"description":"When set, the whole card becomes pressable (a card that behaves as a control).","group":2},{"name":"interactiveContents","type":"boolean | undefined","required":false,"description":"A clickable container whose nested controls keep their own button/link roles.","default":"false","group":2},{"name":"steadyPress","type":"boolean | undefined","required":false,"description":"Keep the resting opacity while pressed; hover lift and native ripple remain.","default":"false","group":2},{"name":"selected","type":"boolean | undefined","required":false,"description":"Active/selected surface: a primary border and a soft primary tint. For selectable cards (a card-style radio or checkbox option that is chosen).","default":"false","group":2},{"name":"grow","type":"boolean | undefined","required":false,"description":"Grow to fill the main axis of a parent Row/Column (flexGrow: 1). On a card that renders sections, the BODY takes up whatever slack the growth won, so the content region fills the taller surface and a footer stays on its floor rather than floating up under the content. Implied inside a Grid cell: the grid stretches its cells to the row's height and the card fills that box, so the tiles of one row are equal-height without being asked.","default":"false","group":2},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (pick one; default is the standard inset). Scales the card's own content padding and the gap between flat children.","default":"false","group":3},{"name":"comfortable","type":"boolean | undefined","required":false,"description":"Density (pick one; default is the standard inset). Scales the card's own content padding and the gap between flat children.","default":"false","group":3},{"name":"dense","type":"boolean | undefined","required":false,"description":"Gap-free content densities, tightest first in precedence.","default":"false","group":3},{"name":"snug","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"cozy","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"relaxed","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"roomy","type":"boolean | undefined","required":false,"description":"The showcase card's density: a 24 px inset with a 20 px rhythm between flat children (the hand-off's section page card). Unlike the other named densities it keeps the gap.","default":"false","group":3},{"name":"spacious","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"insetContent","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"rail","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"summary","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"metric","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"request","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"menu","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"panel","type":"boolean | undefined","required":false,"description":"A section panel: an 18 px inset with a 12 px rhythm (the hand-off's accessibility cards and anatomy legend).","default":"false","group":3},{"name":"guide","type":"boolean | undefined","required":false,"description":"A guidance card: 18 by 20 with a 10 px rhythm (the hand-off's usage guidance and \"From the docs\" cards).","default":"false","group":3},{"name":"linkTile","type":"boolean | undefined","required":false,"description":"A link tile: 14 by 16 with a 6 px rhythm (the hand-off's related-component tiles).","default":"false","group":3},{"name":"well","type":"boolean | undefined","required":false,"description":"A well: a 16 px inset with a 12 px rhythm (the section pages' skeleton card and wizard preview).","default":"false","group":3},{"name":"pager","type":"boolean | undefined","required":false,"description":"A pager card: 16 by 18 with a 4 px rhythm (the hand-off's previous and next cards).","default":"false","group":3},{"name":"gapless","type":"boolean | undefined","required":false,"description":"Keep the reference inset without the compact density's flat-child gap.","default":"false","group":3},{"name":"borderless","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"smallCorners","type":"boolean | undefined","required":false,"description":"The tile corner.","default":"false","group":4},{"name":"calloutCorners","type":"boolean | undefined","required":false,"description":"The callout corner (14 on the web): a note under a table, a compact link tile.","default":"false","group":4},{"name":"largeCorners","type":"boolean | undefined","required":false,"description":"The section panel corner (18 on the web): a card framing a section of a page.","default":"false","group":4},{"name":"stageCorners","type":"boolean | undefined","required":false,"description":"The stage corner (20 on the web): a staging frame, a figure and its legend.","default":"false","group":4},{"name":"showcaseCorners","type":"boolean | undefined","required":false,"description":"The showcase card's corner (20 on the web): the v4 section page's card.","default":"false","group":4},{"name":"heroCorners","type":"boolean | undefined","required":false,"description":"The hero stage's corner (24 on the web): the v4 section hero's stage (`.st`).","default":"false","group":4},{"name":"inset","type":"boolean | undefined","required":false,"description":"","default":"false","group":4},{"name":"gatePanel","type":"boolean | undefined","required":false,"description":"Original inset human-gate content panel.","default":"false","group":4},{"name":"versionPanel","type":"boolean | undefined","required":false,"description":"Original compact version-history row.","default":"false","group":4},{"name":"notePanel","type":"boolean | undefined","required":false,"description":"Original inset metric-tool note.","default":"false","group":4},{"name":"dimmed","type":"boolean | undefined","required":false,"description":"","default":"false","group":4},{"name":"clip","type":"boolean | undefined","required":false,"description":"","default":"false","group":4},{"name":"tileShadow","type":"boolean | undefined","required":false,"description":"","default":"false","group":4},{"name":"rowShadow","type":"boolean | undefined","required":false,"description":"","default":"false","group":4},{"name":"emptyShadow","type":"boolean | undefined","required":false,"description":"","default":"false","group":4},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"","group":4},{"name":"testOnly_hovered","type":"boolean | undefined","required":false,"description":"Reference harness: hold the existing hover lift.","default":"false","group":4},{"name":"onLiftChange","type":"((raised: boolean) => void) | undefined","required":false,"description":"","group":4},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":4},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":4},{"name":"board","type":"boolean | undefined","required":false,"description":"A board ticket with fixed text slots and an optional full-bleed image header.","default":"false"},{"name":"ticketNumber","type":"string | undefined","required":false,"description":""},{"name":"priorityLabel","type":"string | undefined","required":false,"description":""},{"name":"statusLabel","type":"string | undefined","required":false,"description":""},{"name":"blocked","type":"boolean | undefined","required":false,"description":"Display Blocked, or Blocked by the supplied reason, as the status.","default":"false"},{"name":"blockedReason","type":"string | undefined","required":false,"description":""},{"name":"typeLabel","type":"string | undefined","required":false,"description":""},{"name":"aiActive","type":"boolean | undefined","required":false,"description":"Display functional text shimmer and cycling dots while work is active.","default":"false"},{"name":"onAIProgressPress","type":"(() => void) | undefined","required":false,"description":"Open the active AI work from its progress label, independently of the card."},{"name":"moveHandle","type":"ReactNode","required":false,"description":"Board's provided move handle, preserving its pointer/keyboard bindings."},{"name":"imageSource","type":"ImageSourcePropType | undefined","required":false,"description":"Actual supplied image; authenticated React Native sources retain their headers."},{"name":"imageLabel","type":"string | undefined","required":false,"description":""}],"groups":[{"title":"Simple content props for the children-less / data-driven case","pickOne":false},{"title":"Elevation","pickOne":true,"note":"Elevation (pick one; default is a soft resting shadow)."},{"title":"Padding","pickOne":false,"note":"Padding (orthogonal booleans). A card with raw children is padded by default, and the data-driven string path (no children) pads through its self-padding sections instead, so neither prop moves the surface inset there. `flush` strips the raw-children inset (edge-to-edge content, or composing the self-padding CardHeader/CardContent); `padded` is the explicit form of the padded-by-default."},{"title":"Density","pickOne":true,"note":"Density (pick one; default is the standard inset). Scales the card's own content padding and the gap between flat children."},{"title":"Corners","pickOne":true,"note":"Corners (pick one; default is the card corner). The smaller step wins."}],"inherits":[]},{"name":"CardSectionProps","props":[{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds."}],"groups":[],"inherits":[]},{"name":"CardTextProps","props":[{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"style","type":"StyleProp<TextStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook."}],"groups":[],"inherits":[]},{"name":"CardContentProps","props":[{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds."},{"name":"dense","type":"boolean | undefined","required":false,"description":"The tightest inset, 10 x 14: a one-line label under a specimen well.","default":"false"},{"name":"compact","type":"boolean | undefined","required":false,"description":"A 12 x 16 inset: a short caption (a title over a meta line).","default":"false"},{"name":"cozy","type":"boolean | undefined","required":false,"description":"A 14 x 16 inset: a fuller caption (a title, a note, a code line).","default":"false"}],"groups":[],"inherits":[]},{"name":"CardMediaProps","props":[{"name":"src","type":"string | number | undefined","required":false,"description":"The cover image: a URI string (or a docs sample path), or a bundled `require(...)` asset."},{"name":"height","type":"number | undefined","required":false,"description":"Height of the image band in px (the image covers it edge to edge). The well that hosts `children` grows with its content instead, from the step its booleans pick.","default":"180"},{"name":"alt","type":"string | undefined","required":false,"description":"Accessible name / alt text announced for the image."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the image, as `alt` gives; when both are set it wins, as on Image."},{"name":"children","type":"ReactNode","required":false,"description":"Live content to stage in place of an image: CardMedia becomes a sunken well (the page's `surface-sunken` fill, an ink tint under glass) that centers what it holds, a specimen above a caption. Children win over `src` when both are passed."},{"name":"compact","type":"boolean | undefined","required":false,"description":"A shorter well: 130 px at least, a 24 x 16 inset (a size or state specimen).","default":"false","group":0},{"name":"tall","type":"boolean | undefined","required":false,"description":"A taller well: 240 px at least, a 32 x 20 inset (a platform skin specimen).","default":"false","group":0},{"name":"stage","type":"boolean | undefined","required":false,"description":"A figure's stage: 320 px at least, an 80 x 40 inset (an anatomy figure under its marks).","default":"false","group":0},{"name":"playground","type":"boolean | undefined","required":false,"description":"A playground's stage: 340 px at least, a 44 x 28 inset, growing to the height and the remaining width of a panel beside it (a live specimen beside its knobs).","default":"false","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the image, or to the well.","group":0}],"groups":[{"title":"Well size","pickOne":true,"note":"Well size (pick one; children only). The default well is 160 px tall at least, with a 28 x 20 inset."}],"inherits":[]}],"platformNotes":{"web":"A content surface, used three ways: a stat card (a single metric, a big number and a delta), a section card (a labeled surface with an optional eyebrow, header and footer), and the generic card that brings its own structure. It is the Canvas v4 panel: the card fill under a hairline at the card corner (16 px on the web, 12 natively), the small shadow at rest and the large one `raised`; `flat` drops the shadow and steps the fill up a surface, `sunken` drops the shadow and sinks the fill to the well beneath the page (`surface-sunken`, the hand-off's `--bg2` tiles, stages and panels set into a card) under the hairline, and `outlined` drops the shadow and keeps the card fill under the hairline (the hand-off's page cards; a platform whose card control draws an outline instead of a shadow draws both the same), and `heroShadow` is the medium shadow (the hand-off's `--sh-md`, its section hero's stage), between the resting card and the raised one. Precedence is `raised`, `flat`, `sunken`, `outlined`, `heroShadow`.\nOn Android `sunken` is the Material 3 filled card: the well's fill with no outline.\nA pressable card lifts 2 px on hover and takes the raised shadow. `selected` draws the primary border with a ring of the accent's soft wash around it.\n\nCorners (pick one; the smaller step wins): the card corner by default, `smallCorners` for the tile corner (12), and the three steps the hand-off's component page frames with, `calloutCorners` (14: a note under a table, a compact link tile), `largeCorners` (18: a card framing a section of a page) and `stageCorners` (20: a staging frame, a figure and its legend), and the two its section pages frame with, `showcaseCorners` (20: a section page's showcase card) and `heroCorners` (24: the section hero's stage). The web skin draws each from its row; the native skins keep their own card corner on every step but the tile.\n\nA card with content is padded by default, and a padded surface also spaces its flat children (the card owns the vertical rhythm, so a stack of Typography lines needs no layout wrapper); pass `flush` to opt out of both, the inset and the spacing, for edge-to-edge content (a table, a nav bar) or when you compose the self-padding `CardHeader`/`CardContent`.\n\nThe section props (`eyebrow` / `badge` / `title` / `description` / `icon` / `actions` / `footer`) render self-padding sections, so a sectioned card needs no `padded`: a tracked mono eyebrow with a badge opposite, the 20 px title in the display face over its muted description, the body, and a footer under a hairline in the subtle ink. They compose with a string `body` OR with raw children, so a panel can carry a titled header above a table or a form; children win when both are passed. For a cover image, `CardMedia` is the full-bleed top slot: it spans the card edge to edge, its top corners follow the card's corner, and its bottom edge stays flat; compose it with `flush` and let `CardContent` pad the text below.\n\nDensity: the card's own inset is 20 px with an 8 px rhythm; pass `compact` (14 / 8) or `comfortable` (28 / 8) to tighten or relax the card's own padding and the gap between flat children (`compact` takes precedence, and a density prop pads the surface on its own). On a sectioned card (an eyebrow, a title or a footer) the surface never pads, so a density moves its inset and rhythm onto the sections instead: the first section takes the inset above, every section the inset beside, the last the inset below, and each section sits the rhythm under the one before it. `grow` fills the height a parent Row or Column hands the card (the body takes the slack, so a footer stays on its floor); inside a `Grid` cell it is implied, so the tiles of one row are equal-height without being asked.\n\nThe hand-off's component page insets are their own density steps, the same on every platform: `panel` (18 with a 12 px rhythm: a section panel, an accessibility card, a figure's legend), `guide` (18×20 with 10: a guidance card), `linkTile` (14×16 with 6: a link tile) and `pager` (16×18 with 4: a previous or next card); the section pages add `well` (16 with a 12 px rhythm: a loading-state well, a wizard's preview).\n\nGap-free content densities preserve dense application layouts: `dense` (12),\n`snug` (18), `cozy` (20), `relaxed` (22×24), `spacious` (28), `insetContent` (14),\n`rail` (12×14), `summary` (14×16), `metric` (14×18), `request` (18/22/18/20),\nand `menu` (12 vertical). `roomy` sits between `relaxed` and `spacious` and keeps a\nrhythm: a 24 px inset with 20 px between flat children, the Canvas v4 section page's\nshowcase card, the same on every platform. Precedence follows that order, then the\npage steps (`panel`, `guide`, `linkTile`, `pager`, `well`), before compact/comfortable.\n`gapless` removes flat-child spacing; `borderless`, `inset`,\n`dimmed` and `clip` control surface anatomy. `tileShadow`, `rowShadow`, and\n`emptyShadow` extend the elevation axis after raised/flat/outlined/heroShadow. Accessible names and\nhover-lift reporting are supported on interactive cards.\n\n`interactiveContents` keeps a clickable card from nesting a button role around its\nown buttons and links. `steadyPress` preserves its resting opacity while keeping\nthe hover lift and native ripple.\n\n`gatePanel`, `versionPanel` and `notePanel` preserve the original Argus inset\ncontent surfaces. Precedence is note, version, then gate; they own their secondary\nfill, exact insets and corners.","ios":"A content surface, used three ways: a stat card (a single metric, a big number and a delta), a section card (a labeled surface with an optional eyebrow, header and footer), and the generic card that brings its own structure. It is the Canvas v4 panel: the card fill under a hairline at the card corner (16 px on the web, 12 natively), the small shadow at rest and the large one `raised`; `flat` drops the shadow and steps the fill up a surface, `sunken` drops the shadow and sinks the fill to the well beneath the page (`surface-sunken`, the hand-off's `--bg2` tiles, stages and panels set into a card) under the hairline, and `outlined` drops the shadow and keeps the card fill under the hairline (the hand-off's page cards; a platform whose card control draws an outline instead of a shadow draws both the same), and `heroShadow` is the medium shadow (the hand-off's `--sh-md`, its section hero's stage), between the resting card and the raised one. Precedence is `raised`, `flat`, `sunken`, `outlined`, `heroShadow`.\nA pressable card lifts 2 px on hover and takes the raised shadow. `selected` draws the primary border with a ring of the accent's soft wash around it.\n\nCorners (pick one; the smaller step wins): the card corner by default, `smallCorners` for the tile corner (12), and the three steps the hand-off's component page frames with, `calloutCorners` (14: a note under a table, a compact link tile), `largeCorners` (18: a card framing a section of a page) and `stageCorners` (20: a staging frame, a figure and its legend), and the two its section pages frame with, `showcaseCorners` (20: a section page's showcase card) and `heroCorners` (24: the section hero's stage). The web skin draws each from its row; the native skins keep their own card corner on every step but the tile.\n\nA card with content is padded by default, and a padded surface also spaces its flat children (the card owns the vertical rhythm, so a stack of Typography lines needs no layout wrapper); pass `flush` to opt out of both, the inset and the spacing, for edge-to-edge content (a table, a nav bar) or when you compose the self-padding `CardHeader`/`CardContent`.\n\nThe section props (`eyebrow` / `badge` / `title` / `description` / `icon` / `actions` / `footer`) render self-padding sections, so a sectioned card needs no `padded`: a tracked mono eyebrow with a badge opposite, the 20 px title in the display face over its muted description, the body, and a footer under a hairline in the subtle ink. They compose with a string `body` OR with raw children, so a panel can carry a titled header above a table or a form; children win when both are passed. For a cover image, `CardMedia` is the full-bleed top slot: it spans the card edge to edge, its top corners follow the card's corner, and its bottom edge stays flat; compose it with `flush` and let `CardContent` pad the text below.\n\nDensity: the card's own inset is 20 px with an 8 px rhythm; pass `compact` (14 / 8) or `comfortable` (28 / 8) to tighten or relax the card's own padding and the gap between flat children (`compact` takes precedence, and a density prop pads the surface on its own). On a sectioned card (an eyebrow, a title or a footer) the surface never pads, so a density moves its inset and rhythm onto the sections instead: the first section takes the inset above, every section the inset beside, the last the inset below, and each section sits the rhythm under the one before it. `grow` fills the height a parent Row or Column hands the card (the body takes the slack, so a footer stays on its floor); inside a `Grid` cell it is implied, so the tiles of one row are equal-height without being asked.\n\nThe hand-off's component page insets are their own density steps, the same on every platform: `panel` (18 with a 12 px rhythm: a section panel, an accessibility card, a figure's legend), `guide` (18×20 with 10: a guidance card), `linkTile` (14×16 with 6: a link tile) and `pager` (16×18 with 4: a previous or next card); the section pages add `well` (16 with a 12 px rhythm: a loading-state well, a wizard's preview).\n\nGap-free content densities preserve dense application layouts: `dense` (12),\n`snug` (18), `cozy` (20), `relaxed` (22×24), `spacious` (28), `insetContent` (14),\n`rail` (12×14), `summary` (14×16), `metric` (14×18), `request` (18/22/18/20),\nand `menu` (12 vertical). `roomy` sits between `relaxed` and `spacious` and keeps a\nrhythm: a 24 px inset with 20 px between flat children, the Canvas v4 section page's\nshowcase card, the same on every platform. Precedence follows that order, then the\npage steps (`panel`, `guide`, `linkTile`, `pager`, `well`), before compact/comfortable.\n`gapless` removes flat-child spacing; `borderless`, `inset`,\n`dimmed` and `clip` control surface anatomy. `tileShadow`, `rowShadow`, and\n`emptyShadow` extend the elevation axis after raised/flat/outlined/heroShadow. Accessible names and\nhover-lift reporting are supported on interactive cards.\n\n`interactiveContents` keeps a clickable card from nesting a button role around its\nown buttons and links. `steadyPress` preserves its resting opacity while keeping\nthe hover lift and native ripple.\n\n`gatePanel`, `versionPanel` and `notePanel` preserve the original Argus inset\ncontent surfaces. Precedence is note, version, then gate; they own their secondary\nfill, exact insets and corners.","android":"A content surface, used three ways: a stat card (a single metric, a big number and a delta), a section card (a labeled surface with an optional eyebrow, header and footer), and the generic card that brings its own structure. It is the Canvas v4 panel: the card fill under a hairline at the card corner (16 px on the web, 12 natively), the small shadow at rest and the large one `raised`; `flat` drops the shadow and steps the fill up a surface, `sunken` drops the shadow and sinks the fill to the well beneath the page (`surface-sunken`, the hand-off's `--bg2` tiles, stages and panels set into a card) under the hairline, and `outlined` drops the shadow and keeps the card fill under the hairline (the hand-off's page cards; a platform whose card control draws an outline instead of a shadow draws both the same), and `heroShadow` is the medium shadow (the hand-off's `--sh-md`, its section hero's stage), between the resting card and the raised one. Precedence is `raised`, `flat`, `sunken`, `outlined`, `heroShadow`.\nOn Android `sunken` is the Material 3 filled card: the well's fill with no outline.\nA pressable card lifts 2 px on hover and takes the raised shadow. `selected` draws the primary border with a ring of the accent's soft wash around it.\n\nCorners (pick one; the smaller step wins): the card corner by default, `smallCorners` for the tile corner (12), and the three steps the hand-off's component page frames with, `calloutCorners` (14: a note under a table, a compact link tile), `largeCorners` (18: a card framing a section of a page) and `stageCorners` (20: a staging frame, a figure and its legend), and the two its section pages frame with, `showcaseCorners` (20: a section page's showcase card) and `heroCorners` (24: the section hero's stage). The web skin draws each from its row; the native skins keep their own card corner on every step but the tile.\n\nA card with content is padded by default, and a padded surface also spaces its flat children (the card owns the vertical rhythm, so a stack of Typography lines needs no layout wrapper); pass `flush` to opt out of both, the inset and the spacing, for edge-to-edge content (a table, a nav bar) or when you compose the self-padding `CardHeader`/`CardContent`.\n\nThe section props (`eyebrow` / `badge` / `title` / `description` / `icon` / `actions` / `footer`) render self-padding sections, so a sectioned card needs no `padded`: a tracked mono eyebrow with a badge opposite, the 20 px title in the display face over its muted description, the body, and a footer under a hairline in the subtle ink. They compose with a string `body` OR with raw children, so a panel can carry a titled header above a table or a form; children win when both are passed. For a cover image, `CardMedia` is the full-bleed top slot: it spans the card edge to edge, its top corners follow the card's corner, and its bottom edge stays flat; compose it with `flush` and let `CardContent` pad the text below.\n\nDensity: the card's own inset is 20 px with an 8 px rhythm; pass `compact` (14 / 8) or `comfortable` (28 / 8) to tighten or relax the card's own padding and the gap between flat children (`compact` takes precedence, and a density prop pads the surface on its own). On a sectioned card (an eyebrow, a title or a footer) the surface never pads, so a density moves its inset and rhythm onto the sections instead: the first section takes the inset above, every section the inset beside, the last the inset below, and each section sits the rhythm under the one before it. `grow` fills the height a parent Row or Column hands the card (the body takes the slack, so a footer stays on its floor); inside a `Grid` cell it is implied, so the tiles of one row are equal-height without being asked.\n\nThe hand-off's component page insets are their own density steps, the same on every platform: `panel` (18 with a 12 px rhythm: a section panel, an accessibility card, a figure's legend), `guide` (18×20 with 10: a guidance card), `linkTile` (14×16 with 6: a link tile) and `pager` (16×18 with 4: a previous or next card); the section pages add `well` (16 with a 12 px rhythm: a loading-state well, a wizard's preview).\n\nGap-free content densities preserve dense application layouts: `dense` (12),\n`snug` (18), `cozy` (20), `relaxed` (22×24), `spacious` (28), `insetContent` (14),\n`rail` (12×14), `summary` (14×16), `metric` (14×18), `request` (18/22/18/20),\nand `menu` (12 vertical). `roomy` sits between `relaxed` and `spacious` and keeps a\nrhythm: a 24 px inset with 20 px between flat children, the Canvas v4 section page's\nshowcase card, the same on every platform. Precedence follows that order, then the\npage steps (`panel`, `guide`, `linkTile`, `pager`, `well`), before compact/comfortable.\n`gapless` removes flat-child spacing; `borderless`, `inset`,\n`dimmed` and `clip` control surface anatomy. `tileShadow`, `rowShadow`, and\n`emptyShadow` extend the elevation axis after raised/flat/outlined/heroShadow. Accessible names and\nhover-lift reporting are supported on interactive cards.\n\n`interactiveContents` keeps a clickable card from nesting a button role around its\nown buttons and links. `steadyPress` preserves its resting opacity while keeping\nthe hover lift and native ripple.\n\n`gatePanel`, `versionPanel` and `notePanel` preserve the original Argus inset\ncontent surfaces. Precedence is note, version, then gate; they own their secondary\nfill, exact insets and corners."}},{"slug":"carousel","name":"Carousel","category":"organisms","description":"A horizontally paged slide viewer: swipe (or use the prev/next arrows and the dot indicators) to move one slide at a time.","source":"src/organisms/carousel/carousel.md","url":"https://canvas.nannier.com/ai/4.2.0/components/carousel.md","humanUrl":"https://canvas.nannier.com/components/carousel","exports":["Carousel","CarouselProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"CarouselProps","props":[{"name":"items","type":"CarouselItem[]","required":true,"description":"The slides, left to right."},{"name":"index","type":"number | undefined","required":false,"description":"Controlled current slide. Pair with `onIndexChange`. Omit for uncontrolled."},{"name":"defaultIndex","type":"number | undefined","required":false,"description":"Initial current slide for the uncontrolled case (read once; default 0).","default":"0"},{"name":"onIndexChange","type":"((index: number) => void) | undefined","required":false,"description":"Called with the next current index whenever the slide changes."},{"name":"loop","type":"boolean | undefined","required":false,"description":"Wrap from the last slide to the first (and first to last) on arrow nav.","default":"false"},{"name":"showArrows","type":"boolean | undefined","required":false,"description":"Show the prev/next chevron buttons beside the slides. Default is platform-adaptive: on for web, off for iOS + Android (swipe idioms); pass `true` to opt in.","default":"false"},{"name":"showDots","type":"boolean | undefined","required":false,"description":"Show the centered dot indicators below the slides. Default is platform-adaptive: on for web + iOS (UIPageControl), off for Android M3.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"A horizontally paged slide viewer: swipe (or use the prev/next arrows and the\ndot indicators) to move one slide at a time.\n\nPaging snaps to the viewport width, the current slide drives the dots, and the\narrows step the index (clamped, or wrapped when `loop`). Slides hold any\ncontent; pass an `items` array of `{ key, content }`.\n\nEach slide is itself the card: it paints the surface, rounds the corners and\nclips its content to them. So pass the slide's content, not a Card. A plain\nstring renders in the slide's own type, inset from its edge; any other node\nfills the slide inside its 1px edge, so a picture is masked to the slide's\nshape. A\nCard nested inside frames the slide\ntwice, and on Android the Material 3\nitem's 28dp corners cut the Card's own 12dp edge.\n\nThe prev and next arrows sit beside the slides, never over them, so nothing\nnear a slide's edge is hidden behind an arrow; the slides narrow by the two\narrow gutters instead.\n\nEvery slide is mounted from the first frame and stays mounted, so a slide's own\nstate (a field's text, a playing video) survives the carousel measuring its\nviewport, on the first layout and whenever a hidden carousel is shown again.\nUntil it has measured, the current slide fills the viewport on its own. A\ncarousel does not window its slides, so a long gallery loads every slide's\ncontent up front.\n\nOn web, Tab visits the carousel in the order it reads: the previous arrow, the\nslide viewport, the next arrow, then the slide picker (an arrow disabled at the\nend of a non-looping carousel is skipped). Tab reaches the viewport while its\nslides overflow it, and the focused viewport draws the theme's focus ring around\nthe slide. Left and Right move between\nslides, while Home and End reach the first and last. Controls inside a slide\nkeep their own keyboard behavior. The named slide-picker buttons report the\ncurrent slide and its position in the set; activating the current slide does\nnothing.\nPicker targets measure at least 24px on web, 44pt on iOS, and 48dp on\nAndroid, independently of the small painted dots.\n\nThe active dot follows the committed slide (a dot press, the arrows, the\nkeyboard, a controlled `index`, a finished swipe) in both surface modes; the\nstrip is absent with one slide,\nwith `showDots={false}`, and by default on\nAndroid.","ios":"A horizontally paged slide viewer: swipe (or use the prev/next arrows and the\ndot indicators) to move one slide at a time.\n\nPaging snaps to the viewport width, the current slide drives the dots, and the\narrows step the index (clamped, or wrapped when `loop`). Slides hold any\ncontent; pass an `items` array of `{ key, content }`.\n\nEach slide is itself the card: it paints the surface, rounds the corners and\nclips its content to them. So pass the slide's content, not a Card. A plain\nstring renders in the slide's own type, inset from its edge; any other node\nfills the slide inside its 1px edge, so a picture is masked to the slide's\nshape. A\nCard nested inside frames the slide\ntwice.\n\nThe prev and next arrows sit beside the slides, never over them, so nothing\nnear a slide's edge is hidden behind an arrow; the slides narrow by the two\narrow gutters instead.\n\nEvery slide is mounted from the first frame and stays mounted, so a slide's own\nstate (a field's text, a playing video) survives the carousel measuring its\nviewport, on the first layout and whenever a hidden carousel is shown again.\nUntil it has measured, the current slide fills the viewport on its own. A\ncarousel does not window its slides, so a long gallery loads every slide's\ncontent up front.\n\nOn web, Tab visits the carousel in the order it reads: the previous arrow, the\nslide viewport, the next arrow, then the slide picker (an arrow disabled at the\nend of a non-looping carousel is skipped). Tab reaches the viewport while its\nslides overflow it, and the focused viewport draws the theme's focus ring around\nthe slide. Left and Right move between\nslides, while Home and End reach the first and last. Controls inside a slide\nkeep their own keyboard behavior. The named slide-picker buttons report the\ncurrent slide and its position in the set; activating the current slide does\nnothing.\nPicker targets measure at least 44pt, independently of the small painted dots.\n\nThe active dot follows the committed slide (a dot press, the arrows, the\nkeyboard, a controlled `index`, a finished swipe) in both surface modes; the\nstrip is absent with one slide,\nand with `showDots={false}`.","android":"A horizontally paged slide viewer: swipe (or use the prev/next arrows and the\ndot indicators) to move one slide at a time.\n\nPaging snaps to the viewport width, the current slide drives the dots, and the\narrows step the index (clamped, or wrapped when `loop`). Slides hold any\ncontent; pass an `items` array of `{ key, content }`.\n\nEach slide is itself the card: it paints the surface, rounds the corners and\nclips its content to them. So pass the slide's content, not a Card. A plain\nstring renders in the slide's own type, inset from its edge; any other node\nfills the slide inside its 1px edge, so a picture is masked to the slide's\nshape. A\nCard nested inside frames the slide\ntwice, and on Android the Material 3\nitem's 28dp corners cut the Card's own 12dp edge.\n\nThe prev and next arrows sit beside the slides, never over them, so nothing\nnear a slide's edge is hidden behind an arrow; the slides narrow by the two\narrow gutters instead.\n\nEvery slide is mounted from the first frame and stays mounted, so a slide's own\nstate (a field's text, a playing video) survives the carousel measuring its\nviewport, on the first layout and whenever a hidden carousel is shown again.\nUntil it has measured, the current slide fills the viewport on its own. A\ncarousel does not window its slides, so a long gallery loads every slide's\ncontent up front.\n\nOn web, Tab visits the carousel in the order it reads: the previous arrow, the\nslide viewport, the next arrow, then the slide picker (an arrow disabled at the\nend of a non-looping carousel is skipped). Tab reaches the viewport while its\nslides overflow it, and the focused viewport draws the theme's focus ring around\nthe slide. Left and Right move between\nslides, while Home and End reach the first and last. Controls inside a slide\nkeep their own keyboard behavior. The named slide-picker buttons report the\ncurrent slide and its position in the set; activating the current slide does\nnothing.\nPicker targets measure at least 48dp, independently of the small painted dots.\n\nThe active dot follows the committed slide (a dot press, the arrows, the\nkeyboard, a controlled `index`, a finished swipe) in both surface modes; the\nstrip is absent with one slide,\nwith `showDots={false}`, and by default on Android."}},{"slug":"chart","name":"Chart","category":"charts","description":"A single- or multi-series bar chart: vertical columns (or horizontal rows) sized against the axis max, with per-category values and labels.","source":"src/charts/chart/chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/chart.md","humanUrl":"https://canvas.nannier.com/components/chart","exports":["Chart","ChartDatum","ChartProps","ChartSeries"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ChartProps","props":[{"name":"data","type":"ChartDatum[] | undefined","required":false,"description":"The bars to render, in order (single-series mode)."},{"name":"labels","type":"string[] | undefined","required":false,"description":"Category labels along the x axis (grouped mode, with `series`)."},{"name":"series","type":"ChartSeries[] | undefined","required":false,"description":"Multiple series rendered as grouped columns per category, colored by the chart-1..8 tokens (or a series' own `success`/`destructive` tone)."},{"name":"stacked","type":"boolean | undefined","required":false,"description":"Stack the grouped series within one column per category (composition) instead of clustering them side by side.","default":"false"},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"max","type":"number | undefined","required":false,"description":"Axis maximum. Defaults to the largest value in the data (the largest category TOTAL when `stacked`)."},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (pick one; default is the primary fill). Single-series only.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (pick one; default is the primary fill). Single-series only.","default":"false","group":0},{"name":"horizontal","type":"boolean | undefined","required":false,"description":"Orientation (default is a vertical column chart). Single-series only.","default":"false","group":1},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (default is the standard plot size).","default":"false","group":2},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":2},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Hide the series legend (grouped mode shows one by default).","default":"false","group":2},{"name":"selected","type":"number | null | undefined","required":false,"description":"Press-to-inspect: the selected category index (controlled). Pass null for none. Vertical charts only.","group":2},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Press-to-inspect: the initially selected category (uncontrolled).","group":2},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press selects a category (or clears it with null).","group":2},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats the value axis, the inspected value and the accessible values (data formatting, not styling).","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":2}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (pick one; default is the primary fill). Single-series only."},{"title":"Orientation","pickOne":false,"note":"Orientation (default is a vertical column chart). Single-series only."},{"title":"Density","pickOne":false,"note":"Density (default is the standard plot size)."}],"inherits":[]}],"platformNotes":{"web":"A single- or multi-series bar chart: vertical columns (or horizontal rows) sized against the axis max, with per-category values and labels.\n\nPass `labels` + `series` for grouped clusters colored by the `chart-1`..`chart-8` tokens, add `stacked` to accumulate those series within one column per category, or give a series its own `success` / `destructive` tone when it means success or failure; press or scrub a category to inspect it.","ios":"A single- or multi-series bar chart: vertical columns (or horizontal rows) sized against the axis max, with per-category values and labels.\n\nPass `labels` + `series` for grouped clusters colored by the `chart-1`..`chart-8` tokens, add `stacked` to accumulate those series within one column per category, or give a series its own `success` / `destructive` tone when it means success or failure; press or scrub a category to inspect it.","android":"A single- or multi-series bar chart: vertical columns (or horizontal rows) sized against the axis max, with per-category values and labels.\n\nPass `labels` + `series` for grouped clusters colored by the `chart-1`..`chart-8` tokens, add `stacked` to accumulate those series within one column per category, or give a series its own `success` / `destructive` tone when it means success or failure; press or scrub a category to inspect it."}},{"slug":"chat","name":"Chat","category":"organisms","description":"A controlled assistant conversation with independently scrolling messages, clear author and provider identities, and an anchored multiline composer. The parent supplies the bounds; Chat fills the available height without choosing a fixed height of its own.","source":"src/organisms/chat/chat.md","url":"https://canvas.nannier.com/ai/4.2.0/components/chat.md","humanUrl":"https://canvas.nannier.com/components/chat","exports":["Chat","ChatAttachmentData","ChatComposer","ChatComposerProps","ChatMessage","ChatMessageData","ChatMessageProps","ChatProps","ChatQuestionAnswerData","ChatQuestionData","ChatThread","ChatThreadProps","Markdown","MarkdownProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ChatMessageProps","props":[{"name":"onAction","type":"((messageId: string | number, actionId: string) => void) | undefined","required":false,"description":"The app owns action handling, persistence, and removing resolved actions."},{"name":"onQuestionAnswerChange","type":"((messageId: string | number, answers: ChatQuestionAnswerData[]) => void) | undefined","required":false,"description":"Update the message's controlled questionAnswers; the app owns saving the draft."},{"name":"onSubmitQuestionAnswers","type":"((messageId: string | number, answers: ChatQuestionAnswerData[]) => void) | undefined","required":false,"description":"Submit the final complete answer set; the app owns transport and setting questionsSubmitted."},{"name":"onQuestionIndexChange","type":"((messageId: string | number, index: number) => void) | undefined","required":false,"description":"Save the zero-based current question index; omit questionIndex for local navigation state."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Disable question forms while other application work is in progress.","default":"false"},{"name":"pending","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"message","type":"ChatMessageData","required":true,"description":""},{"name":"onOpenAttachment","type":"((attachment: ChatAttachmentData) => void) | undefined","required":false,"description":""},{"name":"plain","type":"boolean | undefined","required":false,"description":"Render assistant markdown punctuation literally. User messages are always plain text.","default":"false"},{"name":"terminal","type":"boolean | undefined","required":false,"description":"Flat, compact monospace terminal transcript.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":""}],"groups":[],"inherits":[]},{"name":"ChatThreadProps","props":[{"name":"onAction","type":"((messageId: string | number, actionId: string) => void) | undefined","required":false,"description":"The app owns action handling, persistence, and removing resolved actions."},{"name":"onQuestionAnswerChange","type":"((messageId: string | number, answers: ChatQuestionAnswerData[]) => void) | undefined","required":false,"description":"Update the message's controlled questionAnswers; the app owns saving the draft."},{"name":"onSubmitQuestionAnswers","type":"((messageId: string | number, answers: ChatQuestionAnswerData[]) => void) | undefined","required":false,"description":"Submit the final complete answer set; the app owns transport and setting questionsSubmitted."},{"name":"onQuestionIndexChange","type":"((messageId: string | number, index: number) => void) | undefined","required":false,"description":"Save the zero-based current question index; omit questionIndex for local navigation state."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Disable question forms while other application work is in progress.","default":"false"},{"name":"messages","type":"readonly ChatMessageData[]","required":true,"description":""},{"name":"onOpenAttachment","type":"((attachment: ChatAttachmentData) => void) | undefined","required":false,"description":""},{"name":"pending","type":"boolean | undefined","required":false,"description":"A reply is being prepared; no artificial message is added to the data.","default":"false"},{"name":"pendingLabel","type":"string | undefined","required":false,"description":"","default":"\"Assistant is thinking…\""},{"name":"pendingIcon","type":"ReactNode","required":false,"description":"Application-supplied provider mark for a reply that has not started streaming."},{"name":"label","type":"string | undefined","required":false,"description":"","default":"\"Conversation\""},{"name":"emptyState","type":"ReactNode","required":false,"description":""},{"name":"plain","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"terminal","type":"boolean | undefined","required":false,"description":"Flat, compact monospace terminal transcript.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":""},{"name":"style","type":"LayoutStyle","required":false,"description":"Parent composition only. Supply a bounded height, or a bounded flex parent."}],"groups":[],"inherits":[]},{"name":"ChatComposerProps","props":[{"name":"terminal","type":"boolean | undefined","required":false,"description":"Bare terminal prompt; hardware Enter sends and Shift+Enter inserts a newline.","default":"false"},{"name":"autoFocus","type":"boolean | undefined","required":false,"description":"Focus the message input on mount.","default":"false"},{"name":"value","type":"string","required":true,"description":""},{"name":"onChangeText","type":"(value: string) => void","required":true,"description":""},{"name":"onSend","type":"(value: string) => void","required":true,"description":"Receives the trimmed draft. The app owns clearing the draft and starting transport."},{"name":"placeholder","type":"string | undefined","required":false,"description":"","default":"\"Message the assistant…\""},{"name":"composerLabel","type":"string | undefined","required":false,"description":"","default":"\"Message\""},{"name":"sendLabel","type":"string | undefined","required":false,"description":"","default":"\"Send message\""},{"name":"sendDisabled","type":"boolean | undefined","required":false,"description":"Block only sending, keeping the draft, attachments, and message choices interactive.","default":"false"},{"name":"maxLength","type":"number | undefined","required":false,"description":"Optional application input limit; enforced by the native text field."},{"name":"pending","type":"boolean | undefined","required":false,"description":"Prevent sending while a reply is pending; the draft remains editable.","default":"false"},{"name":"disabled","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"onAttach","type":"(() => void) | undefined","required":false,"description":"Show an attachment control; the app owns its file picker and upload service."},{"name":"attachments","type":"readonly ChatAttachmentData[] | undefined","required":false,"description":""},{"name":"onRemoveAttachment","type":"((id: string) => void) | undefined","required":false,"description":""},{"name":"attaching","type":"boolean | undefined","required":false,"description":"File selection or upload is in progress; prevents attaching or sending again.","default":"false"},{"name":"footer","type":"ReactNode","required":false,"description":"Anchored actions or help below the composer, outside the scrolling thread."},{"name":"testID","type":"string | undefined","required":false,"description":""}],"groups":[],"inherits":[]},{"name":"ChatProps","props":[{"name":"onAction","type":"((messageId: string | number, actionId: string) => void) | undefined","required":false,"description":"The app owns action handling, persistence, and removing resolved actions."},{"name":"onQuestionAnswerChange","type":"((messageId: string | number, answers: ChatQuestionAnswerData[]) => void) | undefined","required":false,"description":"Update the message's controlled questionAnswers; the app owns saving the draft."},{"name":"onSubmitQuestionAnswers","type":"((messageId: string | number, answers: ChatQuestionAnswerData[]) => void) | undefined","required":false,"description":"Submit the final complete answer set; the app owns transport and setting questionsSubmitted."},{"name":"onQuestionIndexChange","type":"((messageId: string | number, index: number) => void) | undefined","required":false,"description":"Save the zero-based current question index; omit questionIndex for local navigation state."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Disable question forms while other application work is in progress.","default":"false"},{"name":"messages","type":"readonly ChatMessageData[]","required":true,"description":""},{"name":"onOpenAttachment","type":"((attachment: ChatAttachmentData) => void) | undefined","required":false,"description":""},{"name":"pending","type":"boolean | undefined","required":false,"description":"A reply is being prepared; no artificial message is added to the data.","default":"false"},{"name":"pendingLabel","type":"string | undefined","required":false,"description":""},{"name":"pendingIcon","type":"ReactNode","required":false,"description":"Application-supplied provider mark for a reply that has not started streaming."},{"name":"label","type":"string | undefined","required":false,"description":""},{"name":"emptyState","type":"ReactNode","required":false,"description":""},{"name":"plain","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"terminal","type":"boolean | undefined","required":false,"description":"Flat, compact monospace terminal transcript.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":""},{"name":"style","type":"LayoutStyle","required":false,"description":"Parent composition only. Supply a bounded height, or a bounded flex parent."},{"name":"autoFocus","type":"boolean | undefined","required":false,"description":"Focus the message input on mount.","default":"false"},{"name":"value","type":"string","required":true,"description":""},{"name":"onChangeText","type":"(value: string) => void","required":true,"description":""},{"name":"onSend","type":"(value: string) => void","required":true,"description":"Receives the trimmed draft. The app owns clearing the draft and starting transport."},{"name":"placeholder","type":"string | undefined","required":false,"description":""},{"name":"composerLabel","type":"string | undefined","required":false,"description":""},{"name":"sendLabel","type":"string | undefined","required":false,"description":""},{"name":"sendDisabled","type":"boolean | undefined","required":false,"description":"Block only sending, keeping the draft, attachments, and message choices interactive.","default":"false"},{"name":"maxLength","type":"number | undefined","required":false,"description":"Optional application input limit; enforced by the native text field."},{"name":"onAttach","type":"(() => void) | undefined","required":false,"description":"Show an attachment control; the app owns its file picker and upload service."},{"name":"attachments","type":"readonly ChatAttachmentData[] | undefined","required":false,"description":""},{"name":"onRemoveAttachment","type":"((id: string) => void) | undefined","required":false,"description":""},{"name":"attaching","type":"boolean | undefined","required":false,"description":"File selection or upload is in progress; prevents attaching or sending again.","default":"false"},{"name":"footer","type":"ReactNode","required":false,"description":"Anchored actions or help below the composer, outside the scrolling thread."}],"groups":[],"inherits":[]},{"name":"MarkdownProps","props":[{"name":"children","type":"string","required":true,"description":"Untrusted Markdown source. HTML, URLs and images remain inert text."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Denser document typography using Canvas's body reading scale.","default":"false"},{"name":"terminal","type":"boolean | undefined","required":false,"description":"Compact monospace transcript, with flat horizontally scrolling tables.","default":"false"},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":""},{"name":"testID","type":"string | undefined","required":false,"description":""}],"groups":[],"inherits":[]}],"platformNotes":{"web":"A controlled assistant conversation with independently scrolling messages, clear author and provider identities, and an anchored multiline composer. The parent supplies the bounds; Chat fills the available height without choosing a fixed height of its own.\n\nMessages remain application-owned `ChatMessageData`: keep each `id` stable while updating `content` during streaming. `pending` shows a three-dot thinking indicator until an explicitly `streaming` message arrives; pass `pendingIcon` to identify its provider. Streaming replies retain their own Responding indicator. Both animations stop when their state ends and stay still under Reduce Motion. `providerIcon` accepts an application-supplied provider logo beside the author; label the image or icon with the provider name for assistive technology. `provider` remains an optional supplementary text label such as the transport name. `error` adds a visible failure label; `notice` preserves delivery or fallback information. `footer` anchors connection, review, or other actions below the composer and outside the scrollport.\n\nThe conversation reads like a desktop assistant: one centered column at most 768 points wide, assistant replies as plain text across it, the person's own turns as a neutral bubble on the trailing side without an author line (an explicit `author` or provider still shows), and the composer as one raised, rounded box below with a round add button and a round send button.\n\nSet `activity` on a message for work the assistant did rather than said, such as a command, a tool call or a process log. It shows as one muted line, its `author` then its `notice`, and expands to its markdown `content` when pressed.\n\nPass `actions` on any message for app-owned choices beneath its content: each has a stable `id`, a literal `label`, and optional `primary`. Chat, ChatThread, and ChatMessage call `onAction(messageId, actionId)` when chosen. Choices wrap at narrow widths and use each platform’s Button. `disabled`, `pending`, any streaming message in the thread, or an absent callback prevents activation. The app owns saving the choice, setting busy state while it is accepted, duplicate prevention, and removing resolved or historical actions. Actions do not send a composer draft or submit question answers.\n\nAssistant content supports paragraphs, headings, lists, quotes, fenced code, bold, emphasis, and inline code through React Native text. HTML, images, and links stay literal text and never load or execute remote content. `plain` renders all source punctuation literally; user messages are always plain text. This is a small safe markdown subset rather than a complete CommonMark renderer.\n\n`ChatThread` follows new content while the reader is within 48 points of the bottom. Scrolling up to read older messages pauses following; returning to the bottom resumes it. Message updates, streaming text, question-height changes, and viewport resizing coalesce into a tail adjustment after layout settles. Scrolling is immediate and never animated, so it does not add motion when text streams or Reduce Motion is enabled. The overflowing thread is keyboard focusable with a visible focus frame. The native app or owning Dialog handles safe areas and keyboard avoidance.\n\n`ChatComposer` keeps Enter available for newlines. Its explicit Send control receives the trimmed draft through `onSend`; empty, disabled, pending, or uploading sends are blocked. An attached file permits an empty text draft. `sendDisabled` blocks only Send while leaving drafts, attachment controls, and message choices interactive; use it when a saved choice must be made before another freeform message. Pending replies leave the draft editable. The app owns draft clearing, transport, cancellation, persistence, and retry behavior.\n\nPass `terminal` to Chat or its standalone pieces for a flat, left-aligned monospace transcript. Messages use `❯` for the user and `●` for the assistant beside their author, preserving provider text and current delivery state. No user bubble or conversation card is added. The bare composer places `❯` and its multiline editor between two full-width hairlines, with an explicit rectangular Send action. Hardware Enter sends; Shift+Enter inserts a newline. IME composition and native soft-keyboard Enter retain their normal text-entry behavior. Sending returns focus to the editor; `autoFocus` optionally focuses it on mount. The app still owns clearing the draft, delivery, and preventing duplicate requests. Pending replies keep the draft editable and block sending.\n\n`Markdown terminal` preserves the same safe document grammar with 13px monospace text, compact spacing, and semantic headings. Tables remain aligned table rows in a horizontal scrollport instead of becoming stacked cards. Fenced code and tabs remain literal whitespace. `Textarea terminal` supplies the prompt's bare monospace metrics and implies `embedded`; existing Textarea defaults remain unchanged.\n\nSet `onAttach` to show the accessible paperclip action. The app owns file picking and uploading, passes composer `attachments`, and removes a staged file through `onRemoveAttachment(id)`. A `ChatAttachmentData` has an `id`, `name`, optional `uploading` or `error` flags, and optional `notice` text. Uploading and failed files block sending; remove a failed file or replace it after retrying. `attaching` also blocks attaching and sending while the app opens a picker or uploads. Saved message attachments use the same metadata; `onOpenAttachment(attachment)` on Chat, ChatThread, or ChatMessage delegates opening or downloading to the app. Canvas never requests, uploads, or opens file URLs itself.\n\nAn assistant message can include `questions`: each `ChatQuestionData` has a stable `id`, `title`, optional `multiple`, and `options` with an `id`, `label`, and optional `description`. Supply controlled `ChatQuestionAnswerData` entries in `questionAnswers` containing `questionId`, `optionId` for a single choice or `optionIds` for multiple choices, and optional `customText`. Set `multiple` on the question for checkboxes; a custom answer can be combined with regular choices. A single-choice question also offers Select multiple at the bottom-right of its action row: switching it on records `multiple: true` in its answer and uses `optionIds`, preserving the original question metadata. The switch retains existing selections and custom text. Switching it off returns to the first selected choice, or clears an empty draft. Every question offers Write my own answer under the reserved `__custom` option id, limited to 1000 characters.\n\nThe active form shows one question with a counter derived from the actual question count. Selecting an ordinary radio saves and advances before the last question. Custom text stays on the current question and uses Next; a blank custom answer cannot advance. Back is a neutral outline button that preserves saved selections and text. Revisited valid single choices offer Next. Checkboxes use Submit to advance; Submit appears only for multiple-choice questions and the last question. The last question always requires explicit Submit before the complete batch is sent, and every question must have a real answer. An incomplete earlier answer returns the reader to the first unresolved question instead of submitting. Submitted custom text is trimmed.\n\nChat, ChatThread, and ChatMessage expose `onQuestionAnswerChange(messageId, answers)`, `onQuestionIndexChange(messageId, index)`, and `onSubmitQuestionAnswers(messageId, answers)`. Record answer changes in message data and pass the zero-based `questionIndex` to control navigation, including saved continuation after reload. Omitting `questionIndex` uses local navigation state. The position is clamped to the actual list. The final callback receives fresh answers for the whole batch, including the current answer; set `questionsSubmitted` after accepting it. Repeated activations are guarded while navigation or submission settles. A busy state that ends without a saved receipt permits retry. The app owns persistence, transport, and duplicate prevention across requests.\n\nBoth answer callbacks and an enabled form are required for interaction. `disabled`, `pending`, and active streaming lock the current question. Use `questionsDisabled` for an inactive earlier batch: it shows every original question and option read-only, without navigation actions. `questionsSubmitted` shows saved answers with an Answers sent receipt. Multiple-choice receipts include every selected label and custom text; an answer-mode override is identified as Multiple answers selected by you. Question labels and descriptions remain literal text; RadioGroup supplies arrow navigation and accessible group names. The counter is announced as Question X of N in a polite live region; navigation moves focus there through the kit's shared browser and native accessibility focus mechanism.\n\nThe current question is framed by the existing compact, flat selected Card: a soft theme tint and primary border distinguish its counter, answers and actions from the surrounding conversation. Saved receipts and inactive question history remain unframed. The Card is visual only, so answer controls retain their own accessible roles and focus behavior.\n\n`Markdown` reuses Chat's safe grammar and renderer for standalone documents. It preserves heading levels one through six, emphasis, inline and fenced code, quotes, ordered and unordered lists, nested indentation, static checked/unchecked task lists, horizontal rules, and pipe tables.\nTables use Canvas DataTable's container-responsive stacked layout on narrow surfaces, retaining every column on iOS too.\nChecklists are read-only Canvas selection controls; reading a document never changes its source. HTML, links and image syntax remain inert text: no source is executed and no remote image is requested. `MarkdownProps` accepts the source as children, an optional accessibility label and test ID; `compact` uses dense document typography. The parent supplies width.","ios":"A controlled assistant conversation with independently scrolling messages, clear author and provider identities, and an anchored multiline composer. The parent supplies the bounds; Chat fills the available height without choosing a fixed height of its own.\n\nMessages remain application-owned `ChatMessageData`: keep each `id` stable while updating `content` during streaming. `pending` shows a three-dot thinking indicator until an explicitly `streaming` message arrives; pass `pendingIcon` to identify its provider. Streaming replies retain their own Responding indicator. Both animations stop when their state ends and stay still under Reduce Motion. `providerIcon` accepts an application-supplied provider logo beside the author; label the image or icon with the provider name for assistive technology. `provider` remains an optional supplementary text label such as the transport name. `error` adds a visible failure label; `notice` preserves delivery or fallback information. `footer` anchors connection, review, or other actions below the composer and outside the scrollport.\n\nThe conversation reads like a desktop assistant: one centered column at most 768 points wide, assistant replies as plain text across it, the person's own turns as a neutral bubble on the trailing side without an author line (an explicit `author` or provider still shows), and the composer as one raised, rounded box below with a round add button and a round send button.\n\nSet `activity` on a message for work the assistant did rather than said, such as a command, a tool call or a process log. It shows as one muted line, its `author` then its `notice`, and expands to its markdown `content` when pressed.\n\nPass `actions` on any message for app-owned choices beneath its content: each has a stable `id`, a literal `label`, and optional `primary`. Chat, ChatThread, and ChatMessage call `onAction(messageId, actionId)` when chosen. Choices wrap at narrow widths and use each platform’s Button. `disabled`, `pending`, any streaming message in the thread, or an absent callback prevents activation. The app owns saving the choice, setting busy state while it is accepted, duplicate prevention, and removing resolved or historical actions. Actions do not send a composer draft or submit question answers.\n\nAssistant content supports paragraphs, headings, lists, quotes, fenced code, bold, emphasis, and inline code through React Native text. HTML, images, and links stay literal text and never load or execute remote content. `plain` renders all source punctuation literally; user messages are always plain text. This is a small safe markdown subset rather than a complete CommonMark renderer.\n\n`ChatThread` follows new content while the reader is within 48 points of the bottom. Scrolling up to read older messages pauses following; returning to the bottom resumes it. Message updates, streaming text, question-height changes, and viewport resizing coalesce into a tail adjustment after layout settles. Scrolling is immediate and never animated, so it does not add motion when text streams or Reduce Motion is enabled. The overflowing thread is keyboard focusable with a visible focus frame. The native app or owning Dialog handles safe areas and keyboard avoidance.\n\n`ChatComposer` keeps Enter available for newlines. Its explicit Send control receives the trimmed draft through `onSend`; empty, disabled, pending, or uploading sends are blocked. An attached file permits an empty text draft. `sendDisabled` blocks only Send while leaving drafts, attachment controls, and message choices interactive; use it when a saved choice must be made before another freeform message. Pending replies leave the draft editable. The app owns draft clearing, transport, cancellation, persistence, and retry behavior.\n\nPass `terminal` to Chat or its standalone pieces for a flat, left-aligned monospace transcript. Messages use `❯` for the user and `●` for the assistant beside their author, preserving provider text and current delivery state. No user bubble or conversation card is added. The bare composer places `❯` and its multiline editor between two full-width hairlines, with an explicit rectangular Send action. Hardware Enter sends; Shift+Enter inserts a newline. IME composition and native soft-keyboard Enter retain their normal text-entry behavior. Sending returns focus to the editor; `autoFocus` optionally focuses it on mount. The app still owns clearing the draft, delivery, and preventing duplicate requests. Pending replies keep the draft editable and block sending.\n\n`Markdown terminal` preserves the same safe document grammar with 13px monospace text, compact spacing, and semantic headings. Tables remain aligned table rows in a horizontal scrollport instead of becoming stacked cards. Fenced code and tabs remain literal whitespace. `Textarea terminal` supplies the prompt's bare monospace metrics and implies `embedded`; existing Textarea defaults remain unchanged.\n\nSet `onAttach` to show the accessible paperclip action. The app owns file picking and uploading, passes composer `attachments`, and removes a staged file through `onRemoveAttachment(id)`. A `ChatAttachmentData` has an `id`, `name`, optional `uploading` or `error` flags, and optional `notice` text. Uploading and failed files block sending; remove a failed file or replace it after retrying. `attaching` also blocks attaching and sending while the app opens a picker or uploads. Saved message attachments use the same metadata; `onOpenAttachment(attachment)` on Chat, ChatThread, or ChatMessage delegates opening or downloading to the app. Canvas never requests, uploads, or opens file URLs itself.\n\nAn assistant message can include `questions`: each `ChatQuestionData` has a stable `id`, `title`, optional `multiple`, and `options` with an `id`, `label`, and optional `description`. Supply controlled `ChatQuestionAnswerData` entries in `questionAnswers` containing `questionId`, `optionId` for a single choice or `optionIds` for multiple choices, and optional `customText`. Set `multiple` on the question for checkboxes; a custom answer can be combined with regular choices. A single-choice question also offers Select multiple at the bottom-right of its action row: switching it on records `multiple: true` in its answer and uses `optionIds`, preserving the original question metadata. The switch retains existing selections and custom text. Switching it off returns to the first selected choice, or clears an empty draft. Every question offers Write my own answer under the reserved `__custom` option id, limited to 1000 characters.\n\nThe active form shows one question with a counter derived from the actual question count. Selecting an ordinary radio saves and advances before the last question. Custom text stays on the current question and uses Next; a blank custom answer cannot advance. Back is a neutral outline button that preserves saved selections and text. Revisited valid single choices offer Next. Checkboxes use Submit to advance; Submit appears only for multiple-choice questions and the last question. The last question always requires explicit Submit before the complete batch is sent, and every question must have a real answer. An incomplete earlier answer returns the reader to the first unresolved question instead of submitting. Submitted custom text is trimmed.\n\nChat, ChatThread, and ChatMessage expose `onQuestionAnswerChange(messageId, answers)`, `onQuestionIndexChange(messageId, index)`, and `onSubmitQuestionAnswers(messageId, answers)`. Record answer changes in message data and pass the zero-based `questionIndex` to control navigation, including saved continuation after reload. Omitting `questionIndex` uses local navigation state. The position is clamped to the actual list. The final callback receives fresh answers for the whole batch, including the current answer; set `questionsSubmitted` after accepting it. Repeated activations are guarded while navigation or submission settles. A busy state that ends without a saved receipt permits retry. The app owns persistence, transport, and duplicate prevention across requests.\n\nBoth answer callbacks and an enabled form are required for interaction. `disabled`, `pending`, and active streaming lock the current question. Use `questionsDisabled` for an inactive earlier batch: it shows every original question and option read-only, without navigation actions. `questionsSubmitted` shows saved answers with an Answers sent receipt. Multiple-choice receipts include every selected label and custom text; an answer-mode override is identified as Multiple answers selected by you. Question labels and descriptions remain literal text; RadioGroup supplies arrow navigation and accessible group names. The counter is announced as Question X of N in a polite live region; navigation moves focus there through the kit's shared browser and native accessibility focus mechanism.\n\nThe current question is framed by the existing compact, flat selected Card: a soft theme tint and primary border distinguish its counter, answers and actions from the surrounding conversation. Saved receipts and inactive question history remain unframed. The Card is visual only, so answer controls retain their own accessible roles and focus behavior.\n\n`Markdown` reuses Chat's safe grammar and renderer for standalone documents. It preserves heading levels one through six, emphasis, inline and fenced code, quotes, ordered and unordered lists, nested indentation, static checked/unchecked task lists, horizontal rules, and pipe tables.\nTables use Canvas DataTable's container-responsive stacked layout on narrow surfaces, retaining every column on iOS too.\nChecklists are read-only Canvas selection controls; reading a document never changes its source. HTML, links and image syntax remain inert text: no source is executed and no remote image is requested. `MarkdownProps` accepts the source as children, an optional accessibility label and test ID; `compact` uses dense document typography. The parent supplies width.","android":"A controlled assistant conversation with independently scrolling messages, clear author and provider identities, and an anchored multiline composer. The parent supplies the bounds; Chat fills the available height without choosing a fixed height of its own.\n\nMessages remain application-owned `ChatMessageData`: keep each `id` stable while updating `content` during streaming. `pending` shows a three-dot thinking indicator until an explicitly `streaming` message arrives; pass `pendingIcon` to identify its provider. Streaming replies retain their own Responding indicator. Both animations stop when their state ends and stay still under Reduce Motion. `providerIcon` accepts an application-supplied provider logo beside the author; label the image or icon with the provider name for assistive technology. `provider` remains an optional supplementary text label such as the transport name. `error` adds a visible failure label; `notice` preserves delivery or fallback information. `footer` anchors connection, review, or other actions below the composer and outside the scrollport.\n\nThe conversation reads like a desktop assistant: one centered column at most 768 points wide, assistant replies as plain text across it, the person's own turns as a neutral bubble on the trailing side without an author line (an explicit `author` or provider still shows), and the composer as one raised, rounded box below with a round add button and a round send button.\n\nSet `activity` on a message for work the assistant did rather than said, such as a command, a tool call or a process log. It shows as one muted line, its `author` then its `notice`, and expands to its markdown `content` when pressed.\n\nPass `actions` on any message for app-owned choices beneath its content: each has a stable `id`, a literal `label`, and optional `primary`. Chat, ChatThread, and ChatMessage call `onAction(messageId, actionId)` when chosen. Choices wrap at narrow widths and use each platform’s Button. `disabled`, `pending`, any streaming message in the thread, or an absent callback prevents activation. The app owns saving the choice, setting busy state while it is accepted, duplicate prevention, and removing resolved or historical actions. Actions do not send a composer draft or submit question answers.\n\nAssistant content supports paragraphs, headings, lists, quotes, fenced code, bold, emphasis, and inline code through React Native text. HTML, images, and links stay literal text and never load or execute remote content. `plain` renders all source punctuation literally; user messages are always plain text. This is a small safe markdown subset rather than a complete CommonMark renderer.\n\n`ChatThread` follows new content while the reader is within 48 points of the bottom. Scrolling up to read older messages pauses following; returning to the bottom resumes it. Message updates, streaming text, question-height changes, and viewport resizing coalesce into a tail adjustment after layout settles. Scrolling is immediate and never animated, so it does not add motion when text streams or Reduce Motion is enabled. The overflowing thread is keyboard focusable with a visible focus frame. The native app or owning Dialog handles safe areas and keyboard avoidance.\n\n`ChatComposer` keeps Enter available for newlines. Its explicit Send control receives the trimmed draft through `onSend`; empty, disabled, pending, or uploading sends are blocked. An attached file permits an empty text draft. `sendDisabled` blocks only Send while leaving drafts, attachment controls, and message choices interactive; use it when a saved choice must be made before another freeform message. Pending replies leave the draft editable. The app owns draft clearing, transport, cancellation, persistence, and retry behavior.\n\nPass `terminal` to Chat or its standalone pieces for a flat, left-aligned monospace transcript. Messages use `❯` for the user and `●` for the assistant beside their author, preserving provider text and current delivery state. No user bubble or conversation card is added. The bare composer places `❯` and its multiline editor between two full-width hairlines, with an explicit rectangular Send action. Hardware Enter sends; Shift+Enter inserts a newline. IME composition and native soft-keyboard Enter retain their normal text-entry behavior. Sending returns focus to the editor; `autoFocus` optionally focuses it on mount. The app still owns clearing the draft, delivery, and preventing duplicate requests. Pending replies keep the draft editable and block sending.\n\n`Markdown terminal` preserves the same safe document grammar with 13px monospace text, compact spacing, and semantic headings. Tables remain aligned table rows in a horizontal scrollport instead of becoming stacked cards. Fenced code and tabs remain literal whitespace. `Textarea terminal` supplies the prompt's bare monospace metrics and implies `embedded`; existing Textarea defaults remain unchanged.\n\nSet `onAttach` to show the accessible paperclip action. The app owns file picking and uploading, passes composer `attachments`, and removes a staged file through `onRemoveAttachment(id)`. A `ChatAttachmentData` has an `id`, `name`, optional `uploading` or `error` flags, and optional `notice` text. Uploading and failed files block sending; remove a failed file or replace it after retrying. `attaching` also blocks attaching and sending while the app opens a picker or uploads. Saved message attachments use the same metadata; `onOpenAttachment(attachment)` on Chat, ChatThread, or ChatMessage delegates opening or downloading to the app. Canvas never requests, uploads, or opens file URLs itself.\n\nAn assistant message can include `questions`: each `ChatQuestionData` has a stable `id`, `title`, optional `multiple`, and `options` with an `id`, `label`, and optional `description`. Supply controlled `ChatQuestionAnswerData` entries in `questionAnswers` containing `questionId`, `optionId` for a single choice or `optionIds` for multiple choices, and optional `customText`. Set `multiple` on the question for checkboxes; a custom answer can be combined with regular choices. A single-choice question also offers Select multiple at the bottom-right of its action row: switching it on records `multiple: true` in its answer and uses `optionIds`, preserving the original question metadata. The switch retains existing selections and custom text. Switching it off returns to the first selected choice, or clears an empty draft. Every question offers Write my own answer under the reserved `__custom` option id, limited to 1000 characters.\n\nThe active form shows one question with a counter derived from the actual question count. Selecting an ordinary radio saves and advances before the last question. Custom text stays on the current question and uses Next; a blank custom answer cannot advance. Back is a neutral outline button that preserves saved selections and text. Revisited valid single choices offer Next. Checkboxes use Submit to advance; Submit appears only for multiple-choice questions and the last question. The last question always requires explicit Submit before the complete batch is sent, and every question must have a real answer. An incomplete earlier answer returns the reader to the first unresolved question instead of submitting. Submitted custom text is trimmed.\n\nChat, ChatThread, and ChatMessage expose `onQuestionAnswerChange(messageId, answers)`, `onQuestionIndexChange(messageId, index)`, and `onSubmitQuestionAnswers(messageId, answers)`. Record answer changes in message data and pass the zero-based `questionIndex` to control navigation, including saved continuation after reload. Omitting `questionIndex` uses local navigation state. The position is clamped to the actual list. The final callback receives fresh answers for the whole batch, including the current answer; set `questionsSubmitted` after accepting it. Repeated activations are guarded while navigation or submission settles. A busy state that ends without a saved receipt permits retry. The app owns persistence, transport, and duplicate prevention across requests.\n\nBoth answer callbacks and an enabled form are required for interaction. `disabled`, `pending`, and active streaming lock the current question. Use `questionsDisabled` for an inactive earlier batch: it shows every original question and option read-only, without navigation actions. `questionsSubmitted` shows saved answers with an Answers sent receipt. Multiple-choice receipts include every selected label and custom text; an answer-mode override is identified as Multiple answers selected by you. Question labels and descriptions remain literal text; RadioGroup supplies arrow navigation and accessible group names. The counter is announced as Question X of N in a polite live region; navigation moves focus there through the kit's shared browser and native accessibility focus mechanism.\n\nThe current question is framed by the existing compact, flat selected Card: a soft theme tint and primary border distinguish its counter, answers and actions from the surrounding conversation. Saved receipts and inactive question history remain unframed. The Card is visual only, so answer controls retain their own accessible roles and focus behavior.\n\n`Markdown` reuses Chat's safe grammar and renderer for standalone documents. It preserves heading levels one through six, emphasis, inline and fenced code, quotes, ordered and unordered lists, nested indentation, static checked/unchecked task lists, horizontal rules, and pipe tables.\nTables use Canvas DataTable's container-responsive stacked layout on narrow surfaces.\nChecklists are read-only Canvas selection controls; reading a document never changes its source. HTML, links and image syntax remain inert text: no source is executed and no remote image is requested. `MarkdownProps` accepts the source as children, an optional accessibility label and test ID; `compact` uses dense document typography. The parent supplies width."}},{"slug":"checkbox","name":"Checkbox","category":"atoms","description":"Multi-select option, single yes/no, grouped lists.","source":"src/atoms/checkbox/checkbox.md","url":"https://canvas.nannier.com/ai/4.2.0/components/checkbox.md","humanUrl":"https://canvas.nannier.com/components/checkbox","exports":["Checkbox","CheckboxProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"CheckboxProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"Label text (the option's title) shown beside the box."},{"name":"description","type":"ReactNode","required":false,"description":"Optional muted secondary line rendered under the label, for the common title-plus-description option (a notification setting, a consent row). Supplying it builds the stacked title/description layout inside the control, so the caller never hand-composes a Row + Column + two Typography nodes and the whole row stays tappable."},{"name":"checked","type":"boolean | undefined","required":false,"description":"Controlled checked state; omit for uncontrolled use.","default":"false"},{"name":"defaultChecked","type":"boolean | undefined","required":false,"description":"Initial state for uncontrolled use (a bare <Checkbox /> is interactive).","default":"false"},{"name":"indeterminate","type":"boolean | undefined","required":false,"description":"Mixed state: some-but-not-all selected. Shown as a dash, not a tick. Takes visual precedence over `checked`. Implies `selection`: a mixed state belongs to a list's select-all, and a switch has none.","default":"false"},{"name":"selection","type":"boolean | undefined","required":false,"description":"A checkbox that selects an item in a list or a bulk selection (a table's rows, a list in edit mode, a select-all), rather than one on/off setting. The web draws the checkbox, iOS the edit-mode selection circle, Android the Material 3 checkbox. Without it a Checkbox is one setting, which iOS and Android render as their switch (role `switch`), so a settings row reads the way each platform writes it.","default":"false"},{"name":"onChange","type":"((next: boolean) => void) | undefined","required":false,"description":"Fired with the next checked value when the row is pressed (both modes). Web keyboard activation supports Space on release and Enter."},{"name":"onValueChange","type":"((next: boolean) => void) | undefined","required":false,"description":"Alias of onChange, for parity with RN's value-style callbacks."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for a LABEL-LESS checkbox (one with no `children`, e.g. a row selector in a table). With a visible label the label itself is the name; without one this is what a screen reader announces."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the pressable row."},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the base box).","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the base box).","default":"false","group":0},{"name":"disabled","type":"boolean | undefined","required":false,"description":"State.","default":"false","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1},{"name":"ref","type":"React.Ref<View>","required":false,"description":"Ref to the interactive checkbox row, including its label. Typed as a React Native View. On web, React Native Web exposes its DOM host; focus() and blur() move browser focus. Native host behavior depends on the platform and React Native version. Calling focus() does not activate the control or call accessibility focus APIs."}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default is the base box)."},{"title":"State","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"Multi-select option, single yes/no, grouped lists.\n\nOne job, a platform's own control: a Checkbox that is one setting (a yes/no, a consent, an opt-in)\nrenders the platform's switch on iOS and Android, where a single setting is a switch (Material 3 on phones included), and stays a checkbox on the web; its role follows what renders (`switch` there, `checkbox` here).\nA Checkbox that selects items in a list, a table's rows or a \"select all\" parent takes `selection`:\nthe web keeps the checkbox, Android the Material 3 checkbox, and iOS draws the edit-mode selection circle.\n`indeterminate` implies `selection`, since a mixed state belongs to a \"select all\" parent and a switch has none. In glass mode the box keeps its solid look on every platform: it is a small mark inside content, not a surface, so it draws with no pane and no rim, a checked box in its solid brand fill under its check and an empty box with its solid outline.\n\nPass `ref` to access the interactive checkbox row, including its label. Use `useRef<ComponentRef<typeof Checkbox>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn the web, Space activates the focused control on key release, and Enter also activates it. Holding Space does not repeat the change. Moving focus away, disabling the control, or composing text cancels a pending Space press.","ios":"Multi-select option, single yes/no, grouped lists.\n\nOne job, a platform's own control: a Checkbox that is one setting (a yes/no, a consent, an opt-in)\nrenders the platform's switch, where a single setting is a switch, and stays a checkbox on the web; its role follows what renders (`switch` here, `checkbox` there).\nA Checkbox that selects items in a list, a table's rows or a \"select all\" parent takes `selection`:\niOS draws the edit-mode selection circle.\n`indeterminate` implies `selection`, since a mixed state belongs to a \"select all\" parent and a switch has none. In glass mode the box keeps its solid look on every platform: it is a small mark inside content, not a surface, so it draws with no pane and no rim, a checked box in its solid brand fill under its check and an empty box with its solid outline.\n\nPass `ref` to access the interactive checkbox row, including its label. Use `useRef<ComponentRef<typeof Checkbox>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn the web, Space activates the focused control on key release, and Enter also activates it. Holding Space does not repeat the change. Moving focus away, disabling the control, or composing text cancels a pending Space press.","android":"Multi-select option, single yes/no, grouped lists.\n\nOne job, a platform's own control: a Checkbox that is one setting (a yes/no, a consent, an opt-in)\nrenders the platform's switch, where a single setting is a switch, and stays a checkbox on the web; its role follows what renders (`switch` here, `checkbox` there).\nA Checkbox that selects items in a list, a table's rows or a \"select all\" parent takes `selection`:\nAndroid draws the Material 3 checkbox.\n`indeterminate` implies `selection`, since a mixed state belongs to a \"select all\" parent and a switch has none. In glass mode the box keeps its solid look on every platform: it is a small mark inside content, not a surface, so it draws with no pane and no rim, a checked box in its solid brand fill under its check and an empty box with its solid outline.\n\nPass `ref` to access the interactive checkbox row, including its label. Use `useRef<ComponentRef<typeof Checkbox>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn the web, Space activates the focused control on key release, and Enter also activates it. Holding Space does not repeat the change. Moving focus away, disabling the control, or composing text cancels a pending Space press."}},{"slug":"chip","name":"Chip","category":"atoms","description":"An interactive pill for filter chips, tags, and selectable tokens. It carries an optional leading icon and a label, becomes tappable with `onPress`, and grows a trailing \"×\" remove button with `onRemove`.","source":"src/atoms/chip/chip.md","url":"https://canvas.nannier.com/ai/4.2.0/components/chip.md","humanUrl":"https://canvas.nannier.com/components/chip","exports":["Chip","ChipGroup","ChipGroupProps","ChipProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ChipGroupProps","props":[{"name":"value","type":"string | number | undefined","required":false,"description":"The chosen chip's value (CONTROLLED). Omit for uncontrolled use."},{"name":"defaultValue","type":"string | number | undefined","required":false,"description":"Initial chosen value for uncontrolled use (a bare group selects on press)."},{"name":"onChange","type":"((value: string | number) => void) | undefined","required":false,"description":"Fired with the newly chosen chip's value."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Disable every chip in the group.","default":"false"},{"name":"option","type":"boolean | undefined","required":false,"description":"Draw every chip as an `option` chip (Chip's compact settings pick), 4 px apart: the pick-one sets of a settings panel.","default":"false"},{"name":"label","type":"string | undefined","required":false,"description":"The group's name, rendered as a heading above the chips and announced as the radiogroup's accessible name. The group owns this label anatomy; never hand-compose a heading Text beside a bare group."},{"name":"description","type":"ReactNode","required":false,"description":"Optional muted supporting line rendered under the label."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"The group's accessible name when the page already shows its heading elsewhere (no visible label is rendered). `label` wins when both are passed."},{"name":"children","type":"ReactNode","required":false,"description":"The `<Chip value=\"…\">` options that make up the set."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the group container."},{"name":"style","type":"LayoutStyle","required":false,"description":"Outer layout composition only (flex within a parent), never a restyle hook."}],"groups":[],"inherits":[]},{"name":"ChipProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"The chip label."},{"name":"count","type":"string | number | undefined","required":false,"description":"A dimmed trailing count, set in the mono face."},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a chip within an app-owned host layout.","default":"false"},{"name":"icon","type":"ReactNode","required":false,"description":"A leading element (e.g. an `<Icon />` or a small `<Avatar />`). An `<Icon />` is auto-tinted to the chip's label color unless it sets its own color."},{"name":"trailing","type":"ReactNode","required":false,"description":"A trailing element (e.g. a chevron for a menu trigger). Rendered after the label."},{"name":"onPress","type":"((event?: GestureResponderEvent) => void) | undefined","required":false,"description":"Makes the whole chip tappable (e.g. toggling a filter). Called with the press event, which a ChipGroup option's Space key does not have, so an `href` chip that routes on the client calls `event?.preventDefault()` here."},{"name":"href","type":"string | undefined","required":false,"description":"Makes the chip a LINK to this destination (a route or a URL): on the web react-native-web renders the chip as an `<a href>`, so middle-click, cmd-click and open-in-new-tab work and assistive tech hears a link; it takes the link chip's hover (the accent ink inside an accent edge) in place of the brightening. Native platforms have no anchors, so pair it with an `onPress` that navigates through the host's router, as Button's `href` does. While `disabled` the anchor is suppressed. A link is not a toggle, so it is ignored on a selectable chip or a ChipGroup option."},{"name":"hrefAttrs","type":"{ target?: \"_blank\" | \"_self\"; rel?: string; download?: boolean | string; } | undefined","required":false,"description":"Anchor attributes forwarded with `href` on the web (react-native-web's `hrefAttrs`): `target`, `rel`, `download`. Ignored without `href`, and everywhere natively."},{"name":"onRemove","type":"(() => void) | undefined","required":false,"description":"Adds a trailing \"×\" remove button firing this handler."},{"name":"selectable","type":"boolean | undefined","required":false,"description":"Turns the chip into a filter toggle that owns its own selected state: pressing it lights up (to the accent's soft wash, inside an accent edge on the web and iOS) and back. Selection is controlled via `selected`, uncontrolled via `defaultSelected`.","default":"false"},{"name":"selected","type":"boolean | undefined","required":false,"description":"Selected state for a selectable chip (CONTROLLED). Omit for uncontrolled use.","default":"false"},{"name":"defaultSelected","type":"boolean | undefined","required":false,"description":"Initial selected state for an uncontrolled selectable chip.","default":"false"},{"name":"onSelectedChange","type":"((selected: boolean) => void) | undefined","required":false,"description":"Fired with the next selected state when a selectable chip is pressed."},{"name":"value","type":"string | number | undefined","required":false,"description":"The chip's option value inside a ChipGroup: the chip is one option of the pick-one set, selected when the group's value is this one, and reads as a radio. Ignored outside a group."},{"name":"success","type":"boolean | undefined","required":false,"description":"Color axis (pick one; default the neutral tag). Two families, both a soft tint: Semantic status (matches Badge): success / warning / error / info / neutral.","default":"false","group":0},{"name":"warning","type":"boolean | undefined","required":false,"description":"Color axis (pick one; default the neutral tag). Two families, both a soft tint: Semantic status (matches Badge): success / warning / error / info / neutral.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"The danger tone. This is the name the intent axis uses across the kit (Button, AlertDialog, and every chart) and the one the design hand-off uses here too.","default":"false","group":0},{"name":"info","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"neutral","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"red","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"orange","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"amber","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"yellow","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"lime","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"green","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"emerald","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"teal","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"cyan","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"sky","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"blue","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"indigo","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"violet","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"fuchsia","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"purple","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"pink","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"rose","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"gray","type":"boolean | undefined","required":false,"description":"Free-form palette hues, plus `gray` for an explicit neutral tag.","default":"false","group":1},{"name":"secondary","type":"boolean | undefined","required":false,"description":"Emphasis (orthogonal to color). `outline` is border-only; `primary` is the solid accent. `secondary` is the raised neutral fill (the default on the web and iOS; on Android it fills the otherwise bare outlined chip).","default":"false","group":2},{"name":"primary","type":"boolean | undefined","required":false,"description":"Emphasis (orthogonal to color). `outline` is border-only; `primary` is the solid accent. `secondary` is the raised neutral fill (the default on the web and iOS; on Android it fills the otherwise bare outlined chip).","default":"false","group":2},{"name":"outline","type":"boolean | undefined","required":false,"description":"Emphasis (orthogonal to color). `outline` is border-only; `primary` is the solid accent. `secondary` is the raised neutral fill (the default on the web and iOS; on Android it fills the otherwise bare outlined chip).","default":"false","group":2},{"name":"option","type":"boolean | undefined","required":false,"description":"A compact option in a settings panel, the hand-off playground's knob pick: 26 tall at a small corner, a 500 12px label and no check, idle a bare field-border edge around the muted ink, selected the accent's soft wash inside its edge. An icon-only option is a 30 px square. A ChipGroup's `option` sets it on every chip. On Android an option is the Material 3 chip.","default":"false","group":3},{"name":"token","type":"boolean | undefined","required":false,"description":"A token tag, the hand-off's Tokens chip: a 32 px pill in the card fill inside the hairline, 8 between elements, a 500 12 px mono label, 12 on the text side and 6 beside its leading element, which is sized for a 20 px swatch (`<Chip token icon={<Swatch tiny ring circle color={tokens.primary} />}>`). On Android a token tag is the Material 3 chip.","default":"false","group":3},{"name":"link","type":"boolean | undefined","required":false,"description":"A link to another page, the hand-off's section card link pill: 26 tall at the full round, 10 at both sides, a 500 12 px label in the secondary ink on the popover fill inside the field-border edge; a hovering pointer turns the label and the edge to the accent. Pair it with `href` (and a trailing `<Icon arrowUpRight size={12} />`, which takes the label's ink). A press keeps the resting look, as the hand-off draws it. On Android a link is the Material 3 assist chip.","default":"false","group":3},{"name":"square","type":"boolean | undefined","required":false,"description":"Forces an `option` chip to the 30 px square an icon-only option takes, even when it carries a label and no icon; a label inside the square is set in the tile's own type, a 500 10 px mono line (the hand-off's \"none\" pick in an icon knob). Ignored off the `option` look.","default":"false","group":3},{"name":"small","type":"boolean | undefined","required":false,"description":"A small metadata tag; option, token and link looks retain their own dimensions.","default":"false","group":3},{"name":"disabled","type":"boolean | undefined","required":false,"description":"","default":"false","group":3},{"name":"steadyPress","type":"boolean | undefined","required":false,"description":"Keep resting opacity while pressed, preserving the reference filter treatment.","default":"false","group":3},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"","group":3},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":3},{"name":"style","type":"LayoutStyle","required":false,"description":"For layout composition only (not styling).","group":3}],"groups":[{"title":"Color axis","pickOne":true,"note":"Color axis (pick one; default the neutral tag). Two families, both a soft tint: Semantic status (matches Badge): success / warning / error / info / neutral."},{"title":"Free-form palette hues, plus `gray` for an explicit neutral tag","pickOne":false},{"title":"Emphasis","pickOne":false,"note":"Emphasis (orthogonal to color). `outline` is border-only; `primary` is the solid accent. `secondary` is the raised neutral fill (the default on the web and iOS; on Android it fills the otherwise bare outlined chip)."},{"title":"Look","pickOne":true,"note":"Look (pick one; omit for the chip itself). Precedence: `token` > `option` > `link`."}],"inherits":[]}],"platformNotes":{"web":"An interactive pill for filter chips, tags, and selectable tokens. It carries an\noptional leading icon and a label, becomes tappable with `onPress`, and grows a\ntrailing \"×\" remove button with `onRemove`.\n\nA Chip is a LOW-emphasis tag, not a call to action: the neutral chip is a 28 px\noutlined pill (the raised neutral fill inside a hairline, its label at weight\n500). A status chip is its soft pill (the status wash under the status ink, the\nrecipe Alert and the other toned surfaces share); a palette hue is that hue's\n16% wash inside the same hue at 30%, under a deep ink in the hue that holds\n4.5:1 on the wash. A selectable chip rests as the bare pill in the field border,\nand once selected it is the accent's soft wash in the accent ink, inside an\naccent edge and leading with a check.\nOn Android the chip is Material 3's: a 32dp outlined\ncontainer at the 8dp chip corner, its selected filter chip tonal with an 18dp\ncheck and no outline.\nThe chip owns that whole look, so no call site\nhand-composes a `borderRadius` + `backgroundColor` + padding Pressable.\n\nTwo orthogonal axes drive the look:\n\n- **Color** (pick one; default the neutral tag). A semantic status (`success`,\n  `warning`, `destructive`, `info`, `neutral`) or a free-form palette hue (`red`,\n  `orange`, `amber`, `yellow`, `lime`, `green`, `emerald`, `teal`, `cyan`, `sky`,\n  `blue`, `indigo`, `violet`, `fuchsia`, `purple`, `pink`, `rose`, `gray`). Status\n  names read the theme's status colors (`statusColors`), so a success chip matches a\n  success Badge and Alert; `info` is the primary color. Precedence when more than one\n  is set: status names first, then hues in the order above.\n- **Emphasis**. `outline` drops the fill for the field-border edge around the\n  color's ink; `primary` is the solid accent;\n`secondary` is the higher raised\n  fill with no edge (on Android, the filled chip beside the bare outlined\n  container that is its idle chip).\n`neutral` is the muted tag with no edge;\n  `gray` is the same muted fill and ink inside the chip's own edge. `outline` composes with any color,\n  e.g. `<Chip blue outline>`. Precedence: a color wins over `primary`, and\n  `outline` wins over `primary`'s fill.\n\n`count` adds a dimmed trailing count in the mono face. A hovering pointer\nbrightens the chip on the web. `start` pins a chip when its host layout does not\npublish a Canvas sizing context.\n\n`steadyPress` retains the resting opacity during a press, while selection,\nhover feedback and the native ripple keep working.\n\n`href` makes the chip a link to a route or a URL: a real anchor on the web (so\nmiddle-click and open-in-new-tab work and assistive tech hears a link), with\n`hrefAttrs` forwarding `target`, `rel` and `download`. Native platforms have no\nanchors, so pair `href` with an `onPress` that navigates through the app's router; it\nreceives the press event, so a web app routing on the client calls\n`event?.preventDefault()` there. A hovering pointer turns a link chip's ink and edge to\nthe accent instead of brightening it. A link is not a toggle: `href` is ignored on a\nselectable chip or a ChipGroup option.\n\n`small` gives passive metadata tags a 24 px container and 11 px label where the skin supports it. Platform-native chips and the option, token and link looks keep their own dimensions.","ios":"An interactive pill for filter chips, tags, and selectable tokens. It carries an\noptional leading icon and a label, becomes tappable with `onPress`, and grows a\ntrailing \"×\" remove button with `onRemove`.\n\nA Chip is a LOW-emphasis tag, not a call to action: the neutral chip is a 28 px\noutlined pill (the raised neutral fill inside a hairline, its label at weight\n500). A status chip is its soft pill (the status wash under the status ink, the\nrecipe Alert and the other toned surfaces share); a palette hue is that hue's\n16% wash inside the same hue at 30%, under a deep ink in the hue that holds\n4.5:1 on the wash. A selectable chip rests as the bare pill in the field border,\nand once selected it is the accent's soft wash in the accent ink, inside an\naccent edge and leading with a check.\nThe chip owns that whole look, so no call site\nhand-composes a `borderRadius` + `backgroundColor` + padding Pressable.\n\nTwo orthogonal axes drive the look:\n\n- **Color** (pick one; default the neutral tag). A semantic status (`success`,\n  `warning`, `destructive`, `info`, `neutral`) or a free-form palette hue (`red`,\n  `orange`, `amber`, `yellow`, `lime`, `green`, `emerald`, `teal`, `cyan`, `sky`,\n  `blue`, `indigo`, `violet`, `fuchsia`, `purple`, `pink`, `rose`, `gray`). Status\n  names read the theme's status colors (`statusColors`), so a success chip matches a\n  success Badge and Alert; `info` is the primary color. Precedence when more than one\n  is set: status names first, then hues in the order above.\n- **Emphasis**. `outline` drops the fill for the field-border edge around the\n  color's ink; `primary` is the solid accent;\n`secondary` is the higher raised fill with no edge.\n`neutral` is the muted tag with no edge;\n  `gray` is the same muted fill and ink inside the chip's own edge. `outline` composes with any color,\n  e.g. `<Chip blue outline>`. Precedence: a color wins over `primary`, and\n  `outline` wins over `primary`'s fill.\n\n`count` adds a dimmed trailing count in the mono face. A hovering pointer\nbrightens the chip on the web. `start` pins a chip when its host layout does not\npublish a Canvas sizing context.\n\n`steadyPress` retains the resting opacity during a press, while selection,\nhover feedback and the native ripple keep working.\n\n`href` makes the chip a link to a route or a URL: a real anchor on the web (so\nmiddle-click and open-in-new-tab work and assistive tech hears a link), with\n`hrefAttrs` forwarding `target`, `rel` and `download`. Native platforms have no\nanchors, so pair `href` with an `onPress` that navigates through the app's router; it\nreceives the press event, so a web app routing on the client calls\n`event?.preventDefault()` there. A hovering pointer turns a link chip's ink and edge to\nthe accent instead of brightening it. A link is not a toggle: `href` is ignored on a\nselectable chip or a ChipGroup option.\n\n`small` gives passive metadata tags a 24 px container and 11 px label where the skin supports it. Platform-native chips and the option, token and link looks keep their own dimensions.","android":"An interactive pill for filter chips, tags, and selectable tokens. It carries an\noptional leading icon and a label, becomes tappable with `onPress`, and grows a\ntrailing \"×\" remove button with `onRemove`.\n\nA Chip is a LOW-emphasis tag, not a call to action: the neutral chip is a 28 px\noutlined pill (the raised neutral fill inside a hairline, its label at weight\n500). A status chip is its soft pill (the status wash under the status ink, the\nrecipe Alert and the other toned surfaces share); a palette hue is that hue's\n16% wash inside the same hue at 30%, under a deep ink in the hue that holds\n4.5:1 on the wash. A selectable chip rests as the bare pill in the field border,\nand once selected it is the accent's soft wash in the accent ink, inside an\naccent edge and leading with a check.\nOn Android the chip is Material 3's: a 32dp outlined\ncontainer at the 8dp chip corner, its selected filter chip tonal with an 18dp\ncheck and no outline.\nThe chip owns that whole look, so no call site\nhand-composes a `borderRadius` + `backgroundColor` + padding Pressable.\n\nTwo orthogonal axes drive the look:\n\n- **Color** (pick one; default the neutral tag). A semantic status (`success`,\n  `warning`, `destructive`, `info`, `neutral`) or a free-form palette hue (`red`,\n  `orange`, `amber`, `yellow`, `lime`, `green`, `emerald`, `teal`, `cyan`, `sky`,\n  `blue`, `indigo`, `violet`, `fuchsia`, `purple`, `pink`, `rose`, `gray`). Status\n  names read the theme's status colors (`statusColors`), so a success chip matches a\n  success Badge and Alert; `info` is the primary color. Precedence when more than one\n  is set: status names first, then hues in the order above.\n- **Emphasis**. `outline` drops the fill for the field-border edge around the\n  color's ink; `primary` is the solid accent;\n`secondary` is the higher raised\n  fill with no edge (on Android, the filled chip beside the bare outlined\n  container that is its idle chip).\n`neutral` is the muted tag with no edge;\n  `gray` is the same muted fill and ink inside the chip's own edge. `outline` composes with any color,\n  e.g. `<Chip blue outline>`. Precedence: a color wins over `primary`, and\n  `outline` wins over `primary`'s fill.\n\n`count` adds a dimmed trailing count in the mono face. A hovering pointer\nbrightens the chip on the web. `start` pins a chip when its host layout does not\npublish a Canvas sizing context.\n\n`steadyPress` retains the resting opacity during a press, while selection,\nhover feedback and the native ripple keep working.\n\n`href` makes the chip a link to a route or a URL: a real anchor on the web (so\nmiddle-click and open-in-new-tab work and assistive tech hears a link), with\n`hrefAttrs` forwarding `target`, `rel` and `download`. Native platforms have no\nanchors, so pair `href` with an `onPress` that navigates through the app's router; it\nreceives the press event, so a web app routing on the client calls\n`event?.preventDefault()` there. A hovering pointer turns a link chip's ink and edge to\nthe accent instead of brightening it. A link is not a toggle: `href` is ignored on a\nselectable chip or a ChipGroup option.\n\n`small` gives passive metadata tags a 24 px container and 11 px label where the skin supports it. Platform-native chips and the option, token and link looks keep their own dimensions."}},{"slug":"code-block","name":"CodeBlock","category":"molecules","description":"Syntax-highlighted code display with clipboard copy, horizontal scrolling, line emphasis, diff rendering, collapsible folding, and tabbed alternatives.","source":"src/molecules/code-block/code-block.md","url":"https://canvas.nannier.com/ai/4.2.0/components/code-block.md","humanUrl":"https://canvas.nannier.com/components/code-block","exports":["CodeBlock","CodeBlockProps","CodeBlockTab"],"dependencies":[{"name":"expo-clipboard","range":"*","optional":true},{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"CodeBlockProps","props":[{"name":"code","type":"string | undefined","required":false,"description":"The code to render. Newlines are preserved (RN Text honors \"\\n\")."},{"name":"filename","type":"string | undefined","required":false,"description":"Optional filename label shown in a header bar above the surface. Honored by the plain and numbered variants (and the terminal chrome label); the inline pill has no header. When both are set, `filename` takes the header label and `language` renders as a trailing badge."},{"name":"language","type":"string | undefined","required":false,"description":"The snippet's language. Drives syntax highlighting (ts/tsx/js/jsx, json, bash/sh, css, html, python — anything else renders monochrome) and the header/terminal label when no `filename` is given."},{"name":"transcript","type":"boolean | undefined","required":false,"description":"Bare execution output: selectable, wrapped monochrome text with no card, header or expander. Takes precedence over terminal, numbered and inline; other display modifiers are ignored.","default":"false","group":0},{"name":"terminal","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"numbered","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"inline","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (pick one; default is the comfortable ramp).","default":"false","group":1},{"name":"playground","type":"boolean | undefined","required":false,"description":"The hand-off component page's JSX card (Component.dc.html lines 171 to 174, the playground's output): the block at the card corner, its header a 40 px bar on the card fill, 16 in and 8 out, with its Copy a 28 px hairline button, and the code 16 above and below, 18 in, at the default 13 / 1.7 ramp. `compact` wins when both are passed.","default":"false","group":1},{"name":"snippet","type":"boolean | undefined","required":false,"description":"The hand-off component page's own snippet (Component.dc.html line 283, the Usage section's block under its paragraph): the code-card corner, with the code 16 above and below and 18 in at the default 13 / 1.7 ramp. `compact` and `playground` win over it.","default":"false","group":1},{"name":"guide","type":"boolean | undefined","required":false,"description":"The hand-off component page's card snippet (Component.dc.html line 288, the block in a Usage guidance card): the card-snippet corner, with the code 12 above and below and 14 in at 12 / 1.65. Every other density wins over it.","default":"false","group":1},{"name":"copy","type":"boolean | undefined","required":false,"description":"Show a copy affordance (header-hosted when a header/chrome exists, else pinned top-right). On the `inline` variant the whole pill becomes the copy button: a raised mono chip with a trailing copy glyph that turns to a check once copied (an import line a reader takes away).","default":"false","group":2},{"name":"wrap","type":"boolean | undefined","required":false,"description":"Soft-wrap long lines instead of scrolling them horizontally. An overflowing unwrapped block is a keyboard tab stop; arrow keys use the platform's normal scrolling.","default":"false","group":2},{"name":"diff","type":"boolean | undefined","required":false,"description":"Render the code as a unified diff: the first column of every line is the marker (\"+\" added, \"-\" removed, anything else context). Added/removed rows tint green/red, markers stay out of the selection, and the copy chip yields the post-change code (context + added lines, markers stripped).","default":"false","group":2},{"name":"attached","type":"boolean | undefined","required":false,"description":"Square the top edge (no top radius/border) to sit flush under an adjoining bar.","default":"false","group":2},{"name":"headerless","type":"boolean | undefined","required":false,"description":"Draw no header bar: `language` still drives the highlighting, but neither it nor a `filename` labels the block, and `copy` floats over the code's top-right corner. For a snippet whose context already names it (a docs page's usage block). Plain and numbered variants; a `tabs` strip still needs its header, and the terminal keeps its chrome.","default":"false","group":2},{"name":"unbadged","type":"boolean | undefined","required":false,"description":"Keep the header bar but draw no trailing language badge beside the copy chip: `language` still drives the highlighting, for a header whose `filename` already names the language (the hand-off's playground bar, Component.dc.html lines 171 to 174, is \"JSX · <Interface>\" and a Copy button only). Nothing changes when there is no `filename`, since the language is then the header's label, not a badge.","default":"false","group":2},{"name":"highlightLines","type":"readonly (string | number)[] | undefined","required":false,"description":"Emphasize lines: entries are 1-based line numbers or \"start-end\" ranges (e.g. `[2, \"5-7\"]`). Numbers refer to the displayed numbering, so they respect `startLine`. Plain and numbered variants only.","group":2},{"name":"startLine","type":"number | undefined","required":false,"description":"First displayed line number for the numbered variant (default 1).","default":"1","group":2},{"name":"collapsible","type":"boolean | undefined","required":false,"description":"Fold long blocks behind a \"Show all\" expander (plain + numbered variants).","default":"false","group":2},{"name":"collapsedLines","type":"number | undefined","required":false,"description":"How many lines a collapsed block shows (default 8).","default":"8","group":2},{"name":"expanded","type":"boolean | undefined","required":false,"description":"Controlled expanded state for `collapsible`.","default":"false","group":2},{"name":"defaultExpanded","type":"boolean | undefined","required":false,"description":"Uncontrolled initial expanded state (default false).","default":"false","group":2},{"name":"onExpandedChange","type":"((expanded: boolean) => void) | undefined","required":false,"description":"Called when the expander toggles (fires in both modes).","group":2},{"name":"tabs","type":"readonly CodeBlockTab[] | undefined","required":false,"description":"Labeled code alternatives rendered as a tab strip in the header (or the terminal chrome) — the classic npm/yarn/bun switcher. Each tab supplies its own code and optional language/filename.","group":2},{"name":"active","type":"number | undefined","required":false,"description":"Controlled active tab index.","group":2},{"name":"defaultActive","type":"number | undefined","required":false,"description":"Uncontrolled initial tab index (default 0).","group":2},{"name":"onTabChange","type":"((index: number) => void) | undefined","required":false,"description":"Called with the next tab index when a tab is selected (fires in both modes).","group":2},{"name":"prompt","type":"string | undefined","required":false,"description":"The terminal prompt marker (default \"$\"). Lines starting with it render as commands.","default":"\"$\"","group":2},{"name":"onCopy","type":"((code: string, event: GestureResponderEvent) => void) | undefined","required":false,"description":"Called when the copy affordance is pressed, with the copied text. The chip also writes the clipboard itself (navigator.clipboard on web, the optional expo-clipboard peer on native), so this is for side effects, not plumbing.","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":2}],"groups":[{"title":"Variant","pickOne":true,"note":"Variant (pick one; default is the plain block)."},{"title":"Density","pickOne":true,"note":"Density (pick one; default is the comfortable ramp)."},{"title":"Orthogonal modifiers","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"Syntax-highlighted code display with clipboard copy, horizontal scrolling, line\nemphasis, diff rendering, collapsible folding, and tabbed alternatives.\n\nThe variant axis picks the surface (`transcript` > `terminal` > `numbered` > `inline` > plain,\nfirst match wins); the density axis is `compact` (the tightened ramp), `playground`\n(the hand-off component page's JSX card: the block at the card corner, its header a 40\npx bar on the card fill, 16 in and 8 out, its Copy a 28 px hairline button, and the code\n16 above and below and 18 in at the default ramp), `snippet` (the page's own snippet, the\nUsage section's block: the code-card corner with the code 16 above and below and 18 in\nat the default ramp) or `guide` (a card's snippet, the block in a guidance card: a 10 px\ncorner with the code 12 above and below and 14 in at 12 / 1.65), in that order of\nprecedence; `copy`, `wrap`, `diff`,\n`collapsible`, `attached`, `headerless`, and `unbadged` stack orthogonally. `language`\ndrives the in-kit highlighter (ts/tsx/js/jsx, json, bash, css, html, python; anything\nelse renders monochrome) and, with no `filename`, labels a header bar above the code;\nwith a `filename` it is a trailing badge beside the copy chip instead, which `unbadged`\ndrops for a filename that already names the language (the hand-off's playground bar,\n\"JSX · ButtonProps\" and a Copy button only). `headerless` keeps the highlighting and\ndrops the whole bar (a `tabs` strip and the terminal chrome stay), so `copy` floats\nover the code's corner. Long lines scroll horizontally instead of truncating, and\nevery run of code, highlighted tokens included, is set in the theme's mono face.\n\nThe block is the v4 hand-off's code card on every platform: the sunken well on a\nhairline at a 14 px corner, a 36 px header of 12 px mono labels, 13 / 1.7 code, line\nnumbers in the subtle ink, and the hand-off's code inks (each light-scheme ink held\nto 4.5:1 on the well). A ts or js snippet takes the hand-off's CodeBlock renderer:\nkeywords, strings, numbers and tag names in the accent, mint, amber and cyan. A tsx\nor jsx snippet takes the hand-off's component-page highlighter, which paints four\nthings and nothing else: a Capitalised tag name in the accent (the brackets and slash\nneutral), an attribute name before its `=` in cyan, a string literal in mint and a\ncomment in the subtle ink; a bare boolean attribute, a keyword, a number and the\nchildren text stay in the code ink, so `<Button>Save changes</Button>` reads as one\nlabel after one accent name. The terminal is a fixed dark window in every scheme.\n\n`inline` honours `copy` alone of the orthogonal booleans: `<CodeBlock inline copy>`\nis the import chip, a raised monospace pill (34 tall, the control corner, the\n`popover` fill and `field-border` hairline, 12 px mono in `muted-foreground`)\nwhose whole surface is one copy button, with a trailing copy glyph that turns to\na check for a moment once the code is on the clipboard. The chip copies the code\nverbatim, announces itself as \"Copy\" followed by the code, sets the code in one\nink (no syntax colours), and on the web its hairline turns to the accent under the\npointer. Under glass it is a control-layer pane.\n\nWhen a line is wider than the block, Tab reaches the scrollable code and the\nplatform's arrow keys scroll it; while it has keyboard focus, the block's card\ndraws the theme's focus ring. Short content, `wrap`, and `inline` do not add\na scrolling tab stop. Native scrolling continues to use the native ScrollView.","ios":"Syntax-highlighted code display with clipboard copy, horizontal scrolling, line\nemphasis, diff rendering, collapsible folding, and tabbed alternatives.\n\nThe variant axis picks the surface (`transcript` > `terminal` > `numbered` > `inline` > plain,\nfirst match wins); the density axis is `compact` (the tightened ramp), `playground`\n(the hand-off component page's JSX card: the block at the card corner, its header a 40\npx bar on the card fill, 16 in and 8 out, its Copy a 28 px hairline button, and the code\n16 above and below and 18 in at the default ramp), `snippet` (the page's own snippet, the\nUsage section's block: the code-card corner with the code 16 above and below and 18 in\nat the default ramp) or `guide` (a card's snippet, the block in a guidance card: a 10 px\ncorner with the code 12 above and below and 14 in at 12 / 1.65), in that order of\nprecedence; `copy`, `wrap`, `diff`,\n`collapsible`, `attached`, `headerless`, and `unbadged` stack orthogonally. `language`\ndrives the in-kit highlighter (ts/tsx/js/jsx, json, bash, css, html, python; anything\nelse renders monochrome) and, with no `filename`, labels a header bar above the code;\nwith a `filename` it is a trailing badge beside the copy chip instead, which `unbadged`\ndrops for a filename that already names the language (the hand-off's playground bar,\n\"JSX · ButtonProps\" and a Copy button only). `headerless` keeps the highlighting and\ndrops the whole bar (a `tabs` strip and the terminal chrome stay), so `copy` floats\nover the code's corner. Long lines scroll horizontally instead of truncating, and\nevery run of code, highlighted tokens included, is set in the theme's mono face.\n\nThe block is the v4 hand-off's code card on every platform: the sunken well on a\nhairline at a 14 px corner, a 36 px header of 12 px mono labels, 13 / 1.7 code, line\nnumbers in the subtle ink, and the hand-off's code inks (each light-scheme ink held\nto 4.5:1 on the well). A ts or js snippet takes the hand-off's CodeBlock renderer:\nkeywords, strings, numbers and tag names in the accent, mint, amber and cyan. A tsx\nor jsx snippet takes the hand-off's component-page highlighter, which paints four\nthings and nothing else: a Capitalised tag name in the accent (the brackets and slash\nneutral), an attribute name before its `=` in cyan, a string literal in mint and a\ncomment in the subtle ink; a bare boolean attribute, a keyword, a number and the\nchildren text stay in the code ink, so `<Button>Save changes</Button>` reads as one\nlabel after one accent name. The terminal is a fixed dark window in every scheme.\n\n`inline` honours `copy` alone of the orthogonal booleans: `<CodeBlock inline copy>`\nis the import chip, a raised monospace pill (34 tall, the control corner, the\n`popover` fill and `field-border` hairline, 12 px mono in `muted-foreground`)\nwhose whole surface is one copy button, with a trailing copy glyph that turns to\na check for a moment once the code is on the clipboard. The chip copies the code\nverbatim, announces itself as \"Copy\" followed by the code, sets the code in one\nink (no syntax colours), and on the web its hairline turns to the accent under the\npointer. Under glass it is a control-layer pane.\n\nWhen a line is wider than the block, Tab reaches the scrollable code and the\nplatform's arrow keys scroll it; while it has keyboard focus, the block's card\ndraws the theme's focus ring. Short content, `wrap`, and `inline` do not add\na scrolling tab stop. Native scrolling continues to use the native ScrollView.","android":"Syntax-highlighted code display with clipboard copy, horizontal scrolling, line\nemphasis, diff rendering, collapsible folding, and tabbed alternatives.\n\nThe variant axis picks the surface (`transcript` > `terminal` > `numbered` > `inline` > plain,\nfirst match wins); the density axis is `compact` (the tightened ramp), `playground`\n(the hand-off component page's JSX card: the block at the card corner, its header a 40\npx bar on the card fill, 16 in and 8 out, its Copy a 28 px hairline button, and the code\n16 above and below and 18 in at the default ramp), `snippet` (the page's own snippet, the\nUsage section's block: the code-card corner with the code 16 above and below and 18 in\nat the default ramp) or `guide` (a card's snippet, the block in a guidance card: a 10 px\ncorner with the code 12 above and below and 14 in at 12 / 1.65), in that order of\nprecedence; `copy`, `wrap`, `diff`,\n`collapsible`, `attached`, `headerless`, and `unbadged` stack orthogonally. `language`\ndrives the in-kit highlighter (ts/tsx/js/jsx, json, bash, css, html, python; anything\nelse renders monochrome) and, with no `filename`, labels a header bar above the code;\nwith a `filename` it is a trailing badge beside the copy chip instead, which `unbadged`\ndrops for a filename that already names the language (the hand-off's playground bar,\n\"JSX · ButtonProps\" and a Copy button only). `headerless` keeps the highlighting and\ndrops the whole bar (a `tabs` strip and the terminal chrome stay), so `copy` floats\nover the code's corner. Long lines scroll horizontally instead of truncating, and\nevery run of code, highlighted tokens included, is set in the theme's mono face.\n\nThe block is the v4 hand-off's code card on every platform: the sunken well on a\nhairline at a 14 px corner, a 36 px header of 12 px mono labels, 13 / 1.7 code, line\nnumbers in the subtle ink, and the hand-off's code inks (each light-scheme ink held\nto 4.5:1 on the well). A ts or js snippet takes the hand-off's CodeBlock renderer:\nkeywords, strings, numbers and tag names in the accent, mint, amber and cyan. A tsx\nor jsx snippet takes the hand-off's component-page highlighter, which paints four\nthings and nothing else: a Capitalised tag name in the accent (the brackets and slash\nneutral), an attribute name before its `=` in cyan, a string literal in mint and a\ncomment in the subtle ink; a bare boolean attribute, a keyword, a number and the\nchildren text stay in the code ink, so `<Button>Save changes</Button>` reads as one\nlabel after one accent name. The terminal is a fixed dark window in every scheme.\n\n`inline` honours `copy` alone of the orthogonal booleans: `<CodeBlock inline copy>`\nis the import chip, a raised monospace pill (34 tall, the control corner, the\n`popover` fill and `field-border` hairline, 12 px mono in `muted-foreground`)\nwhose whole surface is one copy button, with a trailing copy glyph that turns to\na check for a moment once the code is on the clipboard. The chip copies the code\nverbatim, announces itself as \"Copy\" followed by the code, sets the code in one\nink (no syntax colours), and on the web its hairline turns to the accent under the\npointer. Under glass it is a control-layer pane.\n\nWhen a line is wider than the block, Tab reaches the scrollable code and the\nplatform's arrow keys scroll it; while it has keyboard focus, the block's card\ndraws the theme's focus ring. Short content, `wrap`, and `inline` do not add\na scrolling tab stop. Native scrolling continues to use the native ScrollView."}},{"slug":"collapsible","name":"Collapsible","category":"molecules","description":"A single disclosure: one header (its `title`, or a custom `trigger`, plus a chevron that rotates when open) over one collapsible content panel.","source":"src/molecules/collapsible/collapsible.md","url":"https://canvas.nannier.com/ai/4.2.0/components/collapsible.md","humanUrl":"https://canvas.nannier.com/components/collapsible","exports":["Collapsible","CollapsibleProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"CollapsibleProps","props":[{"name":"title","type":"string | undefined","required":false,"description":"The default trigger label text."},{"name":"description","type":"string | undefined","required":false,"description":"The muted secondary line under the title in the default trigger anatomy (ignored when a custom `trigger` is given, which owns its own anatomy)."},{"name":"trigger","type":"ReactNode","required":false,"description":"A custom trigger node; if provided, it renders as the pressable's content instead of the `title` text (the chevron still renders alongside)."},{"name":"card","type":"boolean | undefined","required":false,"description":"Card surface: wraps the disclosure in an outlined card container with inset header and content (web/Android). On iOS the default Collapsible already renders as the inset-grouped card, so `card` is a no-op there.","default":"false"},{"name":"reference","type":"boolean | undefined","required":false,"description":"The reference-sheet card (a component page's sub-component props): the card corner on a hairline over the card fill, a 46 px toggle with the title in 600 14 and the `description` inline after it in the mono meta ink, and the content flush to the card's edges, for a `reference attached` DataTable (web/Android). On iOS the default Collapsible already renders as the inset-grouped card, so `reference` changes nothing there.","default":"false"},{"name":"children","type":"ReactNode","required":true,"description":"The collapsible content. A string renders in the skin's content type; a ReactNode renders as-is."},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Pair with `onOpenChange`. Omit for uncontrolled.","default":"false"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Called with the next open state whenever the header toggles."},{"name":"defaultOpen","type":"boolean | undefined","required":false,"description":"Initial open state for the uncontrolled case (read once, default false).","default":"false"},{"name":"disabled","type":"boolean | undefined","required":false,"description":"A disabled header does not toggle and reads dimmed.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"A single disclosure: one header (its `title`, or a custom `trigger`, plus a chevron that rotates when open) over one collapsible content panel.\n\nClosed by default; pass `defaultOpen` to start open. Open state is controlled (`open` + `onOpenChange`) or uncontrolled (`defaultOpen`). A `description` adds a muted secondary line under the title;\n`card` wraps the disclosure in an outlined card surface on web and Android (on iOS the default look already is the inset-grouped card, so `card` is a no-op there).\nFor a set of related, peer sections, reach for an Accordion (a group of these); Collapsible is the standalone primitive.","ios":"A single disclosure: one header (its `title`, or a custom `trigger`, plus a chevron that rotates when open) over one collapsible content panel.\n\nClosed by default; pass `defaultOpen` to start open. Open state is controlled (`open` + `onOpenChange`) or uncontrolled (`defaultOpen`). A `description` adds a muted secondary line under the title;\non iOS the default look already is the inset-grouped card, so `card` is a no-op there.\nFor a set of related, peer sections, reach for an Accordion (a group of these); Collapsible is the standalone primitive.","android":"A single disclosure: one header (its `title`, or a custom `trigger`, plus a chevron that rotates when open) over one collapsible content panel.\n\nClosed by default; pass `defaultOpen` to start open. Open state is controlled (`open` + `onOpenChange`) or uncontrolled (`defaultOpen`). A `description` adds a muted secondary line under the title;\n`card` wraps the disclosure in an outlined card surface.\nFor a set of related, peer sections, reach for an Accordion (a group of these); Collapsible is the standalone primitive."}},{"slug":"command","name":"Command","category":"organisms","description":"Cmd+K search: navigation, actions, recent items.","source":"src/organisms/command/command.md","url":"https://canvas.nannier.com/ai/4.2.0/components/command.md","humanUrl":"https://canvas.nannier.com/components/command","exports":["Command","CommandGroup","CommandItem","CommandProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"CommandProps","props":[{"name":"placeholder","type":"string | undefined","required":false,"description":"Prompt shown in the empty search input.","default":"\"Search commands...\""},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible purpose for the search input and result list. Defaults to the search placeholder. Supply this when the placeholder does not explain the task."},{"name":"query","type":"string | undefined","required":false,"description":"The text typed into the search input (CONTROLLED). Filters the rows to the labels matching it (case-insensitive). Omit and use `defaultQuery` for uncontrolled use: a bare Command is searchable out of the box."},{"name":"defaultQuery","type":"string | undefined","required":false,"description":"Initial query for uncontrolled use."},{"name":"onQueryChange","type":"((query: string) => void) | undefined","required":false,"description":"Fired with the new query on each keystroke (both modes)."},{"name":"groups","type":"CommandGroup[] | undefined","required":false,"description":"Grouped result rows."},{"name":"filtered","type":"boolean | undefined","required":false,"description":"Groups are already filtered and ranked by the owner; preserve their order and contents.","default":"false"},{"name":"embedded","type":"boolean | undefined","required":false,"description":"Fill the parent and inherit its surface, for composition inside a Dialog or Drawer. Ignored with trigger.","default":"false"},{"name":"autoFocus","type":"boolean | undefined","required":false,"description":"Focus the inline search field after mounting, allowing the containing overlay to capture its opener first.","default":"false"},{"name":"onKeyPress","type":"((e: TextInputKeyPressEvent) => void) | undefined","required":false,"description":"Input keyboard handler, called before built-in navigation. preventDefault cancels built-in handling."},{"name":"emptyMessage","type":"string | undefined","required":false,"description":"Content shown when there are no result rows, including an empty query."},{"name":"active","type":"number | undefined","required":false,"description":"Flat index of the highlighted row (CONTROLLED), counted across the visible (query-matching) rows. Omit for uncontrolled use."},{"name":"defaultActive","type":"number | undefined","required":false,"description":"Initial highlighted row for uncontrolled use (hovering a row moves it, typing resets it to the first match)."},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Omit for uncontrolled (the search trigger toggles it).","default":"false"},{"name":"defaultOpen","type":"boolean | undefined","required":false,"description":"Render the palette open initially for uncontrolled use (selecting a row closes it).","default":"false"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes."},{"name":"trigger","type":"boolean | undefined","required":false,"description":"Render a collapsed full-width search trigger above the palette (a search glyph + \"Search...\" + a trailing kbd cap). The palette card still renders inline below the trigger (gated by `open`), mirroring how Dropdown shows its trigger plus the open menu in the docs.","default":"false"},{"name":"footer","type":"boolean | undefined","required":false,"description":"Append a footer hint bar below the list (↑ ↓ to navigate, ↵ to select, esc to close).","default":"false"},{"name":"onSelect","type":"((item: CommandItem, index: number) => void) | undefined","required":false,"description":"Called with the chosen item and its flat index (within the visible, query-matching rows) when a row is pressed."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element; the scrolling results list gets `${testID}-results`."},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"Cmd+K search: navigation, actions, recent items.\n\nThe search row is a real input: typing filters the grouped rows to the matching\nlabels, and a query that matches nothing shows a muted \"No results\" row.\n\nOn every platform the palette is the v4 card: 520 wide at an 18-pixel corner, a 48-pixel\nsearch row with an `esc` cap over a hairline,\nmono eyebrows over 38-pixel rows (44 on\niOS, 48 on Android) with quiet icons\nand mono shortcuts, the accent's soft wash under the\nactive row, and an optional footer of mono hints.\nNeither iOS nor Android ships a\ncommand palette, so both take this look in their own face.\n\nIn glass mode the triggered palette is a functional-layer glass card under the\nsearch bar, with its own search field; the search editor keeps focus while typing\nfilters the rows. Solid mode paints the skin's own palette.\n\nThe search placeholder names the input and its result list. Supply `accessibilityLabel` when a more specific purpose is needed. `defaultActive={-1}` starts without a highlighted result: Enter selects nothing until navigation or hovering chooses a row. Either arrow key starts at the first result from this state. Controlled indices above the visible result count clamp to the last match; negative, fractional and non-finite indices leave no active result.\n\nUse `filtered` when a search service or index supplies ranked groups; Command keeps\nthose rows and their order instead of filtering their labels again. An item's\n`description` supplies its secondary text. `emptyMessage` provides both the initial\nprompt and the no-match message.\n\nUse `embedded` inside a `Dialog` or `Drawer` to inherit its surface and fill its\nbounds. It has no effect when `trigger` is set. Long results scroll within the\npalette. `autoFocus` focuses the inline field after the containing overlay captures\nits opener, so closing restores the original control. `onKeyPress` runs before\nbuilt-in navigation; call `preventDefault()` to handle an application shortcut.","ios":"Cmd+K search: navigation, actions, recent items.\n\nThe search row is a real input: typing filters the grouped rows to the matching\nlabels, and a query that matches nothing shows a muted \"No results\" row.\n\nOn every platform the palette is the v4 card: 520 wide at an 18-pixel corner, a 48-pixel\nsearch row with an `esc` cap over a hairline,\nmono eyebrows over 38-pixel rows (44 on iOS) with quiet icons\nand mono shortcuts, the accent's soft wash under the\nactive row, and an optional footer of mono hints.\niOS ships no command palette, so it takes this look in its own face.\n\nIn glass mode the triggered palette is a functional-layer glass card under the\nsearch bar, with its own search field; the search editor keeps focus while typing\nfilters the rows. Solid mode paints the skin's own palette.\n\nThe search placeholder names the input and its result list. Supply `accessibilityLabel` when a more specific purpose is needed. `defaultActive={-1}` starts without a highlighted result: Enter selects nothing until navigation or hovering chooses a row. Either arrow key starts at the first result from this state. Controlled indices above the visible result count clamp to the last match; negative, fractional and non-finite indices leave no active result.\n\nUse `filtered` when a search service or index supplies ranked groups; Command keeps\nthose rows and their order instead of filtering their labels again. An item's\n`description` supplies its secondary text. `emptyMessage` provides both the initial\nprompt and the no-match message.\n\nUse `embedded` inside a `Dialog` or `Drawer` to inherit its surface and fill its\nbounds. It has no effect when `trigger` is set. Long results scroll within the\npalette. `autoFocus` focuses the inline field after the containing overlay captures\nits opener, so closing restores the original control. `onKeyPress` runs before\nbuilt-in navigation; call `preventDefault()` to handle an application shortcut.","android":"Cmd+K search: navigation, actions, recent items.\n\nThe search row is a real input: typing filters the grouped rows to the matching\nlabels, and a query that matches nothing shows a muted \"No results\" row.\n\nOn every platform the palette is the v4 card: 520 wide at an 18-pixel corner, a 48-pixel\nsearch row with an `esc` cap over a hairline,\nmono eyebrows over 38-pixel rows (48 on Android) with quiet icons\nand mono shortcuts, the accent's soft wash under the\nactive row, and an optional footer of mono hints.\nAndroid ships no command palette, so it takes this look in its own face.\n\nIn glass mode the triggered palette is a functional-layer glass card under the\nsearch bar, with its own search field; the search editor keeps focus while typing\nfilters the rows. Solid mode paints the skin's own palette.\n\nThe search placeholder names the input and its result list. Supply `accessibilityLabel` when a more specific purpose is needed. `defaultActive={-1}` starts without a highlighted result: Enter selects nothing until navigation or hovering chooses a row. Either arrow key starts at the first result from this state. Controlled indices above the visible result count clamp to the last match; negative, fractional and non-finite indices leave no active result.\n\nUse `filtered` when a search service or index supplies ranked groups; Command keeps\nthose rows and their order instead of filtering their labels again. An item's\n`description` supplies its secondary text. `emptyMessage` provides both the initial\nprompt and the no-match message.\n\nUse `embedded` inside a `Dialog` or `Drawer` to inherit its surface and fill its\nbounds. It has no effect when `trigger` is set. Long results scroll within the\npalette. `autoFocus` focuses the inline field after the containing overlay captures\nits opener, so closing restores the original control. `onKeyPress` runs before\nbuilt-in navigation; call `preventDefault()` to handle an application shortcut."}},{"slug":"composed-chart","name":"ComposedChart","category":"charts","description":"Bars, lines, and gradient-washed areas sharing one categorical axis: each series picks its mark with a `line` or `area` boolean (bars by default; precedence line > area > bars).","source":"src/charts/composed-chart/composed-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/composed-chart.md","humanUrl":"https://canvas.nannier.com/components/composed-chart","exports":["ComposedChart","ComposedChartProps","ComposedSeries"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ComposedChartProps","props":[{"name":"series","type":"ComposedSeries[]","required":true,"description":"The series to plot; each picks its mark (bars by default, `line`, or `area`)."},{"name":"dots","type":"boolean | undefined","required":false,"description":"Mark each line/area datum with a dot (auto-suppressed when bands are under 14px).","default":"false"},{"name":"labels","type":"string[]","required":true,"description":"Category labels along the x axis, one per data column."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"max","type":"number | undefined","required":false,"description":"Y-axis maximum override. Defaults to a nice bound above the data max."},{"name":"min","type":"number | undefined","required":false,"description":"Y-axis minimum override. Defaults to 0 (or the data min when negative)."},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (single-series only; pick one; default is the primary fill).","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (single-series only; pick one; default is the primary fill).","default":"false","group":0},{"name":"curved","type":"boolean | undefined","required":false,"description":"Curve (omit for straight segments).","default":"false","group":1},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":2},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":2},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"hideAxes","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats tick labels and accessible values (data formatting, not styling).","group":3},{"name":"selected","type":"number | null | undefined","required":false,"description":"Scrub-to-inspect: the selected category index (controlled). Pass null for none.","group":3},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Scrub-to-inspect: the initially selected category (uncontrolled).","group":3},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press/scrub selects a category (or clears it with null).","group":3},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":3},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":3}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (single-series only; pick one; default is the primary fill)."},{"title":"Curve","pickOne":false,"note":"Curve (omit for straight segments)."},{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."},{"title":"Furniture visibility","pickOne":false}],"inherits":["Omit<CartesianSeriesProps, \"series\">"]}],"platformNotes":{"web":"Bars, lines, and gradient-washed areas sharing one categorical axis: each series picks its mark with a `line` or `area` boolean (bars by default; precedence line > area > bars).\n\nThe classic \"revenue bars with a margin line\" chart, on one shared zero-based y axis, with the same scrub-to-inspect, legend, and accessible-name contract as the other cartesian charts. For bar-only grouped data, reach for the bar `Chart`'s grouped mode instead; composed earns its keep when the marks mix.","ios":"Bars, lines, and gradient-washed areas sharing one categorical axis: each series picks its mark with a `line` or `area` boolean (bars by default; precedence line > area > bars).\n\nThe classic \"revenue bars with a margin line\" chart, on one shared zero-based y axis, with the same scrub-to-inspect, legend, and accessible-name contract as the other cartesian charts. For bar-only grouped data, reach for the bar `Chart`'s grouped mode instead; composed earns its keep when the marks mix.","android":"Bars, lines, and gradient-washed areas sharing one categorical axis: each series picks its mark with a `line` or `area` boolean (bars by default; precedence line > area > bars).\n\nThe classic \"revenue bars with a margin line\" chart, on one shared zero-based y axis, with the same scrub-to-inspect, legend, and accessible-name contract as the other cartesian charts. For bar-only grouped data, reach for the bar `Chart`'s grouped mode instead; composed earns its keep when the marks mix."}},{"slug":"container","name":"Container","category":"atoms","description":"The bounds provider. A Canvas component never dictates its own width: `Container` conforms to its parent (full width, no cap) by default, and a named step of the shared width scale (`xxxs` 192 through `page` 1280) caps and centers it, so the reading measure of a form, an article, or a card stack is a step you can name instead of a width invented at the call site.","source":"src/atoms/container/container.md","url":"https://canvas.nannier.com/ai/4.2.0/components/container.md","humanUrl":"https://canvas.nannier.com/components/container","exports":["Container","ContainerProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ContainerProps","props":[{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"fluid","type":"boolean | undefined","required":false,"description":"No cap, the default: the container spans its parent. Explicit `fluid` wins over every step when several are passed.","default":"false"},{"name":"padTight","type":"boolean | undefined","required":false,"description":"Gutters: horizontal padding (pick one; omit for none).","default":"false","group":0},{"name":"pad","type":"boolean | undefined","required":false,"description":"Gutters: horizontal padding (pick one; omit for none).","default":"false","group":0},{"name":"padLoose","type":"boolean | undefined","required":false,"description":"Gutters: horizontal padding (pick one; omit for none).","default":"false","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Layout containers are the exception to the no-sizing rule: for composition inside an app frame only (a `flex` in a screen shell), never a restyle hook.","group":0},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":1}],"groups":[{"title":"Gutters","pickOne":true,"note":"Gutters: horizontal padding (pick one; omit for none)."},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"The bounds provider. A Canvas component never dictates its own width:\n`Container` conforms to its parent (full width, no cap) by default, and a named\nstep of the shared width scale (`xxxs` 192 through `page` 1280) caps and centers\nit, so the reading measure of a form, an article, or a card stack is a step you\ncan name instead of a width invented at the call site.\n\nA component fills the parent it is given (a field, a card, a table) or hugs its\ncontent (a button, a badge), and the nearest layout container provides the\nbounds. `Container` is the layout container whose job is a MEASURE, and by\ndefault the parent is the conformance factor. A cap is fluid: inside anything\nnarrower than the step the container simply fills its parent, which is all a\nphone screen is. `start` pins a capped box to the leading edge instead of\ncentering it, and `padTight` / `pad` / `padLoose` add horizontal gutters from\nRow and Column's own padding scale.\n\nThe step booleans and `start` are the kit's measure axis, and the fields, Field,\nForm, Button, and ButtonGroup carry it too: `<Input sm start>` says exactly what\n`<Container sm start>` around it says, a cap at the step and fluid below it. Reach\nfor Container when the measure belongs to a group (a form, an article, a card\nstack) rather than to one component.","ios":"The bounds provider. A Canvas component never dictates its own width:\n`Container` conforms to its parent (full width, no cap) by default, and a named\nstep of the shared width scale (`xxxs` 192 through `page` 1280) caps and centers\nit, so the reading measure of a form, an article, or a card stack is a step you\ncan name instead of a width invented at the call site.\n\nA component fills the parent it is given (a field, a card, a table) or hugs its\ncontent (a button, a badge), and the nearest layout container provides the\nbounds. `Container` is the layout container whose job is a MEASURE, and by\ndefault the parent is the conformance factor. A cap is fluid: inside anything\nnarrower than the step the container simply fills its parent, which is all a\nphone screen is. `start` pins a capped box to the leading edge instead of\ncentering it, and `padTight` / `pad` / `padLoose` add horizontal gutters from\nRow and Column's own padding scale.\n\nThe step booleans and `start` are the kit's measure axis, and the fields, Field,\nForm, Button, and ButtonGroup carry it too: `<Input sm start>` says exactly what\n`<Container sm start>` around it says, a cap at the step and fluid below it. Reach\nfor Container when the measure belongs to a group (a form, an article, a card\nstack) rather than to one component.","android":"The bounds provider. A Canvas component never dictates its own width:\n`Container` conforms to its parent (full width, no cap) by default, and a named\nstep of the shared width scale (`xxxs` 192 through `page` 1280) caps and centers\nit, so the reading measure of a form, an article, or a card stack is a step you\ncan name instead of a width invented at the call site.\n\nA component fills the parent it is given (a field, a card, a table) or hugs its\ncontent (a button, a badge), and the nearest layout container provides the\nbounds. `Container` is the layout container whose job is a MEASURE, and by\ndefault the parent is the conformance factor. A cap is fluid: inside anything\nnarrower than the step the container simply fills its parent, which is all a\nphone screen is. `start` pins a capped box to the leading edge instead of\ncentering it, and `padTight` / `pad` / `padLoose` add horizontal gutters from\nRow and Column's own padding scale.\n\nThe step booleans and `start` are the kit's measure axis, and the fields, Field,\nForm, Button, and ButtonGroup carry it too: `<Input sm start>` says exactly what\n`<Container sm start>` around it says, a cap at the step and fluid below it. Reach\nfor Container when the measure belongs to a group (a form, an article, a card\nstack) rather than to one component."}},{"slug":"dashboard-grid","name":"DashboardGrid","category":"organisms","description":"A 12-column widget board for overview screens. Each widget declares a span in twelfths, and the grid measures its OWN width (never the window) to pick a tier: a wide container honors every span, a narrower one reflows widgets to their `narrowSpan`, and a phone-sized one stacks them full width.","source":"src/organisms/dashboard-grid/dashboard-grid.md","url":"https://canvas.nannier.com/ai/4.2.0/components/dashboard-grid.md","humanUrl":"https://canvas.nannier.com/components/dashboard-grid","exports":["DashboardGrid","DashboardGridProps","DashboardWidget","clearStoredDashboardOrder"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"DashboardGridProps","props":[{"name":"items","type":"DashboardWidget[] | undefined","required":false,"description":"The widgets to lay out, and the canonical collection prop. Their array order is the fallback order: any widget whose id is missing from the active order is appended, so adding one to a release never breaks a saved layout."},{"name":"order","type":"string[] | undefined","required":false,"description":"CONTROLLED widget order, as ids. The primary path: the consuming app owns the array and persists it through its own API, applying each `onOrderChange`. Ids the widget list does not hold are ignored, and widgets missing from it are appended, so a stored order survives a release that adds or drops a widget."},{"name":"defaultOrder","type":"string[] | undefined","required":false,"description":"Initial order for UNCONTROLLED use; the grid then applies each drop itself. Defaults to the `items` array order."},{"name":"onOrderChange","type":"((order: string[]) => void) | undefined","required":false,"description":"Fired with the full, reconciled next order after every drop that changes it, in BOTH the controlled and the uncontrolled mode."},{"name":"unlocked","type":"boolean | undefined","required":false,"description":"Customize mode: cells gain the edit affordance and a drag grip, and the board becomes reorderable. The grid never flips this itself; the app owns the \"Done\" / \"Customize\" control. Locked (the default) the drag provider is not mounted at all.","default":"false"},{"name":"storageKey","type":"string | undefined","required":false,"description":"Web-only convenience for the UNCONTROLLED path: seed the initial order from browser storage under this key and write each drop back to it. Ignored when `order` is passed (the controlled order owns persistence). On native there is no storage, so the order is session-only there; `clearStoredDashboardOrder` forgets a saved layout. A server-rendered board renders `defaultOrder` first and adopts the saved layout in the commit right after hydration, so React always hydrates against the markup the server actually sent."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density axis (pass none for the default density).","default":"false","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook.","group":0}],"groups":[{"title":"Density axis","pickOne":false,"note":"Density axis (pass none for the default density)."}],"inherits":[]}],"platformNotes":{"web":"A 12-column widget board for overview screens. Each widget declares a span in twelfths, and the grid measures its OWN width (never the window) to pick a tier: a wide container honors every span, a narrower one reflows widgets to their `narrowSpan`, and a phone-sized one stacks them full width.\n\nCells render bare, because a widget arrives with its own surface (a Card, a Chart, a Stats row) and a second frame around it would only double up. A widget's `title` is its accessible name rather than a header the grid paints: customize mode uses it to name the widget's drag grip and its drop zone.\n\nLocked, it is a plain static grid and no drag machinery is mounted at all; `unlocked` turns on customize mode, where every cell gains a grip and the board reorders by pointer, keyboard, or screen reader through the kit's own drag-and-drop. The order is a plain array of ids, controlled through `order` and `onOrderChange` so the app can persist it, or left to the grid with `defaultOrder`.\n\nThe board takes its widgets through `items`, the collection prop every other collection-taking component in the kit uses.","ios":"A 12-column widget board for overview screens. Each widget declares a span in twelfths, and the grid measures its OWN width (never the window) to pick a tier: a wide container honors every span, a narrower one reflows widgets to their `narrowSpan`, and a phone-sized one stacks them full width.\n\nCells render bare, because a widget arrives with its own surface (a Card, a Chart, a Stats row) and a second frame around it would only double up. A widget's `title` is its accessible name rather than a header the grid paints: customize mode uses it to name the widget's drag grip and its drop zone.\n\nLocked, it is a plain static grid and no drag machinery is mounted at all; `unlocked` turns on customize mode, where every cell gains a grip and the board reorders by pointer, keyboard, or screen reader through the kit's own drag-and-drop. The order is a plain array of ids, controlled through `order` and `onOrderChange` so the app can persist it, or left to the grid with `defaultOrder`.\n\nThe board takes its widgets through `items`, the collection prop every other collection-taking component in the kit uses.","android":"A 12-column widget board for overview screens. Each widget declares a span in twelfths, and the grid measures its OWN width (never the window) to pick a tier: a wide container honors every span, a narrower one reflows widgets to their `narrowSpan`, and a phone-sized one stacks them full width.\n\nCells render bare, because a widget arrives with its own surface (a Card, a Chart, a Stats row) and a second frame around it would only double up. A widget's `title` is its accessible name rather than a header the grid paints: customize mode uses it to name the widget's drag grip and its drop zone.\n\nLocked, it is a plain static grid and no drag machinery is mounted at all; `unlocked` turns on customize mode, where every cell gains a grip and the board reorders by pointer, keyboard, or screen reader through the kit's own drag-and-drop. The order is a plain array of ids, controlled through `order` and `onOrderChange` so the app can persist it, or left to the grid with `defaultOrder`.\n\nThe board takes its widgets through `items`, the collection prop every other collection-taking component in the kit uses."}},{"slug":"data-table","name":"DataTable","category":"organisms","description":"A data table rendered from column and row data, with sorting, row selection, pagination, and the loading and empty states built in.","source":"src/organisms/data-table/data-table.md","url":"https://canvas.nannier.com/ai/4.2.0/components/data-table.md","humanUrl":"https://canvas.nannier.com/components/data-table","exports":["DataTable","DataTableColumn","DataTableGroup","DataTableProps","DataTableSort"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"DataTableProps","props":[{"name":"columns","type":"(string | DataTableColumn)[]","required":true,"description":"Columns: a header label per column, or a `DataTableColumn` descriptor for per-column alignment (`numeric`/`centered`), a fixed `width`, and sorting (`sortable`, `sortValue`). Strings and descriptors mix freely. Treat the array and descriptors as immutable: replace both when a column changes."},{"name":"rows","type":"ReactNode[][] | undefined","required":false,"description":"Row data: an array of rows, each an array of cells (one per column). A cell is a string (rendered in the default cell type) or any ReactNode for a custom cell, such as a link, a `Badge`, or a monospace name (rendered directly). Treat this data as immutable: replace the outer array and each changed row when data changes, so cached sorting and pagination update correctly."},{"name":"groups","type":"DataTableGroup[] | undefined","required":false,"description":"Group the rows under titled bands (the props table's \"Intent\", \"Size\" and \"State\" groups): each group draws a band spanning every column, its label, an optional adornment and an optional count on the sunken fill, then its own rows. Given `groups`, the table's rows are the groups' rows in order and `rows` is ignored; every row index a callback reports (`onRowPress`, `onRowEdit`, `rowKey` and the rest) counts through them in that order. Sorting reorders rows within their group and never moves a group; paging pages the rows, and each page draws the band of every group it shows. A group with no rows draws no band."},{"name":"striped","type":"boolean | undefined","required":false,"description":"Tint every other data row for easier horizontal scanning.","default":"false"},{"name":"bordered","type":"boolean | undefined","required":false,"description":"Draw the table's frame on the firmer field boundary rather than the hairline.","default":"false"},{"name":"attached","type":"boolean | undefined","required":false,"description":"The table sits flush inside a frame its parent draws (a `flush` Card, a bordered panel that clips to its corners), so it draws no frame of its own. Without it a standalone table frames itself (on the web and Android, a hairline at the table corner over the card fill), which is the standalone look.","default":"false"},{"name":"stacks","type":"boolean | undefined","required":false,"description":"Responsive: when the table's own CONTAINER is at or below `stackBreakpoint` (default `sm` = 640), each row lays its cells out top to bottom at the full width instead of side by side, so long text reads at the width of the table rather than a column's share of it. The first cell leads the row as its title; every later cell carries its column label above its value. The header row is drawn only while it holds a control (a sortable column, or the box that selects every row), as a band of its labels that wraps; the selection box and the row actions stay at the row's leading and trailing edges. A stacked table never pans, and on iOS it stacks instead of collapsing to its first column. Container-measured with a viewport seed for the first frame, like Row `stacks`; crossing the breakpoint changes the layout only.","default":"false"},{"name":"stackBreakpoint","type":"BreakpointKey | undefined","required":false,"description":"The breakpoint at and below which `stacks` stacks the rows (default `\"sm\"`). Only meaningful with `stacks` (DEV warns without it)."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Tighter vertical padding on header and data cells.","default":"false","group":0},{"name":"comfortable","type":"boolean | undefined","required":false,"description":"Looser vertical padding on header and data cells.","default":"false","group":0},{"name":"reference","type":"boolean | undefined","required":false,"description":"The reference sheet (a component page's props table): the column headings as the page's small uppercase mono label on a header row with no fill of its own, 12 px above and below whatever the density; rows 10 px above and below with a rule above each; the columns 16 px apart and 16 px in from the frame's sides; and the frame at the panel corner on the `border` hairline over the card fill, so `bordered` only firms the hairline and `attached` still drops the frame. On iOS the table keeps its own look and this changes nothing.","default":"false","group":0},{"name":"bare","type":"boolean | undefined","required":false,"description":"The bare hairline table: no frame and no fill, a `field-border` rule under the headings (the reference sheet's mono uppercase label) and a `border` rule under every row, the first column flush with the table's start, each cell keeping 12 px clear at its end inside its column's width, and 12 px above and below whatever the density. `reference` wins over it. On iOS the table keeps its own look and this changes nothing.","default":"false","group":0},{"name":"matrix","type":"boolean | undefined","required":false,"description":"The specimen matrix (a section page's states grid): no frame, no fill and no rules, the headings as the page's small uppercase mono label in the third ink, the cells unpadded, the rows 12 px apart and the columns 20 px apart. Pair it with `fit` columns for the hand-off's content-sized tracks. `reference` and `bare` win over it. On iOS the table keeps its own look and this changes nothing.","default":"false","group":0},{"name":"alignTop","type":"boolean | undefined","required":false,"description":"Align every cell to the top of its row rather than its middle, so a row whose description wraps keeps its name, type and default beside the description's first line. The selection box and the row actions center on that first line, as they do in a stacked row.","default":"false","group":0},{"name":"footer","type":"ReactNode","required":false,"description":"A row drawn inside the table's frame under the last row (and under the pagination bar when `paginated`): 44 px tall with its content centered, for a \"Show all\" control or a note. A hairline separates it from what sits above it: the one the last row draws already, or its own where nothing above it draws one.","group":0},{"name":"sortable","type":"boolean | undefined","required":false,"description":"Make every column sortable: pressing a header cycles ascending, descending, off. A column descriptor opts back out with `sortable: false`. Sorting is self-managed out of the box; control it via `sort`/`onSortChange`.","default":"false","group":0},{"name":"sort","type":"DataTableSort | null | undefined","required":false,"description":"Controlled sort state (`null` = unsorted). Omit for uncontrolled use.","group":0},{"name":"defaultSort","type":"DataTableSort | null | undefined","required":false,"description":"Initial sort for uncontrolled use.","group":0},{"name":"onSortChange","type":"((sort: DataTableSort | null) => void) | undefined","required":false,"description":"Fired with the next sort (or `null` when cleared) on header press.","group":0},{"name":"selectable","type":"boolean | undefined","required":false,"description":"Row selection: a leading checkbox column with a select-all header checkbox (indeterminate on a partial selection). Selection is keyed by `rowKey` (the row's original index when omitted) and self-managed out of the box; control it via `selectedKeys`/`onSelectionChange`. When no `onRowPress` is set, pressing anywhere on a row toggles it.","default":"false","group":0},{"name":"selectedKeys","type":"(string | number)[] | undefined","required":false,"description":"Controlled selected row keys. Omit for uncontrolled use.","group":0},{"name":"defaultSelectedKeys","type":"(string | number)[] | undefined","required":false,"description":"Initial selected row keys for uncontrolled use.","group":0},{"name":"onSelectionChange","type":"((keys: Array<string | number>) => void) | undefined","required":false,"description":"Fired with the next selected keys when a row or the select-all is toggled.","group":0},{"name":"paginated","type":"boolean | undefined","required":false,"description":"Page the rows through a built-in footer (the kit Pagination): a \"Showing X-Y of N\" range with Prev/Next, plus the selection count when `selectable`. Sorting applies before paging. Self-managed out of the box; control the page via `page`/`onPageChange`.","default":"false","group":0},{"name":"pageSize","type":"number | undefined","required":false,"description":"Rows per page (CONTROLLED; default 10, or the first of `pageSizes`).","group":0},{"name":"defaultPageSize","type":"number | undefined","required":false,"description":"Initial rows per page for uncontrolled use.","group":0},{"name":"pageSizes","type":"number[] | undefined","required":false,"description":"Selectable rows-per-page values. Supplying them upgrades the footer to the Pagination `withSize` variant (a \"Rows per page\" selector).","group":0},{"name":"onPageSizeChange","type":"((size: number) => void) | undefined","required":false,"description":"Fired with the next rows-per-page value when the footer selector changes it.","group":0},{"name":"page","type":"number | undefined","required":false,"description":"Current page, 1-based (CONTROLLED). Omit for uncontrolled use.","group":0},{"name":"defaultPage","type":"number | undefined","required":false,"description":"Initial page for uncontrolled use.","group":0},{"name":"onPageChange","type":"((page: number) => void) | undefined","required":false,"description":"Fired with the next 1-based page when the footer pagination navigates.","group":0},{"name":"loading","type":"boolean | undefined","required":false,"description":"Loading state: the body renders pulsing skeleton placeholder rows (one per would-be row on the page) instead of data.","default":"false","group":0},{"name":"emptyMessage","type":"ReactNode","required":false,"description":"What to render, centered under the header, when `rows` is empty (and not `loading`). A string gets the muted caption type; any ReactNode renders as given (an `EmptyState`, a retry Button). Omitted = just the header row, as before.","group":0},{"name":"onRowPress","type":"((row: ReactNode[], index: number) => void) | undefined","required":false,"description":"When set, each data row is pressable, reporting the row data and its index in `rows`. A press anywhere on the row acts; the keyboard and screen-reader path is a button inside the row's FIRST column, named from the row's plain text cells (or, when it has none, by that cell's own content). The row itself stays a `row`, so keep your own controls out of the first column here: a control there would nest inside the activator.","group":0},{"name":"onRowEdit","type":"((rowIndex: number) => void) | undefined","required":false,"description":"Row editing: passing this adds a trailing actions column with a pencil button per row. Pressing the pencil opens the row's edit mode (its string cells become fields with a trailing Save/Cancel pair) and fires this with the row's original index in `rows`. Save reports the edited cells through `onRowCommit`; Cancel (or Escape in a field) closes without committing.","group":0},{"name":"onRowDelete","type":"((rowIndex: number) => void) | undefined","required":false,"description":"Row deletion: passing this adds a delete (bin) button to the trailing actions column. Delete is second-press confirm: the first press ARMS it (the bin turns destructive and its accessible name says confirm), a second press within the confirm window fires this with the row's original index, and pressing anywhere else in the table (or the window lapsing) disarms.","group":0},{"name":"inlineEdit","type":"boolean | undefined","required":false,"description":"Let string cells be edited in place: pressing one swaps it to a field. Enter or blur commits through `onCellCommit`; Escape restores the cell. Custom ReactNode cells (badges, links) are not editable.","default":"false","group":0},{"name":"onCellCommit","type":"((rowIndex: number, colIndex: number, next: string) => void) | undefined","required":false,"description":"Fired when an `inlineEdit` cell commits (Enter or blur) with a changed value: the row's original index in `rows`, the column index, and the next text. Data stays yours: re-render with updated `rows` to keep the edit.","group":0},{"name":"onRowCommit","type":"((rowIndex: number, cells: ReactNode[]) => void) | undefined","required":false,"description":"Fired when a pencil-opened row edit is saved: the row's original index in `rows` and the full cells array with the edited strings in place (custom ReactNode cells pass through unchanged).","group":0},{"name":"virtualized","type":"boolean | undefined","required":false,"description":"Render the data rows through a windowed `FlatList` instead of mounting every row up front, for large tables. The header row stays fixed above it. Give the table a bounded height (via `style`, e.g. `{ maxHeight: 400 }`) so the body can scroll; without one it warns and renders eagerly. Default mounts all rows.","default":"false","group":0},{"name":"rowKey","type":"((row: ReactNode[], index: number) => string | number) | undefined","required":false,"description":"Stable key for a row, derived from the row data and its index in `rows`. Selection is keyed by it, and it keeps React row identity stable when rows reorder (sorting, live data) and a cell is a stateful custom ReactNode. When omitted, rows key off their original array index (safe for string/number cells and stateless custom cells; selection then tracks row POSITIONS, so supply a real key when the data itself can be reordered, inserted, or deleted). Keep this function pure; replace its identity when external data changes how keys are derived, so the cached selection summary updates.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Density","pickOne":true,"note":"Density (pick one; default is the regular row height)."}],"inherits":[]}],"platformNotes":{"web":"A data table rendered from column and row data, with sorting, row selection,\npagination, and the loading and empty states built in.\n\nColumns are plain header labels or descriptors (`{ label, numeric, width,\nsortable, ... }`) for per-column alignment, fixed widths, and sorting; compose a\ntoolbar above when the screen needs one. Density tweaks affect padding live.\nPass `onRowEdit` / `onRowDelete` for a trailing actions column: the pencil opens\nthe row's string cells as fields with Save/Cancel (committing via\n`onRowCommit`), and Delete asks for a confirming second press before it fires.\n`inlineEdit` skips the pencil and lets a string cell be pressed straight into a\nfield, committing via `onCellCommit`. `onRowPress` makes the whole row act on\npress and puts the keyboard and screen-reader path on a button in the row's\nfirst column, so keep your own controls out of that column when you use it. Data\nstays yours either way: the table reports intent and re-renders whatever rows it\nis handed back.\n\nTreat `rows` and `columns` as immutable inputs. When editing data, replace the outer `rows` array and each changed row, as the examples below do. When changing a column, replace its descriptor and the `columns` array. Keep unchanged arrays and callbacks stable for large tables: Canvas caches sorting, paging, and selection summaries so typing a draft or opening a row action does not process the whole data set again. `sortValue` and `rowKey` must be pure functions of their inputs. If either closes over changing external data, supply a new callback identity; for `sortValue`, also replace its column descriptor and the `columns` array. A saved edit appears in sorted order when the updated `rows` arrive.\n\nOn narrow web and Android layouts, the columns still share the table width and\nwrap their text, each keeping a 110 px minimum (a column with a fixed `width`\nkeeps that width), and they pan horizontally only when those minimums exceed\nthe table width. A long cell wraps inside its column rather than widening the\ntable. The overflowing scrollport is a keyboard tab stop, so the\nplatform's arrow keys can reveal the remaining columns, and while it has keyboard\nfocus the table's surface draws the theme's focus ring. A table that fits adds\nno scrolling tab stop, and on Android it takes no sideways drag either, so a tap\nthat drifts sideways still presses its row and a swipe that starts across it\nscrolls the page (while TalkBack explores by touch the scroller stays enabled, so\nthe exploring finger reaches every cell). On an iPhone-width table iOS shows only\nthe first column instead, as SwiftUI Table does. A table that passes `stacks`\ndoes neither: at that width each row stacks its cells (see Stacked below).\nOn the web and Android, and for a table that stacks on any platform, crossing\nthat width changes the layout only: rows, custom cells, an open editor with its\ntext and focus, and a windowed body's scroll position stay as they are when a\nwindow is resized across it or a phone measures the table on its first frame.\nThe iOS first-column layout is the exception: below that width the columns\nafter the first leave the table, with any editor or custom cell in them, and\nmount again when it widens.\n\nA `virtualized` table's body scrolls its rows under the fixed header. On the\nweb, while those rows overflow, the body is a keyboard tab stop of its own\n(after the column scroller when a narrow table pans, and before the rows'\ncontrols when they have any), the keyboard can scroll it, and while it has\nkeyboard focus the table's surface draws the same focus ring. The body is the\ntable's row group, so the rows it renders stay inside the table for a screen\nreader rather than behind an unnamed focusable node.","ios":"A data table rendered from column and row data, with sorting, row selection,\npagination, and the loading and empty states built in.\n\nColumns are plain header labels or descriptors (`{ label, numeric, width,\nsortable, ... }`) for per-column alignment, fixed widths, and sorting; compose a\ntoolbar above when the screen needs one. Density tweaks affect padding live.\nPass `onRowEdit` / `onRowDelete` for a trailing actions column: the pencil opens\nthe row's string cells as fields with Save/Cancel (committing via\n`onRowCommit`), and Delete asks for a confirming second press before it fires.\n`inlineEdit` skips the pencil and lets a string cell be pressed straight into a\nfield, committing via `onCellCommit`. `onRowPress` makes the whole row act on\npress and puts the keyboard and screen-reader path on a button in the row's\nfirst column, so keep your own controls out of that column when you use it. Data\nstays yours either way: the table reports intent and re-renders whatever rows it\nis handed back.\n\nTreat `rows` and `columns` as immutable inputs. When editing data, replace the outer `rows` array and each changed row, as the examples below do. When changing a column, replace its descriptor and the `columns` array. Keep unchanged arrays and callbacks stable for large tables: Canvas caches sorting, paging, and selection summaries so typing a draft or opening a row action does not process the whole data set again. `sortValue` and `rowKey` must be pure functions of their inputs. If either closes over changing external data, supply a new callback identity; for `sortValue`, also replace its column descriptor and the `columns` array. A saved edit appears in sorted order when the updated `rows` arrive.\n\nOn an iPhone-width table iOS shows only the first column, as SwiftUI Table does. A table that passes `stacks` does not: at that width each row stacks its cells (see Stacked below). For a table that stacks, crossing that width changes the layout only: rows, custom cells, an open editor with its text and focus, and a windowed body's scroll position stay as they are when the window is resized across it or the table is measured on its first frame. The first-column layout is the exception: below that width the columns after the first leave the table, with any editor or custom cell in them, and mount again when it widens.\n\nA `virtualized` table's body scrolls its rows under the fixed header. On the\nweb, while those rows overflow, the body is a keyboard tab stop of its own\n(after the column scroller when a narrow table pans, and before the rows'\ncontrols when they have any), the keyboard can scroll it, and while it has\nkeyboard focus the table's surface draws the same focus ring. The body is the\ntable's row group, so the rows it renders stay inside the table for a screen\nreader rather than behind an unnamed focusable node.","android":"A data table rendered from column and row data, with sorting, row selection,\npagination, and the loading and empty states built in.\n\nColumns are plain header labels or descriptors (`{ label, numeric, width,\nsortable, ... }`) for per-column alignment, fixed widths, and sorting; compose a\ntoolbar above when the screen needs one. Density tweaks affect padding live.\nPass `onRowEdit` / `onRowDelete` for a trailing actions column: the pencil opens\nthe row's string cells as fields with Save/Cancel (committing via\n`onRowCommit`), and Delete asks for a confirming second press before it fires.\n`inlineEdit` skips the pencil and lets a string cell be pressed straight into a\nfield, committing via `onCellCommit`. `onRowPress` makes the whole row act on\npress and puts the keyboard and screen-reader path on a button in the row's\nfirst column, so keep your own controls out of that column when you use it. Data\nstays yours either way: the table reports intent and re-renders whatever rows it\nis handed back.\n\nTreat `rows` and `columns` as immutable inputs. When editing data, replace the outer `rows` array and each changed row, as the examples below do. When changing a column, replace its descriptor and the `columns` array. Keep unchanged arrays and callbacks stable for large tables: Canvas caches sorting, paging, and selection summaries so typing a draft or opening a row action does not process the whole data set again. `sortValue` and `rowKey` must be pure functions of their inputs. If either closes over changing external data, supply a new callback identity; for `sortValue`, also replace its column descriptor and the `columns` array. A saved edit appears in sorted order when the updated `rows` arrive.\n\nOn narrow layouts, the columns still share the table width and wrap their text, each keeping a 110 px minimum (a column with a fixed `width` keeps that width), and they pan horizontally only when those minimums exceed the table width. A long cell wraps inside its column rather than widening the table. The overflowing scrollport is a keyboard tab stop, so the platform's arrow keys can reveal the remaining columns, and while it has keyboard focus the table's surface draws the theme's focus ring. A table that fits adds no scrolling tab stop and takes no sideways drag either, so a tap that drifts sideways still presses its row and a swipe that starts across it scrolls the page (while TalkBack explores by touch the scroller stays enabled, so the exploring finger reaches every cell). A table that passes `stacks` does not pan: at that width each row stacks its cells (see Stacked below). Crossing that width changes the layout only: rows, custom cells, an open editor with its text and focus, and a windowed body's scroll position stay as they are when a window is resized across it or a phone measures the table on its first frame.\n\nA `virtualized` table's body scrolls its rows under the fixed header. On the\nweb, while those rows overflow, the body is a keyboard tab stop of its own\n(after the column scroller when a narrow table pans, and before the rows'\ncontrols when they have any), the keyboard can scroll it, and while it has\nkeyboard focus the table's surface draws the same focus ring. The body is the\ntable's row group, so the rows it renders stay inside the table for a screen\nreader rather than behind an unnamed focusable node."}},{"slug":"depth-chart","name":"DepthChart","category":"charts","description":"The order-book view: cumulative bid and ask step areas mirrored around the spread, bids in the success tone and asks in destructive, on a numeric price axis.","source":"src/charts/depth-chart/depth-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/depth-chart.md","humanUrl":"https://canvas.nannier.com/components/depth-chart","exports":["DepthChart","DepthChartProps","DepthLevel"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"DepthChartProps","props":[{"name":"bids","type":"DepthLevel[]","required":true,"description":"Bid levels (any order; sorted internally)."},{"name":"asks","type":"DepthLevel[]","required":true,"description":"Ask levels (any order; sorted internally)."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":0},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":0},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":1},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":1},{"name":"hideAxes","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":1},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats tick labels and accessible values (data formatting, not styling).","group":1},{"name":"spread","type":"string | undefined","required":false,"description":"The spread's label (\"spread 0.12%\"): drawn as a dashed guide midway between the best bid and the best ask, with this label in a pill at its top. Omit for no guide.","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."},{"title":"Furniture visibility","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"The order-book view: cumulative bid and ask step areas mirrored around the spread, bids in the success tone and asks in destructive, on a numeric price axis.","ios":"The order-book view: cumulative bid and ask step areas mirrored around the spread, bids in the success tone and asks in destructive, on a numeric price axis.","android":"The order-book view: cumulative bid and ask step areas mirrored around the spread, bids in the success tone and asks in destructive, on a numeric price axis."}},{"slug":"description-lists","name":"DescriptionList","category":"molecules","description":"Key-value pairs in stacked, two-column, or inline-edit layouts. Used for detail panels, settings, and profile views. Rows flagged `update` carry a working in-place editor: Update opens it, Enter or Save commits the new value and fires `onUpdate`, Escape or Cancel dismisses it. `muted` sets each text value as a note beside its term, in the small type and the muted ink, for a list that explains its terms (a key and its effect) rather than reporting data; a node value renders as given, and a platform skin whose value detail is already the secondary ink keeps its type.","source":"src/molecules/description-lists/description-lists.md","url":"https://canvas.nannier.com/ai/4.2.0/components/description-lists.md","humanUrl":"https://canvas.nannier.com/components/description-lists","exports":["DescriptionList","DescriptionListAvatar","DescriptionListItem","DescriptionListProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"DescriptionListProps","props":[{"name":"items","type":"DescriptionListItem[]","required":true,"description":""},{"name":"title","type":"string | undefined","required":false,"description":"Card header band (only shown when `card`): a title and optional subtitle.","group":0},{"name":"subtitle","type":"string | undefined","required":false,"description":"Card header band (only shown when `card`): a title and optional subtitle.","group":0},{"name":"inline","type":"boolean | undefined","required":false,"description":"Layout (pick one; precedence inline > twoColumn > stacked).","default":"false","group":1},{"name":"twoColumn","type":"boolean | undefined","required":false,"description":"Layout (pick one; precedence inline > twoColumn > stacked).","default":"false","group":1},{"name":"stacked","type":"boolean | undefined","required":false,"description":"Layout (pick one; precedence inline > twoColumn > stacked).","default":"false","group":1},{"name":"divided","type":"boolean | undefined","required":false,"description":"Rows (pick one; precedence ruled > divided): a hairline divider beneath every row but the last.","default":"false","group":2},{"name":"ruled","type":"boolean | undefined","required":false,"description":"Rows: a 1 px top rule on every row, the first included, with the row padded 9 above and below and the term hugging its content (a 120 floor, 14 to the value), the v4 hand-off's accessibility-card rows. Wins over `divided`.","default":"false","group":2},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density: tightens the ruled rows to the v4 hand-off's semantics-card rows (Component.dc.html line 263): 8 above and below the text, 12 to the value, the term a fixed 110 column and the value at the top of its row. Only the ruled rows have a compact step; a plain or divided list is unchanged by it.","default":"false","group":2},{"name":"muted","type":"boolean | undefined","required":false,"description":"The values as notes beside their terms: a text value in the small type and the muted ink (400 13/19) instead of the full-weight foreground data, for a list that explains each term (a key and its effect). A node value renders as given, and a platform skin whose value detail is already the secondary ink keeps its type.","default":"false","group":2},{"name":"card","type":"boolean | undefined","required":false,"description":"Surface: wrap the list in a card surface.","default":"false","group":3},{"name":"onUpdate","type":"((index: number, value: string) => void) | undefined","required":false,"description":"Fires when a row's inline editor commits (Enter or Save): the item index and the new value.","group":3},{"name":"onCopy","type":"((value: string) => void) | undefined","required":false,"description":"Fires with a row's `copyValue` when its \"Copy\" button is pressed.","group":3},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":3},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":3}],"groups":[{"title":"Card header band","pickOne":false,"note":"Card header band (only shown when `card`): a title and optional subtitle."},{"title":"Layout","pickOne":true,"note":"Layout (pick one; precedence inline > twoColumn > stacked)."},{"title":"Rows","pickOne":true,"note":"Rows (pick one; precedence ruled > divided): a hairline divider beneath every row but the last."},{"title":"Surface","pickOne":false,"note":"Surface: wrap the list in a card surface."}],"inherits":[]}],"platformNotes":{"web":"Key-value pairs in stacked, two-column, or inline-edit layouts. Used for detail panels, settings, and profile views. Rows flagged `update` carry a working in-place editor: Update opens it, Enter or Save commits the new value and fires `onUpdate`, Escape or Cancel dismisses it. `muted` sets each text value as a note beside its term, in the small type and the muted ink, for a list that explains its terms (a key and its effect) rather than reporting data; a node value renders as given, and a platform skin whose value detail is already the secondary ink keeps its type.\n\nThe rows axis (pick one; `ruled` wins over `divided`): `divided` draws a hairline under every row but the last, the two-column detail look. `ruled` draws the v4 hand-off's accessibility-card rows: a 1 px top rule on every row, the first included, so the list reads as a table that starts under its caption, each row padded 9 above and below with nothing beside, and in the two-column layout the term hugging its content over a 120 floor with 14 to the value.\n\nThe density axis: `compact` tightens the ruled rows to the hand-off's semantics-card rows, each padded 8 above and below with 12 to the value, the two-column term a fixed 110 column, and the value at the top of its row (so a wrapping row of badges starts level with its term); the plain and divided rows have no compact step, so `compact` without `ruled` changes nothing.","ios":"Key-value pairs in stacked, two-column, or inline-edit layouts. Used for detail panels, settings, and profile views. Rows flagged `update` carry a working in-place editor: Update opens it, Enter or Save commits the new value and fires `onUpdate`, Escape or Cancel dismisses it. `muted` sets each text value as a note beside its term, in the small type and the muted ink, for a list that explains its terms (a key and its effect) rather than reporting data; a node value renders as given, and a platform skin whose value detail is already the secondary ink keeps its type.\n\nThe rows axis (pick one; `ruled` wins over `divided`): `divided` draws a hairline under every row but the last, the two-column detail look. `ruled` draws the v4 hand-off's accessibility-card rows: a 1 px top rule on every row, the first included, so the list reads as a table that starts under its caption, each row padded 9 above and below with nothing beside, and in the two-column layout the term hugging its content over a 120 floor with 14 to the value.\n\nThe density axis: `compact` tightens the ruled rows to the hand-off's semantics-card rows, each padded 8 above and below with 12 to the value, the two-column term a fixed 110 column, and the value at the top of its row (so a wrapping row of badges starts level with its term); the plain and divided rows have no compact step, so `compact` without `ruled` changes nothing.","android":"Key-value pairs in stacked, two-column, or inline-edit layouts. Used for detail panels, settings, and profile views. Rows flagged `update` carry a working in-place editor: Update opens it, Enter or Save commits the new value and fires `onUpdate`, Escape or Cancel dismisses it. `muted` sets each text value as a note beside its term, in the small type and the muted ink, for a list that explains its terms (a key and its effect) rather than reporting data; a node value renders as given, and a platform skin whose value detail is already the secondary ink keeps its type.\n\nThe rows axis (pick one; `ruled` wins over `divided`): `divided` draws a hairline under every row but the last, the two-column detail look. `ruled` draws the v4 hand-off's accessibility-card rows: a 1 px top rule on every row, the first included, so the list reads as a table that starts under its caption, each row padded 9 above and below with nothing beside, and in the two-column layout the term hugging its content over a 120 floor with 14 to the value.\n\nThe density axis: `compact` tightens the ruled rows to the hand-off's semantics-card rows, each padded 8 above and below with 12 to the value, the two-column term a fixed 110 column, and the value at the top of its row (so a wrapping row of badges starts level with its term); the plain and divided rows have no compact step, so `compact` without `ruled` changes nothing."}},{"slug":"dialog","name":"Dialog","category":"organisms","description":"A modal dialog: a centered panel over a dimmed backdrop, which glass on the web also blurs, with a title, an optional description, a body for real content like a form, and right-aligned actions. Use it for a focused task that warrants interrupting the page; reach for the Alert Dialog for a terse yes/no confirmation.","source":"src/organisms/dialog/dialog.md","url":"https://canvas.nannier.com/ai/4.2.0/components/dialog.md","humanUrl":"https://canvas.nannier.com/components/dialog","exports":["Dialog","DialogProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"DialogProps","props":[{"name":"form","type":"boolean | undefined","required":false,"description":"Structured form: a named header and close action above scrolling body/footer content.","default":"false"},{"name":"workspace","type":"boolean | undefined","required":false,"description":"Give an overlay form a viewport-bounded body that fills between its fixed header and footer.","default":"false"},{"name":"compact","type":"boolean | undefined","required":false,"description":"Let a workspace hug short content and grow only up to its viewport bound.","default":"false"},{"name":"workspaceHeader","type":"ReactNode","required":false,"description":"Extra content in the fixed header of a workspace form, below its title and description."},{"name":"headerAccessory","type":"ReactNode","required":false,"description":"Content beside the form title, such as a workflow's progress status."},{"name":"workspaceSidebar","type":"ReactNode","required":false,"description":"A fixed side rail beside a workspace's scrolling body."},{"name":"footer","type":"ReactNode","required":false,"description":"Custom actions after the form body; fixed below the body in workspace mode."},{"name":"banded","type":"boolean | undefined","required":false,"description":"Draw the reference's shared workflow panel as three bands split by hairline rules: the header (title, `headerAccessory` and optional `workspaceHeader`), body, and footer. A `workspaceSidebar` stays beside the body. Embedded panels keep their opaque in-page surface without a veil or close action; live panels keep modal presentation.","default":"false"},{"name":"icon","type":"ReactNode","required":false,"description":"A leading glyph for the panel, drawn as the accent's soft tone tile (`Emblem primary soft`) above the title. Pass an `<Icon />`; the tile tints and sizes it."},{"name":"panelWidth","type":"number | undefined","required":false,"description":"Maximum form panel width in pixels; defaults to 560."},{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"title","type":"string | undefined","required":false,"description":"Content (strings, for the children-less / data-driven case).","group":0},{"name":"description","type":"string | undefined","required":false,"description":"Content (strings, for the children-less / data-driven case).","group":0},{"name":"withBody","type":"boolean | undefined","required":false,"description":"Body: render a short form (Amount + Reason fields) inside the panel for the data-driven case.","default":"false","group":1},{"name":"trigger","type":"string | undefined","required":false,"description":"Trigger button label. When set, the dialog renders the button and opens itself on press (uncontrolled). Omit when you drive `open` yourself.","group":2},{"name":"confirmLabel","type":"string | undefined","required":false,"description":"Action labels.","default":"\"Confirm\"","group":3},{"name":"cancelLabel","type":"string | undefined","required":false,"description":"Action labels.","default":"\"Cancel\"","group":3},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Omit for uncontrolled (the trigger opens it).","default":"false","group":4},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes (trigger press, confirm, cancel).","group":5},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Confirm intent (default is a primary confirm).","default":"false","group":6},{"name":"xs","type":"boolean | undefined","required":false,"description":"Width (pick one; default is the standard panel width). First-match precedence: xs, small, medium, large, wide.","default":"false","group":7},{"name":"small","type":"boolean | undefined","required":false,"description":"Width (pick one; default is the standard panel width). First-match precedence: xs, small, medium, large, wide.","default":"false","group":7},{"name":"medium","type":"boolean | undefined","required":false,"description":"Width (pick one; default is the standard panel width). First-match precedence: xs, small, medium, large, wide.","default":"false","group":7},{"name":"large","type":"boolean | undefined","required":false,"description":"Width (pick one; default is the standard panel width). First-match precedence: xs, small, medium, large, wide.","default":"false","group":7},{"name":"wide","type":"boolean | undefined","required":false,"description":"Width (pick one; default is the standard panel width). First-match precedence: xs, small, medium, large, wide.","default":"false","group":7},{"name":"onConfirm","type":"(() => void) | undefined","required":false,"description":"Action handlers.","group":8},{"name":"onCancel","type":"(() => void) | undefined","required":false,"description":"Action handlers.","group":8},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":8},{"name":"overlay","type":"boolean | undefined","required":false,"description":"Presents the dialog OVER the page instead of inline where it is mounted. The default is a contained overlay: a scrim with its own height, sitting in normal flow, which is what the docs catalogue needs to show a dialog inside an example stage. An application confirming a destructive action needs the opposite, and the inline form is actively wrong there: it appends a scrim wherever the component happens to sit, leaves the page behind scrollable and clickable, and still claims `aria-modal`. With `overlay`, the dialog teleports into the nearest `OverlayProvider` and fills it, so `aria-modal` becomes true rather than aspirational. Mount an `OverlayProvider` at the app root for this to cover the screen.","default":"false","group":8},{"name":"dismissible","type":"boolean | undefined","required":false,"description":"Cancel when the backdrop is pressed. Off by default, including destructive dialogs.","default":"false","group":8},{"name":"embedded","type":"boolean | undefined","required":false,"description":"Show the open dialog as a non-modal specimen in the page, for a catalogue or a showcase: it keeps its look, its dialog role and its labelling, but does not take focus when it opens, trap Tab, return focus, claim `aria-modal`, or cancel on Escape, native back or a backdrop press. Ignored with `trigger`, which always opens a live modal.","default":"false","group":8},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"The dialog's accessible name, for the case where `children` supply the panel body. Children REPLACE the built-in title/description, so there is no element left for `aria-labelledby` to point at, and the dialog would otherwise be announced with no name at all. That is merely poor for a `dialog` and invalid for the `alertdialog` a destructive confirm renders.","group":8},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook.","group":8}],"groups":[{"title":"Content","pickOne":false,"note":"Content (strings, for the children-less / data-driven case)."},{"title":"Body","pickOne":false,"note":"Body: render a short form (Amount + Reason fields) inside the panel for the data-driven case."},{"title":"Trigger button label","pickOne":false,"note":"Trigger button label. When set, the dialog renders the button and opens itself on press (uncontrolled). Omit when you drive `open` yourself."},{"title":"Action labels","pickOne":false},{"title":"Controlled open state","pickOne":false,"note":"Controlled open state. Omit for uncontrolled (the trigger opens it)."},{"title":"Fired when the open state changes","pickOne":false,"note":"Fired when the open state changes (trigger press, confirm, cancel)."},{"title":"Confirm intent","pickOne":false,"note":"Confirm intent (default is a primary confirm)."},{"title":"Width","pickOne":true,"note":"Width (pick one; default is the standard panel width). First-match precedence: xs, small, medium, large, wide."},{"title":"Action handlers","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"A modal dialog: a centered panel over a dimmed backdrop, which glass on the web also blurs, with a title, an optional description, a body for real content like a form, and right-aligned actions. Use it for a focused task that warrants interrupting the page; reach for the Alert Dialog for a terse yes/no confirmation.\n\nOn light glass, the description and currency prefix use the stronger foreground color. For custom body content, use the default `Typography` foreground for message copy over the dimmed background.\n\nBrowser Escape and iOS accessibility escape cancel the foremost open child\noverlay before the dialog.\nCancelling the dialog calls `onCancel` and requests\n`open=false`, including destructive dialogs and dialogs with custom children.\nA controlled owner may keep it open; that request never confirms an action.\n\nPass `dismissible` to let a backdrop press follow the same cancel policy. It is\noff by default, so existing dialogs and destructive confirmations keep their\ncurrent outside-press behavior. The scrim is excluded from keyboard navigation.\n\nUse `form overlay dismissible` for the original Argus application dialog: a\npersistent title and optional `description`, a close action, and scrolling body\nand `footer` content. `panelWidth` bounds the form (560 pixels by default), and\nthe viewport keeps a twenty-pixel safe-area inset. The web treatment preserves\nArgus’s 28-pixel content inset, 17-pixel title, rounded card, shadow, and lightly\nfrosted dim. A form with no trigger contributes no layout wrapper to its caller.\nNested menus receive Escape before the dialog; focus stays in the open modal.\n\nFor a conversation or other workspace with its own scroll region, use\n`form workspace overlay`. The dialog measures a safe-area-bounded viewport\nheight; its header and optional `footer` stay fixed while `children` fill the\nremaining space. Put the workspace's scrollable content inside `children` and\nkeep its composer or other controls as siblings of that scroll region. The\nworkspace body does not add an outer scrollport. `workspaceHeader` adds content\nbelow the title and description in the fixed header, such as a step indicator.\nThis mode is intended for an overlay form; ordinary forms keep their existing\nscrolling body.\n\nAdd `compact` to a workspace when short content should determine the panel's\nheight: `form workspace compact overlay`. The panel hugs the conversation and\ncomposer, then grows up to the same safe-area-bounded viewport maximum. A long\nconversation scrolls inside its own thread while the header, composer, and dialog\nfooter remain visible. The default workspace still fills its available height;\n`compact` has no effect without `form workspace`.\n\nAdd `embedded` to show an open dialog in a page as a specimen, the way a catalogue\nor a showcase does: it keeps its look, its dialog role and its labelling, but it is\nnot modal. It does not take focus when it opens, trap Tab, return focus, set\n`aria-modal`, or cancel on Escape, native back or a backdrop press, so the page\naround it keeps its scroll position and its keyboard order. `embedded` is ignored\nwith `trigger`, which always opens a live modal.","ios":"A modal dialog: a centered panel over a dimmed backdrop, which glass on the web also blurs, with a title, an optional description, a body for real content like a form, and right-aligned actions. Use it for a focused task that warrants interrupting the page; reach for the Alert Dialog for a terse yes/no confirmation.\n\nOn light glass, the description and currency prefix use the stronger foreground color. For custom body content, use the default `Typography` foreground for message copy over the dimmed background.\n\nBrowser Escape and iOS accessibility escape cancel the foremost open child overlay before the dialog.\nCancelling the dialog calls `onCancel` and requests\n`open=false`, including destructive dialogs and dialogs with custom children.\nA controlled owner may keep it open; that request never confirms an action.\n\nPass `dismissible` to let a backdrop press follow the same cancel policy. It is\noff by default, so existing dialogs and destructive confirmations keep their\ncurrent outside-press behavior. The scrim is excluded from keyboard navigation.\n\nUse `form overlay dismissible` for the original Argus application dialog: a\npersistent title and optional `description`, a close action, and scrolling body\nand `footer` content. `panelWidth` bounds the form (560 pixels by default), and\nthe viewport keeps a twenty-pixel safe-area inset. The web treatment preserves\nArgus’s 28-pixel content inset, 17-pixel title, rounded card, shadow, and lightly\nfrosted dim. A form with no trigger contributes no layout wrapper to its caller.\nNested menus receive Escape before the dialog; focus stays in the open modal.\n\nFor a conversation or other workspace with its own scroll region, use\n`form workspace overlay`. The dialog measures a safe-area-bounded viewport\nheight; its header and optional `footer` stay fixed while `children` fill the\nremaining space. Put the workspace's scrollable content inside `children` and\nkeep its composer or other controls as siblings of that scroll region. The\nworkspace body does not add an outer scrollport. `workspaceHeader` adds content\nbelow the title and description in the fixed header, such as a step indicator.\nThis mode is intended for an overlay form; ordinary forms keep their existing\nscrolling body.\n\nAdd `compact` to a workspace when short content should determine the panel's\nheight: `form workspace compact overlay`. The panel hugs the conversation and\ncomposer, then grows up to the same safe-area-bounded viewport maximum. A long\nconversation scrolls inside its own thread while the header, composer, and dialog\nfooter remain visible. The default workspace still fills its available height;\n`compact` has no effect without `form workspace`.\n\nAdd `embedded` to show an open dialog in a page as a specimen, the way a catalogue\nor a showcase does: it keeps its look, its dialog role and its labelling, but it is\nnot modal. It does not take focus when it opens, trap Tab, return focus, set\n`aria-modal`, or cancel on Escape, native back or a backdrop press, so the page\naround it keeps its scroll position and its keyboard order. `embedded` is ignored\nwith `trigger`, which always opens a live modal.","android":"A modal dialog: a centered panel over a dimmed backdrop, which glass on the web also blurs, with a title, an optional description, a body for real content like a form, and right-aligned actions. Use it for a focused task that warrants interrupting the page; reach for the Alert Dialog for a terse yes/no confirmation.\n\nOn light glass, the description and currency prefix use the stronger foreground color. For custom body content, use the default `Typography` foreground for message copy over the dimmed background.\n\nBrowser Escape and the system back cancel the foremost open child overlay before the dialog.\nCancelling the dialog calls `onCancel` and requests\n`open=false`, including destructive dialogs and dialogs with custom children.\nA controlled owner may keep it open; that request never confirms an action.\n\nPass `dismissible` to let a backdrop press follow the same cancel policy. It is\noff by default, so existing dialogs and destructive confirmations keep their\ncurrent outside-press behavior. The scrim is excluded from keyboard navigation.\n\nUse `form overlay dismissible` for the original Argus application dialog: a\npersistent title and optional `description`, a close action, and scrolling body\nand `footer` content. `panelWidth` bounds the form (560 pixels by default), and\nthe viewport keeps a twenty-pixel safe-area inset. The web treatment preserves\nArgus’s 28-pixel content inset, 17-pixel title, rounded card, shadow, and lightly\nfrosted dim. A form with no trigger contributes no layout wrapper to its caller.\nNested menus receive Escape before the dialog; focus stays in the open modal.\n\nFor a conversation or other workspace with its own scroll region, use\n`form workspace overlay`. The dialog measures a safe-area-bounded viewport\nheight; its header and optional `footer` stay fixed while `children` fill the\nremaining space. Put the workspace's scrollable content inside `children` and\nkeep its composer or other controls as siblings of that scroll region. The\nworkspace body does not add an outer scrollport. `workspaceHeader` adds content\nbelow the title and description in the fixed header, such as a step indicator.\nThis mode is intended for an overlay form; ordinary forms keep their existing\nscrolling body.\n\nAdd `compact` to a workspace when short content should determine the panel's\nheight: `form workspace compact overlay`. The panel hugs the conversation and\ncomposer, then grows up to the same safe-area-bounded viewport maximum. A long\nconversation scrolls inside its own thread while the header, composer, and dialog\nfooter remain visible. The default workspace still fills its available height;\n`compact` has no effect without `form workspace`.\n\nAdd `embedded` to show an open dialog in a page as a specimen, the way a catalogue\nor a showcase does: it keeps its look, its dialog role and its labelling, but it is\nnot modal. It does not take focus when it opens, trap Tab, return focus, set\n`aria-modal`, or cancel on Escape, native back or a backdrop press, so the page\naround it keeps its scroll position and its keyboard order. `embedded` is ignored\nwith `trigger`, which always opens a live modal."}},{"slug":"divider","name":"Divider","category":"atoms","description":"Horizontal, vertical, with label, with action.","source":"src/atoms/divider/divider.md","url":"https://canvas.nannier.com/ai/4.2.0/components/divider.md","humanUrl":"https://canvas.nannier.com/components/divider","exports":["Divider","DividerProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"DividerProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"Optional middle content. With children, a horizontal divider renders a flanking-line + centered-label row (the \"with label\" / \"with action\" patterns). A string renders as the uppercase mono caption label; arbitrary nodes (e.g. a button) render as-is for the action pattern. Ignored when `vertical`."},{"name":"horizontal","type":"boolean | undefined","required":false,"description":"Orientation (pick one; default is horizontal).","default":"false","group":0},{"name":"vertical","type":"boolean | undefined","required":false,"description":"Orientation (pick one; default is horizontal).","default":"false","group":0},{"name":"soft","type":"boolean | undefined","required":false,"description":"A quieter rule: the hairline at 60% of its strength.","default":"false","group":1},{"name":"strong","type":"boolean | undefined","required":false,"description":"A firmer rule: the `field-border` line, twice the hairline's strength.","default":"false","group":1},{"name":"inset","type":"boolean | undefined","required":false,"description":"Vertical only: a short rule (18 px) centred in its row with 4 px kept on each side, instead of a rule that stretches to the row's height. The separator between groups in a toolbar or a floating bar. A horizontal divider ignores it.","default":"false","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Orientation","pickOne":true,"note":"Orientation (pick one; default is horizontal)."},{"title":"Emphasis","pickOne":true,"note":"Emphasis (pick one; default is the hairline `border`)."}],"inherits":[]}],"platformNotes":{"web":"Horizontal, vertical, with label, with action.","ios":"Horizontal, vertical, with label, with action.","android":"Horizontal, vertical, with label, with action."}},{"slug":"drag-drop","name":"Drag & drop","category":"organisms","description":"A reusable drag-and-drop context: wrap a surface in a `DragDropProvider`, mark droppable regions with `DropZone`, and make items draggable with `Draggable` plus a `DragHandle` grip.","source":"src/organisms/drag-drop/drag-drop.md","url":"https://canvas.nannier.com/ai/4.2.0/components/drag-drop.md","humanUrl":"https://canvas.nannier.com/components/drag-drop","exports":["DragDropProvider","DragDropProviderProps","DragHandle","DragHandleProps","Draggable","DraggableProps","DropEvent","DropZone","DropZoneProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"DragDropProviderProps","props":[{"name":"children","type":"ReactNode","required":true,"description":""},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook. The provider wraps the whole draggable surface and hosts the floating drag ghost."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."}],"groups":[],"inherits":[]},{"name":"DropZoneProps","props":[{"name":"id","type":"string","required":true,"description":"Stable id for this drop target, used in the drop event and for keyboard navigation."},{"name":"label","type":"string","required":true,"description":"Accessible name announced when a drag hovers or drops here (e.g. the column title)."},{"name":"onDrop","type":"((e: DropEvent) => void) | undefined","required":false,"description":"Fired on THIS zone when an item is dropped into it (from any zone, including itself)."},{"name":"horizontal","type":"boolean | undefined","required":false,"description":"Lay the items out in a row so the insertion axis is horizontal (default is a vertical column).","default":"false"},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Refuse drops: the zone is skipped by hit-testing and the keyboard cursor, and never highlights.","default":"false"},{"name":"bordered","type":"boolean | undefined","required":false,"description":"Draw the zone as a visible drop well: a dashed sunken surface with its `label` as an eyebrow over the items. Without it the zone is only a drop target around its children.","default":"false"},{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."}],"groups":[],"inherits":[]},{"name":"DraggableProps","props":[{"name":"id","type":"string","required":true,"description":"Stable id for this item (unique within the provider)."},{"name":"data","type":"T","required":true,"description":"Arbitrary payload handed back in the drop event."},{"name":"label","type":"string | undefined","required":false,"description":"Accessible name of the item, used in drag announcements (falls back to `id`)."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Disable dragging: the grip inside becomes inert.","default":"false"},{"name":"preview","type":"ReactNode","required":false,"description":"Custom floating drag preview; defaults to the item's own `children`."},{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."}],"groups":[],"inherits":[]},{"name":"DragHandleProps","props":[{"name":"label","type":"string | undefined","required":false,"description":"Accessible name for the grip (e.g. \"Reorder Rotate webhook secrets\")."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"A reusable drag-and-drop context: wrap a surface in a `DragDropProvider`, mark droppable regions with `DropZone`, and make items draggable with `Draggable` plus a `DragHandle` grip.\n\nItems lift into a floating ghost and reorder within or across zones, position-aware.\nIt runs on iOS, Android, and the web from one PanResponder + Animated code path,\nand the grip is keyboard- and screen-reader-operable: press Space to grab, the arrow keys to move, Space to drop, Escape to cancel.\n\nThe reading direction is respected throughout. In a right-to-left locale a `horizontal` zone lays its items out right to left, so the first position is the rightmost one, the drop indicator meets the row's right edge, and the two horizontal arrows swap roles (Left Arrow moves forward, Right Arrow back, per the WAI-ARIA practices). Vertical lists and the up/down arrows read the same way in both directions.","ios":"A reusable drag-and-drop context: wrap a surface in a `DragDropProvider`, mark droppable regions with `DropZone`, and make items draggable with `Draggable` plus a `DragHandle` grip.\n\nItems lift into a floating ghost and reorder within or across zones, position-aware.\nIt runs on every platform Canvas supports from one PanResponder + Animated code path,\nand the grip is keyboard- and screen-reader-operable: press Space to grab, the arrow keys to move, Space to drop, Escape to cancel.\n\nThe reading direction is respected throughout. In a right-to-left locale a `horizontal` zone lays its items out right to left, so the first position is the rightmost one, the drop indicator meets the row's right edge, and the two horizontal arrows swap roles (Left Arrow moves forward, Right Arrow back, per the WAI-ARIA practices). Vertical lists and the up/down arrows read the same way in both directions.","android":"A reusable drag-and-drop context: wrap a surface in a `DragDropProvider`, mark droppable regions with `DropZone`, and make items draggable with `Draggable` plus a `DragHandle` grip.\n\nItems lift into a floating ghost and reorder within or across zones, position-aware.\nIt runs on every platform Canvas supports from one PanResponder + Animated code path,\nand the grip is keyboard- and screen-reader-operable: press Space to grab, the arrow keys to move, Space to drop, Escape to cancel.\n\nThe reading direction is respected throughout. In a right-to-left locale a `horizontal` zone lays its items out right to left, so the first position is the rightmost one, the drop indicator meets the row's right edge, and the two horizontal arrows swap roles (Left Arrow moves forward, Right Arrow back, per the WAI-ARIA practices). Vertical lists and the up/down arrows read the same way in both directions."}},{"slug":"drawer","name":"Drawer","category":"organisms","description":"A full-screen panel that slides in from an edge: a navigation drawer, a mobile menu, or a bottom action sheet. Built on React Native's Modal, so it floats over the whole app on iOS, Android, and the web, over a dimmed scrim that glass on the web also blurs. For a small contextual menu, reach for Dropdown or RowMenu instead.","source":"src/organisms/drawer/drawer.md","url":"https://canvas.nannier.com/ai/4.2.0/components/drawer.md","humanUrl":"https://canvas.nannier.com/components/drawer","exports":["Drawer","DrawerProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"DrawerProps","props":[{"name":"header","type":"ReactNode","required":false,"description":"Pinned header above the independently scrolling body."},{"name":"footer","type":"ReactNode","required":false,"description":"Pinned actions below the independently scrolling body."},{"name":"navigation","type":"boolean | undefined","required":false,"description":"Navigation body: no content inset or inter-item gap; fills the available height.","default":"false"},{"name":"terminal","type":"boolean | undefined","required":false,"description":"Solid, rounded execution sidebar inset from the viewport. Overrides edge and plain; width remains configurable.","default":"false"},{"name":"plain","type":"boolean | undefined","required":false,"description":"Square web side panel and the original lightly frosted application dim.","default":"false"},{"name":"instant","type":"boolean | undefined","required":false,"description":"Present and dismiss immediately, preserving the original application interaction.","default":"false"},{"name":"embedded","type":"boolean | undefined","required":false,"description":"Show the open drawer as a non-modal specimen inside its parent, for a catalogue or a showcase: the panel docks against its edge of the parent (which gives it its height) over the dim, with no Modal, no slide, no focus trap, and no close on Escape, native back or a tap on the dim. It keeps its labelling as a named region. Ignored with `trigger`, which always opens a live drawer.","default":"false"},{"name":"children","type":"ReactNode","required":false,"description":"Panel content."},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Omit for uncontrolled (a `trigger` opens it).","default":"false"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes (trigger press, scrim tap, back/escape)."},{"name":"onClosed","type":"(() => void) | undefined","required":false,"description":"Called once after an opened drawer finishes dismissal; never called for its initial closed state."},{"name":"trigger","type":"string | undefined","required":false,"description":"Label for an optional outline trigger button. When set, the drawer renders the button and opens itself on press (uncontrolled). Omit when you drive `open` yourself."},{"name":"left","type":"boolean | undefined","required":false,"description":"A full-height panel on the left edge (default).","default":"false","group":0},{"name":"right","type":"boolean | undefined","required":false,"description":"A full-height panel on the right edge.","default":"false","group":0},{"name":"bottom","type":"boolean | undefined","required":false,"description":"A sheet spanning the width, rising from the bottom.","default":"false","group":0},{"name":"top","type":"boolean | undefined","required":false,"description":"A sheet spanning the width, dropping from the top.","default":"false","group":0},{"name":"width","type":"number | undefined","required":false,"description":"Width of a side drawer in px (default 300). Ignored for the bottom/top sheet.","default":"300","group":0},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the modal surface. Required when the drawer has no trigger whose label can name it.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition for the panel surface, never a restyle hook. (Device safe-area insets are applied automatically.)","group":0}],"groups":[{"title":"Edge axis","pickOne":true,"note":"Edge axis (pick one; first match wins, default is the left side drawer)."}],"inherits":[]}],"platformNotes":{"web":"A full-screen panel that slides in from an edge: a navigation drawer, a mobile menu, or a bottom action sheet. Built on React Native's Modal,\nso it floats over the whole app on iOS, Android, and the web,\nover a dimmed scrim that glass on the web also blurs. For a small contextual menu, reach for Dropdown or RowMenu instead.\n\nDrawer provides an overlay host inside its own window. Dropdown, Select, and other anchored children render above the panel without being clipped by its corners; no additional OverlayProvider is needed inside the drawer. A tap outside an open child menu dismisses that menu, and Escape dismisses the child before the drawer. Nested drawers each keep their overlays in their own window.\n\nOn iOS, VoiceOver's accessibility escape gesture requests dismissal of the\nforemost open child before the drawer.\nAndroid system back uses the same child\nownership.\nA controlled child that stays open continues to own later requests;\none request never falls through to its parent. The scrim remains a pointer\ntarget, and the built-in trigger opens the drawer. Sidebar drill-down navigation\nhas its own back behavior; accessibility escape dismisses the overlay rather\nthan navigating a sidebar level. Focus restoration remains platform-dependent.\n\nGive a controlled drawer an `accessibilityLabel` when it has no built-in\n`trigger`. A drawer with a trigger uses the trigger label as its modal name.\n\n`header` and `footer` pin content around an independently scrolling body. Its\napplication inset is 20 pixels vertically and 24 horizontally, with 22 between\nchildren. `navigation` gives that body no inset or gap and fills its height.\n`plain` preserves the original square Argus side panel and lightly frosted dim on\nweb; native skins retain their platform panel. `instant` presents and dismisses\nwithout a slide or fade. Existing drawers retain their animated default.","ios":"A full-screen panel that slides in from an edge: a navigation drawer, a mobile menu, or a bottom action sheet. Built on React Native's Modal,\nso it floats over the whole app on every platform Canvas supports,\nover a dimmed scrim that glass on the web also blurs. For a small contextual menu, reach for Dropdown or RowMenu instead.\n\nDrawer provides an overlay host inside its own window. Dropdown, Select, and other anchored children render above the panel without being clipped by its corners; no additional OverlayProvider is needed inside the drawer. A tap outside an open child menu dismisses that menu, and Escape dismisses the child before the drawer. Nested drawers each keep their overlays in their own window.\n\nOn iOS, VoiceOver's accessibility escape gesture requests dismissal of the\nforemost open child before the drawer.\nA controlled child that stays open continues to own later requests;\none request never falls through to its parent. The scrim remains a pointer\ntarget, and the built-in trigger opens the drawer. Sidebar drill-down navigation\nhas its own back behavior; accessibility escape dismisses the overlay rather\nthan navigating a sidebar level. Focus restoration remains platform-dependent.\n\nGive a controlled drawer an `accessibilityLabel` when it has no built-in\n`trigger`. A drawer with a trigger uses the trigger label as its modal name.\n\n`header` and `footer` pin content around an independently scrolling body. Its\napplication inset is 20 pixels vertically and 24 horizontally, with 22 between\nchildren. `navigation` gives that body no inset or gap and fills its height.\n`plain` preserves the original square Argus side panel and lightly frosted dim on\nweb; native skins retain their platform panel. `instant` presents and dismisses\nwithout a slide or fade. Existing drawers retain their animated default.","android":"A full-screen panel that slides in from an edge: a navigation drawer, a mobile menu, or a bottom action sheet. Built on React Native's Modal,\nso it floats over the whole app on every platform Canvas supports,\nover a dimmed scrim that glass on the web also blurs. For a small contextual menu, reach for Dropdown or RowMenu instead.\n\nDrawer provides an overlay host inside its own window. Dropdown, Select, and other anchored children render above the panel without being clipped by its corners; no additional OverlayProvider is needed inside the drawer. A tap outside an open child menu dismisses that menu, and Escape dismisses the child before the drawer. Nested drawers each keep their overlays in their own window.\n\nAndroid system back requests dismissal of the foremost open child before the drawer.\nA controlled child that stays open continues to own later requests;\none request never falls through to its parent. The scrim remains a pointer\ntarget, and the built-in trigger opens the drawer. Sidebar drill-down navigation\nhas its own back behavior; accessibility escape dismisses the overlay rather\nthan navigating a sidebar level. Focus restoration remains platform-dependent.\n\nGive a controlled drawer an `accessibilityLabel` when it has no built-in\n`trigger`. A drawer with a trigger uses the trigger label as its modal name.\n\n`header` and `footer` pin content around an independently scrolling body. Its\napplication inset is 20 pixels vertically and 24 horizontally, with 22 between\nchildren. `navigation` gives that body no inset or gap and fills its height.\n`plain` preserves the original square Argus side panel and lightly frosted dim on\nweb; native skins retain their platform panel. `instant` presents and dismisses\nwithout a slide or fade. Existing drawers retain their animated default."}},{"slug":"dropdown","name":"Dropdown","category":"atoms","description":"Floating menus triggered by a button: actions, options, navigation.","source":"src/atoms/dropdown/dropdown.md","url":"https://canvas.nannier.com/ai/4.2.0/components/dropdown.md","humanUrl":"https://canvas.nannier.com/components/dropdown","exports":["Dropdown","DropdownItem","DropdownProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"DropdownProps","props":[{"name":"anchorRef","type":"RefObject<View | null> | undefined","required":false,"description":"Use an existing trigger without adding a trigger or layout wrapper."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Explicit accessible name for the menu."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Exact compact web application menu frame and row metrics.","default":"false"},{"name":"steadyPress","type":"boolean | undefined","required":false,"description":"Preserve resting row fill and opacity during a press.","default":"false"},{"name":"menuWidth","type":"number | undefined","required":false,"description":"Width of the floating menu, clamped inside the overlay outlet."},{"name":"maxHeight","type":"number | undefined","required":false,"description":"Height cap for the compact menu's scrolling contents."},{"name":"note","type":"ReactNode","required":false,"description":"Muted footnote separated from menu commands by a hairline."},{"name":"trigger","type":"string | undefined","required":false,"description":"Label for the default outline trigger button. Omit when supplying a custom trigger via `children`."},{"name":"children","type":"ReactNode","required":false,"description":"A custom trigger rendered in place of the default outline button, e.g. an avatar account chip. It is wrapped in a Pressable that toggles the menu; the menu itself still comes from `items`."},{"name":"triggerLabel","type":"string | undefined","required":false,"description":"The accessible name for a CUSTOM trigger (`children`). Without it the button is named from its own contents, which runs the trigger's text together into one unpunctuated string (\"Rachel Chenrachel@example.com\") and repeats any label a nested control already carries. Ignored by the default `trigger` button, which is named by its own text."},{"name":"label","type":"string | undefined","required":false,"description":"Optional muted section heading rendered above the rows (e.g. \"Actions\")."},{"name":"title","type":"string | undefined","required":false,"description":"Identity header title, rendered in the popover foreground ABOVE everything else in the menu (an account name over its email, say). Pair it with `description`; passing neither omits the header block entirely."},{"name":"description","type":"string | undefined","required":false,"description":"Identity header second line, muted, under `title`."},{"name":"items","type":"DropdownItem[]","required":true,"description":"The menu rows, top to bottom."},{"name":"alignEnd","type":"boolean | undefined","required":false,"description":"Align the menu's TRAILING edge with the trigger's trailing edge instead of the leading edge (the default). For a trigger parked at the end of a bar, where a leading-aligned menu would run off the surface. Logical, so a right-to-left locale mirrors it.","default":"false"},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Dimmed, inert trigger: the menu never opens and the press is a no-op.","default":"false"},{"name":"inline","type":"boolean | undefined","required":false,"description":"Draw the menu open and in flow under the trigger instead of floating it over the page: a specimen of the menu for a docs page or an empty state. The trigger reads as expanded and the press is inert, a row still fires `onSelect`, and nothing dismisses the card, so `open` and `onOpenChange` have no effect. `alignEnd` lines the card up with the trigger's trailing edge, as it does for the floating card.","default":"false"},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Omit for uncontrolled (the trigger opens/closes it).","default":"false"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes (trigger press, select, etc.)."},{"name":"onSelect","type":"((item: DropdownItem, index: number) => void) | undefined","required":false,"description":"Fired with the selected item and its index when a row is pressed."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"Floating menus triggered by a button: actions, options, navigation.\n\nOn the web the menu is the v4 panel: a card with a hairline and a soft shadow, 36-pixel\nrows with quiet icons that take a raised wash under the pointer at once, a mono uppercase\neyebrow over a section, mono shortcuts in their own column, destructive rows in the\ndestructive ink, and a disabled row in the muted ink rather than faded.\niOS and Android keep their platform\nmenus (the iOS pull-down menu, the Material 3 menu) in the theme's colours.\n\nIn glass mode the menu is a dense-layer glass card under its trigger (or above it\nwhen it fits there); the trigger keeps its place, its press and its accessible\nname and state, and a selection commits and closes the menu the moment a row is\npressed. AvatarMenu and the collapsed Navbar menu are built on Dropdown. Solid\nmode paints the skin's own menu.\n\n`compact` tightens the web rows to 30 pixels and lets the menu scroll inside\n`maxHeight`; with `steadyPress` a press does not tint the row. Selected rows take the\naction ink.\nItems can carry a stored `value`, `detail`, `description`, `selected` state, and a\n`sectionBefore` heading. `keepOpen` leaves refresh-style commands open. A `note`\nadds a muted footer. `menuWidth` and `maxHeight` bound the scrolling menu.\nPass `anchorRef` to use an existing trigger without adding another control or\nlayout wrapper; `accessibilityLabel` names the menu independently of its heading.\nChecked choices use browser menu-radio semantics and the native radio trait.","ios":"Floating menus triggered by a button: actions, options, navigation.\n\nOn the web the menu is the v4 panel: a card with a hairline and a soft shadow, 36-pixel\nrows with quiet icons that take a raised wash under the pointer at once, a mono uppercase\neyebrow over a section, mono shortcuts in their own column, destructive rows in the\ndestructive ink, and a disabled row in the muted ink rather than faded.\niOS keeps its platform menu (the iOS pull-down menu) in the theme's colours.\n\nIn glass mode the menu is a dense-layer glass card under its trigger (or above it\nwhen it fits there); the trigger keeps its place, its press and its accessible\nname and state, and a selection commits and closes the menu the moment a row is\npressed. AvatarMenu and the collapsed Navbar menu are built on Dropdown. Solid\nmode paints the skin's own menu.\n\n`compact` tightens the web rows to 30 pixels and lets the menu scroll inside\n`maxHeight`; with `steadyPress` a press does not tint the row. Selected rows take the\naction ink.\nItems can carry a stored `value`, `detail`, `description`, `selected` state, and a\n`sectionBefore` heading. `keepOpen` leaves refresh-style commands open. A `note`\nadds a muted footer. `menuWidth` and `maxHeight` bound the scrolling menu.\nPass `anchorRef` to use an existing trigger without adding another control or\nlayout wrapper; `accessibilityLabel` names the menu independently of its heading.\nChecked choices use browser menu-radio semantics and the native radio trait.","android":"Floating menus triggered by a button: actions, options, navigation.\n\nOn the web the menu is the v4 panel: a card with a hairline and a soft shadow, 36-pixel\nrows with quiet icons that take a raised wash under the pointer at once, a mono uppercase\neyebrow over a section, mono shortcuts in their own column, destructive rows in the\ndestructive ink, and a disabled row in the muted ink rather than faded.\nAndroid keeps its platform menu (the Material 3 menu) in the theme's colours.\n\nIn glass mode the menu is a dense-layer glass card under its trigger (or above it\nwhen it fits there); the trigger keeps its place, its press and its accessible\nname and state, and a selection commits and closes the menu the moment a row is\npressed. AvatarMenu and the collapsed Navbar menu are built on Dropdown. Solid\nmode paints the skin's own menu.\n\n`compact` tightens the web rows to 30 pixels and lets the menu scroll inside\n`maxHeight`; with `steadyPress` a press does not tint the row. Selected rows take the\naction ink.\nItems can carry a stored `value`, `detail`, `description`, `selected` state, and a\n`sectionBefore` heading. `keepOpen` leaves refresh-style commands open. A `note`\nadds a muted footer. `menuWidth` and `maxHeight` bound the scrolling menu.\nPass `anchorRef` to use an existing trigger without adding another control or\nlayout wrapper; `accessibilityLabel` names the menu independently of its heading.\nChecked choices use browser menu-radio semantics and the native radio trait."}},{"slug":"emblem","name":"Emblem","category":"atoms","description":"A tinted rounded square (or circle) that holds a single `Icon` or a short monogram, the recurring \"icon on a soft background\" used in cards, media objects, empty states, and feeds. Emblem owns the surface and the icon color: pick a tone and it tints the square and paints the glyph to match, so a call site never hand-composes `borderRadius` + `backgroundColor` to build an icon background.","source":"src/atoms/emblem/emblem.md","url":"https://canvas.nannier.com/ai/4.2.0/components/emblem.md","humanUrl":"https://canvas.nannier.com/components/emblem","exports":["Emblem","EmblemProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"EmblemProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"A single `<Icon />` element; Emblem tints it to match the tone."},{"name":"label","type":"string | undefined","required":false,"description":"A monogram letter (or two) instead of an icon, painted in the tone color."},{"name":"primary","type":"boolean | undefined","required":false,"description":"Tone (pick one; default `muted`). Sets the tinted surface and the icon color. Precedence: primary > destructive > success > warning > cyan > secondary > muted.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (pick one; default `muted`). Sets the tinted surface and the icon color. Precedence: primary > destructive > success > warning > cyan > secondary > muted.","default":"false","group":0},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (pick one; default `muted`). Sets the tinted surface and the icon color. Precedence: primary > destructive > success > warning > cyan > secondary > muted.","default":"false","group":0},{"name":"warning","type":"boolean | undefined","required":false,"description":"Tone (pick one; default `muted`). Sets the tinted surface and the icon color. Precedence: primary > destructive > success > warning > cyan > secondary > muted.","default":"false","group":0},{"name":"cyan","type":"boolean | undefined","required":false,"description":"The fixed cyan hue (the hand-off's `--cyan`, the `chart-2` series): its wash and ring mixed from it, the glyph in the hue's ink, solved to 4.5:1 per scheme (Typography's `cyan`).","default":"false","group":0},{"name":"secondary","type":"boolean | undefined","required":false,"description":"The solid neutral tile: the `secondary` fill inside the `border` hairline, the glyph in the second ink (`muted-foreground`), with no lit top edge (the hand-off's neutral tile).","default":"false","group":0},{"name":"muted","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default medium).","default":"false","group":1},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default medium).","default":"false","group":1},{"name":"circle","type":"boolean | undefined","required":false,"description":"Circle instead of the default rounded square.","default":"false","group":1},{"name":"soft","type":"boolean | undefined","required":false,"description":"The plain soft tile: the tone's own soft wash (`primary-soft`, `destructive-soft`, ...) with no ring and no lit top edge, at the soft tile's own corner. The tone tile a dialog draws over its title (the v4 hand-off's AlertDialog renderer, `--ion-soft` / `--bad-soft`). Composes with the tone and size axes.","default":"false","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"For layout composition only (not styling): the tint, radius, and size come from props.","group":1}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (pick one; default `muted`). Sets the tinted surface and the icon color. Precedence: primary > destructive > success > warning > cyan > secondary > muted."},{"title":"Size","pickOne":true,"note":"Size (pick one; default medium)."}],"inherits":[]}],"platformNotes":{"web":"A tinted rounded square (or circle) that holds a single `Icon` or a short\nmonogram, the recurring \"icon on a soft background\" used in cards, media objects,\nempty states, and feeds. Emblem owns the surface and the icon color: pick a tone\nand it tints the square and paints the glyph to match, so a call site never\nhand-composes `borderRadius` + `backgroundColor` to build an icon background.","ios":"A tinted rounded square (or circle) that holds a single `Icon` or a short\nmonogram, the recurring \"icon on a soft background\" used in cards, media objects,\nempty states, and feeds. Emblem owns the surface and the icon color: pick a tone\nand it tints the square and paints the glyph to match, so a call site never\nhand-composes `borderRadius` + `backgroundColor` to build an icon background.","android":"A tinted rounded square (or circle) that holds a single `Icon` or a short\nmonogram, the recurring \"icon on a soft background\" used in cards, media objects,\nempty states, and feeds. Emblem owns the surface and the icon color: pick a tone\nand it tints the square and paints the glyph to match, so a call site never\nhand-composes `borderRadius` + `backgroundColor` to build an icon background."}},{"slug":"empty-state","name":"EmptyState","category":"molecules","description":"Centered, calm, never blame the user. Always tell them what could be here, and ideally how to get there.","source":"src/molecules/empty-state/empty-state.md","url":"https://canvas.nannier.com/ai/4.2.0/components/empty-state.md","humanUrl":"https://canvas.nannier.com/components/empty-state","exports":["EmptyState","EmptyStateProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"EmptyStateProps","props":[{"name":"icon","type":"string | ReactElement<unknown, string | React.JSXElementConstructor<any>> | undefined","required":false,"description":"The glyph shown in the disc: a monochrome `<Icon />` element (cloned with the tone's tint and the disc's glyph size, so it follows `success`/default like the disc wash does; a semantic color boolean on the element still wins) or an emoji/character string."},{"name":"title","type":"string | undefined","required":false,"description":"Short, neutral headline naming the empty result."},{"name":"description","type":"string | undefined","required":false,"description":"One reassuring line, ideally pointing at the next step."},{"name":"actionLabel","type":"string | undefined","required":false,"description":"When set, renders a secondary action button below the description (small when `compact`)."},{"name":"onAction","type":"(() => void) | undefined","required":false,"description":"Called when the action button is pressed."},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone axis (pick one; default keeps the disc muted).","default":"false","group":0},{"name":"bordered","type":"boolean | undefined","required":false,"description":"Container axis: wrap the column in a bordered card.","default":"false","group":1},{"name":"elevated","type":"boolean | undefined","required":false,"description":"A shaded card: the `card` fill under the medium shade.","default":"false","group":1},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density axis: tightens the padding, rhythm, tile and title.","default":"false","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":2}],"groups":[{"title":"Tone axis","pickOne":true,"note":"Tone axis (pick one; default keeps the disc muted)."},{"title":"Container axis","pickOne":false,"note":"Container axis: wrap the column in a bordered card."},{"title":"Density axis","pickOne":false,"note":"Density axis: tightens the padding, rhythm, tile and title."}],"inherits":[]}],"platformNotes":{"web":"Centered, calm, never blame the user. Always tell them what could be here, and ideally how to get there.\n\nThe column is padded 40 by 24 at an 18px corner with a 12px rhythm: a 52px glyph tile in\nthe accent's soft wash, a 19px display-face title, a muted 14px description capped at\n320px, and a secondary action. `bordered` draws a dashed edge, `elevated` lifts it onto a\nshaded card, and `compact` tightens the padding, rhythm, tile and title for a table cell.","ios":"Centered, calm, never blame the user. Always tell them what could be here, and ideally how to get there.\n\nThe column is padded 40 by 24 at an 18px corner with a 12px rhythm: a 52px glyph tile in\nthe accent's soft wash, a 19px display-face title, a muted 14px description capped at\n320px, and a secondary action. `bordered` draws a dashed edge, `elevated` lifts it onto a\nshaded card, and `compact` tightens the padding, rhythm, tile and title for a table cell.","android":"Centered, calm, never blame the user. Always tell them what could be here, and ideally how to get there.\n\nThe column is padded 40 by 24 at an 18px corner with a 12px rhythm: a 52px glyph tile in\nthe accent's soft wash, a 19px display-face title, a muted 14px description capped at\n320px, and a secondary action. `bordered` draws a dashed edge, `elevated` lifts it onto a\nshaded card, and `compact` tightens the padding, rhythm, tile and title for a table cell."}},{"slug":"feeds","name":"Feed","category":"molecules","description":"Vertical activity streams with icons and timestamps. Used for audit logs, change history, and notification lists.","source":"src/molecules/feeds/feeds.md","url":"https://canvas.nannier.com/ai/4.2.0/components/feeds.md","humanUrl":"https://canvas.nannier.com/components/feeds","exports":["Feed","FeedItem","FeedProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"FeedProps","props":[{"name":"items","type":"FeedItem[] | undefined","required":false,"description":"Events to render, top to bottom."},{"name":"activity","type":"boolean | undefined","required":false,"description":"Lead axis (pick one; default is the connector node + vertical line).","default":"false","group":0},{"name":"trace","type":"boolean | undefined","required":false,"description":"Lead axis (pick one; default is the connector node + vertical line).","default":"false","group":0},{"name":"connector","type":"boolean | undefined","required":false,"description":"Lead axis (pick one; default is the connector node + vertical line).","default":"false","group":0},{"name":"avatar","type":"boolean | undefined","required":false,"description":"Lead axis (pick one; default is the connector node + vertical line).","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density modifier: tightens the row padding and connector spacing.","default":"false","group":1},{"name":"onItemPress","type":"((index: number) => void) | undefined","required":false,"description":"When set, each event row is pressable, reporting the row index.","group":1},{"name":"label","type":"string | undefined","required":false,"description":"The feed's accessible name (e.g. \"Recent activity\"): a screen reader announces it with the list of events. A `virtualized` feed needs one: on the web its scroller is a keyboard stop while the events overflow, and Chromium names an unnamed stop from the text of every event it has rendered.","group":1},{"name":"virtualized","type":"boolean | undefined","required":false,"description":"Render the rows through a windowed `FlatList` instead of mounting every row up front, for large lists. Give the list a bounded height (via `style`, e.g. `{ maxHeight: 400 }`) so it can scroll; without one it warns and renders eagerly anyway. Default (omitted) mounts all rows, unchanged. On the web, while the rows overflow, the windowed list is a keyboard tab stop the keyboard can scroll, and the feed's card draws the focus ring while it has keyboard focus.","default":"false","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Lead axis","pickOne":true,"note":"Lead axis (pick one; default is the connector node + vertical line)."},{"title":"Density modifier","pickOne":false,"note":"Density modifier: tightens the row padding and connector spacing."}],"inherits":[]}],"platformNotes":{"web":"Vertical activity streams with icons and timestamps. Used for audit logs, change history, and notification lists.\n\nThe events are a list, as in Tailwind UI, and each event is one of its items: a\nscreen reader announces the list with its number of events and moves through it\nevent by event. A pressable event is a button inside its item. The `label` prop\nnames the list (for example \"Recent activity\").\n\nA `virtualized` feed with a bounded height scrolls its events in a list of its\nown. On the web, while those events overflow, that list is a keyboard tab stop\n(before the rows themselves when `onItemPress` makes them buttons), the\nkeyboard can scroll it, and while it has keyboard focus the feed's card draws\nthe theme's focus ring. Only the events near its viewport are mounted, and each\nsays where it sits in the whole feed, so a screen reader still counts every\nevent. Give a windowed feed a `label`: focused, a list with no name is named in\nChromium from the text of every event it has rendered, so the kit warns in\ndevelopment when it has none.\n\n`activity` provides the original Argus time gutter, sentence, and dividing rule.\n`trace` provides a colored marker, optional halo, optional numeric time gutter,\nand inline category label. These unframed rows inherit their owning panel. Pass\nrich `content`, marker `color` and `halo`, and optional `kind` on each item.","ios":"Vertical activity streams with icons and timestamps. Used for audit logs, change history, and notification lists.\n\nThe events are a list, as in Tailwind UI, and each event is one of its items: a\nscreen reader announces the list with its number of events and moves through it\nevent by event. A pressable event is a button inside its item. The `label` prop\nnames the list (for example \"Recent activity\").\n\nA `virtualized` feed with a bounded height scrolls its events in a list of its\nown. On the web, while those events overflow, that list is a keyboard tab stop\n(before the rows themselves when `onItemPress` makes them buttons), the\nkeyboard can scroll it, and while it has keyboard focus the feed's card draws\nthe theme's focus ring. Only the events near its viewport are mounted, and each\nsays where it sits in the whole feed, so a screen reader still counts every\nevent. Give a windowed feed a `label`: focused, a list with no name is named in\nChromium from the text of every event it has rendered, so the kit warns in\ndevelopment when it has none.\n\n`activity` provides the original Argus time gutter, sentence, and dividing rule.\n`trace` provides a colored marker, optional halo, optional numeric time gutter,\nand inline category label. These unframed rows inherit their owning panel. Pass\nrich `content`, marker `color` and `halo`, and optional `kind` on each item.","android":"Vertical activity streams with icons and timestamps. Used for audit logs, change history, and notification lists.\n\nThe events are a list, as in Tailwind UI, and each event is one of its items: a\nscreen reader announces the list with its number of events and moves through it\nevent by event. A pressable event is a button inside its item. The `label` prop\nnames the list (for example \"Recent activity\").\n\nA `virtualized` feed with a bounded height scrolls its events in a list of its\nown. On the web, while those events overflow, that list is a keyboard tab stop\n(before the rows themselves when `onItemPress` makes them buttons), the\nkeyboard can scroll it, and while it has keyboard focus the feed's card draws\nthe theme's focus ring. Only the events near its viewport are mounted, and each\nsays where it sits in the whole feed, so a screen reader still counts every\nevent. Give a windowed feed a `label`: focused, a list with no name is named in\nChromium from the text of every event it has rendered, so the kit warns in\ndevelopment when it has none.\n\n`activity` provides the original Argus time gutter, sentence, and dividing rule.\n`trace` provides a colored marker, optional halo, optional numeric time gutter,\nand inline category label. These unframed rows inherit their owning panel. Pass\nrich `content`, marker `color` and `halo`, and optional `kind` on each item."}},{"slug":"field","name":"Field","category":"molecules","description":"A form row: a label, the control, and one message line under it. Field exists for the part no control owns on its own: every field family already owns its label, but nothing else in the kit renders helper or error text, so that message is what Field adds.","source":"src/molecules/field/field.md","url":"https://canvas.nannier.com/ai/4.2.0/components/field.md","humanUrl":"https://canvas.nannier.com/components/field","exports":["Field","FieldProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"FieldProps","props":[{"name":"label","type":"string | undefined","required":false,"description":"Row label. When the lone child is a field-family control (Input, Textarea, Select, Autocomplete) that carries no `label` of its own, the label and `required` are DELEGATED into that control so each platform places them per its own contract. Any other control keeps the static label above."},{"name":"helper","type":"string | undefined","required":false,"description":"Muted hint under the control. Replaced by `error` when that is set."},{"name":"error","type":"string | undefined","required":false,"description":"Error text. Setting it puts the row in the error state: the message turns destructive and replaces `helper` in place, so the row never changes height and nothing below it jumps."},{"name":"required","type":"boolean | undefined","required":false,"description":"Marks the label with a destructive asterisk (decorative, never in an accessible name). A delegated control takes `required` and announces itself as required; over any other control, the label says it in its own name on iOS and Android (\"Notifications, required\").","default":"false"},{"name":"children","type":"ReactNode","required":false,"description":"The control."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds."},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":0}],"groups":[{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"A form row: a label, the control, and one message line under it. Field exists\nfor the part no control owns on its own: every field family already owns its\nlabel, but nothing else in the kit renders helper or error text, so that message\nis what Field adds.\n\nWhen the row wraps a single field-family control that has no label of its own,\nField hands the label down to it rather than drawing one alongside,\nso each\nplatform still places it its own way: a static title above on web and iOS, the\nfloating in-container label on Android, and `required` goes down with it.\nOver\nany other control (a Switch, a group) Field draws the label above with its star,\nand on iOS and Android the label says \"required\" in its own name.\nSet `error` and it replaces `helper` in\nthe same slot, so the row never changes height and nothing below it jumps; on the\nweb an error leads with a small alert glyph.","ios":"A form row: a label, the control, and one message line under it. Field exists\nfor the part no control owns on its own: every field family already owns its\nlabel, but nothing else in the kit renders helper or error text, so that message\nis what Field adds.\n\nWhen the row wraps a single field-family control that has no label of its own,\nField hands the label down to it rather than drawing one alongside,\nso the platform still places it its own way: a static title above, and `required` goes down with it.\nOver\nany other control (a Switch, a group) Field draws the label above with its star,\nand the label says \"required\" in its own name.\nSet `error` and it replaces `helper` in\nthe same slot, so the row never changes height and nothing below it jumps; on the\nweb an error leads with a small alert glyph.","android":"A form row: a label, the control, and one message line under it. Field exists\nfor the part no control owns on its own: every field family already owns its\nlabel, but nothing else in the kit renders helper or error text, so that message\nis what Field adds.\n\nWhen the row wraps a single field-family control that has no label of its own,\nField hands the label down to it rather than drawing one alongside,\nso the platform still places it its own way: the floating in-container label, and `required` goes down with it.\nOver\nany other control (a Switch, a group) Field draws the label above with its star,\nand the label says \"required\" in its own name.\nSet `error` and it replaces `helper` in\nthe same slot, so the row never changes height and nothing below it jumps; on the\nweb an error leads with a small alert glyph."}},{"slug":"filter-panel","name":"FilterPanel","category":"organisms","description":"Sidebar filter rail: grouped checkbox options under mono group headings, each with its count, and a \"Clear N\" action in the header while any filter is on (a plain accent text action). On the web an option's label is the 400 14px row label, 10px from its box.","source":"src/organisms/filter-panel/filter-panel.md","url":"https://canvas.nannier.com/ai/4.2.0/components/filter-panel.md","humanUrl":"https://canvas.nannier.com/components/filter-panel","exports":["FilterGroup","FilterOption","FilterPanel","FilterPanelProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"FilterPanelProps","props":[{"name":"groups","type":"FilterGroup[]","required":true,"description":"Filter groups, each a heading plus its checkbox options."},{"name":"value","type":"string[] | undefined","required":false,"description":"Controlled selection: the keys of the checked options (each option's `value`, falling back to `\"groupIndex:optionIndex\"`). Provide it with `onSelectionChange` to drive or reset selection from a parent (e.g. from a URL query)."},{"name":"defaultValue","type":"string[] | undefined","required":false,"description":"Initial selection for uncontrolled use. When omitted, the panel seeds from each option's `checked` flag."},{"name":"activeCount","type":"number | undefined","required":false,"description":"Active-filter count shown in the header's \"Clear N\" action. Omit to derive it from the checked options."},{"name":"onClear","type":"(() => void) | undefined","required":false,"description":"Fired when the header \"Clear N\" action is pressed (it shows while a filter is on)."},{"name":"onSelectionChange","type":"((selected: string[]) => void) | undefined","required":false,"description":"Fired with the full set of checked keys whenever the selection changes (both modes) — the controlled signal a parent mirrors into `value`."},{"name":"onChange","type":"((groupIndex: number, optionIndex: number, next: boolean) => void) | undefined","required":false,"description":"Fired when a single option row toggles, with its group/option indexes and next value. Fires alongside `onSelectionChange`."},{"name":"bordered","type":"boolean | undefined","required":false,"description":"Surface (pick one path): a rounded, bordered card vs. a bare panel.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (pick one): tighten the panel's padding and row spacing.","default":"false","group":1},{"name":"responsive","type":"boolean | undefined","required":false,"description":"Opt in to the responsive panel->drawer behavior. Off by default: a bare panel is the docked column at every width, exactly as before.","default":"false","group":2},{"name":"drawerBreakpoint","type":"BreakpointKey | undefined","required":false,"description":"The width at and below which `responsive` collapses to the drawer (default `sm` = 640).","group":2},{"name":"open","type":"boolean | undefined","required":false,"description":"The responsive drawer's open state (CONTROLLED). Omit for the self-managed trigger button.","default":"false","group":2},{"name":"defaultOpen","type":"boolean | undefined","required":false,"description":"Initial open state for the uncontrolled responsive drawer (default closed).","default":"false","group":2},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the responsive drawer opens or closes (trigger, scrim, back).","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook.","group":2}],"groups":[{"title":"Surface","pickOne":true,"note":"Surface (pick one path): a rounded, bordered card vs. a bare panel."},{"title":"Density","pickOne":true,"note":"Density (pick one): tighten the panel's padding and row spacing."},{"title":"Responsive drawer axis","pickOne":false,"note":"Responsive drawer axis: at and below `drawerBreakpoint` the docked panel collapses to a kit-owned \"Filters\" secondary Button (carrying the count) that opens the panel inside a start-edge Drawer, so a phone keeps its width for the results."}],"inherits":[]}],"platformNotes":{"web":"Sidebar filter rail: grouped checkbox options under mono group headings, each\nwith its count, and a \"Clear N\" action in the header while any filter is on (a plain\naccent text action). On the web an option's label is the 400 14px row label, 10px from its box.\n\nAdd `responsive` and at and below `drawerBreakpoint` (default `sm` = 640) the\ndocked panel collapses to a small secondary \"Filters\" button, carrying the live\ncount, that opens the same\npanel inside a start-edge drawer, so a phone keeps its width for the results;\n`open` / `defaultOpen` / `onOpenChange` drive the drawer for controlled use.\n\nOn iOS an option row marks a chosen filter the way an iOS list does: the label\nleads, the count follows, and a trailing check closes the row. The web and\nAndroid lead each row with the platform's selection checkbox. The native rows\nkeep the platform's touch height (44 pt, 48 dp).","ios":"Sidebar filter rail: grouped checkbox options under mono group headings, each\nwith its count, and a \"Clear N\" action in the header while any filter is on (a plain\naccent text action). On the web an option's label is the 400 14px row label, 10px from its box.\n\nAdd `responsive` and at and below `drawerBreakpoint` (default `sm` = 640) the\ndocked panel collapses to a small secondary \"Filters\" button, carrying the live\ncount, that opens the same\npanel inside a start-edge drawer, so a phone keeps its width for the results;\n`open` / `defaultOpen` / `onOpenChange` drive the drawer for controlled use.\n\nOn iOS an option row marks a chosen filter the way an iOS list does: the label leads, the count follows, and a trailing check closes the row. The native rows keep the platform's touch height (44 pt).","android":"Sidebar filter rail: grouped checkbox options under mono group headings, each\nwith its count, and a \"Clear N\" action in the header while any filter is on (a plain\naccent text action). On the web an option's label is the 400 14px row label, 10px from its box.\n\nAdd `responsive` and at and below `drawerBreakpoint` (default `sm` = 640) the\ndocked panel collapses to a small secondary \"Filters\" button, carrying the live\ncount, that opens the same\npanel inside a start-edge drawer, so a phone keeps its width for the results;\n`open` / `defaultOpen` / `onOpenChange` drive the drawer for controlled use.\n\nOn Android each row leads with the platform's selection checkbox. The native rows keep the platform's touch height (48 dp)."}},{"slug":"form","name":"Form","category":"molecules","description":"Stitch your own fields inside it; Form adds the stacked or two-column rhythm, titled sections, the submit and cancel actions row, and Enter to submit.","source":"src/molecules/form/form.md","url":"https://canvas.nannier.com/ai/4.2.0/components/form.md","humanUrl":"https://canvas.nannier.com/components/form","exports":["Form","FormProps","FormSection","FormSectionProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"FormSectionProps","props":[{"name":"title","type":"string | undefined","required":false,"description":"Section heading naming this group of controls."},{"name":"description","type":"ReactNode","required":false,"description":"Muted supporting line under the heading."},{"name":"aside","type":"boolean | undefined","required":false,"description":"Sets the heading in a rail beside the section's rows (a settings page's layout): the rail at the `xs` width step, 48 from the rows, with a 20 px display title over a 14 px description, the rows 18 apart, and 28 above and below the rows closed by a rule. In a section 512 px wide or narrower (the `lg` step, measured on the section itself) the rail stacks over the rows. Omit for the stacked default.","default":"false"},{"name":"children","type":"ReactNode","required":false,"description":"The section's stitched controls."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds."}],"groups":[],"inherits":[]},{"name":"FormProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"The form rows, stitched by the caller: Input, Select, Checkbox, a FormSection, any node. Each control keeps its own state (controlled or uncontrolled); Form never intercepts it."},{"name":"twoColumn","type":"boolean | undefined","required":false,"description":"Two-column: rows flow into a grid of exactly two equal columns, 16 apart, where a FormSection takes the whole line; in a form 512 px wide or narrower (the `lg` width step, measured on the form itself) the rows stack in one full-width column instead. Omit for the stacked default.","default":"false"},{"name":"hints","type":"ReactNode","required":false,"description":"Leading content of the actions row, before the buttons (keyboard hints such as \"↵ to save\"). The row then spreads the hints and the buttons to its two ends."},{"name":"submitLabel","type":"string | undefined","required":false,"description":"Label for the primary submit button. Passing it (or `cancelLabel`) renders the actions row."},{"name":"cancelLabel","type":"string | undefined","required":false,"description":"Renders a ghost cancel button before the submit button."},{"name":"block","type":"boolean | undefined","required":false,"description":"The actions take `block`: the cancel and submit buttons split the actions row equally (the Layout page's compact invite form, where the buttons go full width).","default":"false"},{"name":"onSubmit","type":"(() => void) | undefined","required":false,"description":"Fired when the submit button is pressed, and on the web when Enter is pressed inside one of the form's single-line text fields. Form owns no field state, so the caller reads its own values (no payload)."},{"name":"onCancel","type":"(() => void) | undefined","required":false,"description":"Fired when the cancel button is pressed."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Disables the actions row and Enter-to-submit, and dims the form.","default":"false"},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"The form's name for assistive tech, a brief statement of its purpose (\"Sign in\", \"Invite a teammate\"). Form is a form landmark on the web, and ARIA asks every form landmark for a name: it is how a landmark list tells two forms on one page apart. Omit it and the form stays unnamed, as before."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds."},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":0},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":0}],"groups":[{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"Stitch your own fields inside it; Form adds the stacked or two-column rhythm, titled sections, the submit and cancel actions row, and Enter to submit.\n\nThe actions row sits under a hairline rule, a ghost cancel before the primary submit; each FormSection closes with the same rule. A `disabled` form dims as a whole and disables its actions.\n\n`twoColumn` lays the rows out in exactly two equal columns 16px apart, however wide the form: the fields fill their columns left to right, an odd last field keeps its half, and a FormSection takes the whole row, after which the next field starts a new one. The form measures itself, and at 512px or narrower (the `lg` width step) the rows stack in one full-width column instead.\n\n`FormSection aside` sets the section's heading in a rail beside its rows, the layout of a\nsettings page: the rail at the `xs` width step (320px), 48px from the rows, a 20px title\nover a 14px description, the rows 18px apart, 28px above and below the rows and a rule\nclosing the section. The section measures itself, and at 512px or narrower (the `lg`\nwidth step) the rail stacks over the rows. A form whose last row is an aside section\ndrops the actions row's rule (the section's closes the rows). `hints` puts leading\ncontent in the actions row, before the buttons (the keyboard hints \"↵ to save\"), and the\nrow then spreads the two to its ends.","ios":"Stitch your own fields inside it; Form adds the stacked or two-column rhythm, titled sections, the submit and cancel actions row, and Enter to submit.\n\nThe actions row sits under a hairline rule, a ghost cancel before the primary submit; each FormSection closes with the same rule. A `disabled` form dims as a whole and disables its actions.\n\n`twoColumn` lays the rows out in exactly two equal columns 16px apart, however wide the form: the fields fill their columns left to right, an odd last field keeps its half, and a FormSection takes the whole row, after which the next field starts a new one. The form measures itself, and at 512px or narrower (the `lg` width step) the rows stack in one full-width column instead.\n\n`FormSection aside` sets the section's heading in a rail beside its rows, the layout of a\nsettings page: the rail at the `xs` width step (320px), 48px from the rows, a 20px title\nover a 14px description, the rows 18px apart, 28px above and below the rows and a rule\nclosing the section. The section measures itself, and at 512px or narrower (the `lg`\nwidth step) the rail stacks over the rows. A form whose last row is an aside section\ndrops the actions row's rule (the section's closes the rows). `hints` puts leading\ncontent in the actions row, before the buttons (the keyboard hints \"↵ to save\"), and the\nrow then spreads the two to its ends.","android":"Stitch your own fields inside it; Form adds the stacked or two-column rhythm, titled sections, the submit and cancel actions row, and Enter to submit.\n\nThe actions row sits under a hairline rule, a ghost cancel before the primary submit; each FormSection closes with the same rule. A `disabled` form dims as a whole and disables its actions.\n\n`twoColumn` lays the rows out in exactly two equal columns 16px apart, however wide the form: the fields fill their columns left to right, an odd last field keeps its half, and a FormSection takes the whole row, after which the next field starts a new one. The form measures itself, and at 512px or narrower (the `lg` width step) the rows stack in one full-width column instead.\n\n`FormSection aside` sets the section's heading in a rail beside its rows, the layout of a\nsettings page: the rail at the `xs` width step (320px), 48px from the rows, a 20px title\nover a 14px description, the rows 18px apart, 28px above and below the rows and a rule\nclosing the section. The section measures itself, and at 512px or narrower (the `lg`\nwidth step) the rail stacks over the rows. A form whose last row is an aside section\ndrops the actions row's rule (the section's closes the rows). `hints` puts leading\ncontent in the actions row, before the buttons (the keyboard hints \"↵ to save\"), and the\nrow then spreads the two to its ends."}},{"slug":"funnel-chart","name":"FunnelChart","category":"charts","description":"Stage-by-stage conversion bars: one centered row per stage, labelled on the left and valued on the right.","source":"src/charts/funnel-chart/funnel-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/funnel-chart.md","humanUrl":"https://canvas.nannier.com/components/funnel-chart","exports":["FunnelChart","FunnelChartProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"FunnelChartProps","props":[{"name":"stages","type":"StackedSegment[]","required":true,"description":"Ordered stages, widest first."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the funnel."},{"name":"share","type":"boolean | undefined","required":false,"description":"Show each stage as a share of the FIRST stage instead of the conversion from the previous stage.","default":"false"},{"name":"tapered","type":"boolean | undefined","required":false,"description":"Draw connected stage trapezoids and show counts alongside stage conversion.","default":"false"},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default funnel height).","default":"false","group":0},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":0},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats stage values (data formatting, not styling).","group":0},{"name":"selected","type":"number | null | undefined","required":false,"description":"Press-to-inspect: the selected stage index (controlled). Pass null for none.","group":0},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Press-to-inspect: the initially selected stage (uncontrolled).","group":0},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press selects a stage (or clears it with null).","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Density","pickOne":false,"note":"Density (omit for the default funnel height)."}],"inherits":[]}],"platformNotes":{"web":"Stage-by-stage conversion bars: one centered row per stage, labelled on the left and valued on the right.\n\nThe stages stack as a column of rows, each a ramp-colored bar centered in its track at the stage's share of the first stage's value, so the column tapers as the funnel drops off. The stage's label sits at the start of the row and its value, in the mono face, at the end; `share` shows every stage's percent of the first stage in the value slot instead. Each stage's accessible name carries its percent of the previous stage (of the first stage with `share`). Press a stage to select it (the others dim).","ios":"Stage-by-stage conversion bars: one centered row per stage, labelled on the left and valued on the right.\n\nThe stages stack as a column of rows, each a ramp-colored bar centered in its track at the stage's share of the first stage's value, so the column tapers as the funnel drops off. The stage's label sits at the start of the row and its value, in the mono face, at the end; `share` shows every stage's percent of the first stage in the value slot instead. Each stage's accessible name carries its percent of the previous stage (of the first stage with `share`). Press a stage to select it (the others dim).","android":"Stage-by-stage conversion bars: one centered row per stage, labelled on the left and valued on the right.\n\nThe stages stack as a column of rows, each a ramp-colored bar centered in its track at the stage's share of the first stage's value, so the column tapers as the funnel drops off. The stage's label sits at the start of the row and its value, in the mono face, at the end; `share` shows every stage's percent of the first stage in the value slot instead. Each stage's accessible name carries its percent of the previous stage (of the first stage with `share`). Press a stage to select it (the others dim)."}},{"slug":"gauge","name":"Gauge","category":"charts","description":"A semicircular dial: a 180 degree top arc (muted track plus a tone-colored value arc) for a 0-100 value, the percent readout in the open center of the semicircle, and an optional label below the graphic.","source":"src/charts/gauge/gauge.md","url":"https://canvas.nannier.com/ai/4.2.0/components/gauge.md","humanUrl":"https://canvas.nannier.com/components/gauge","exports":["Gauge","GaugeProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"GaugeProps","props":[{"name":"value","type":"number","required":true,"description":"The value to display, 0–100."},{"name":"label","type":"string | undefined","required":false,"description":"A short caption beneath the number (e.g. \"Uptime\")."},{"name":"primary","type":"boolean | undefined","required":false,"description":"Tone of the fill arc (pick one; default primary). Precedence when several are passed: success > warning > destructive (first match wins).","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Use the wider 250 px adoption dial.","default":"false","group":0},{"name":"success","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"warning","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"For sizing/composition only.","group":0}],"groups":[{"title":"Tone of the fill arc","pickOne":true,"note":"Tone of the fill arc (pick one; default primary). Precedence when several are passed: success > warning > destructive (first match wins)."}],"inherits":[]}],"platformNotes":{"web":"A semicircular dial: a 180 degree top arc (muted track plus a tone-colored value arc) for a 0-100 value, the percent readout in the open center of the semicircle, and an optional label below the graphic.","ios":"A semicircular dial: a 180 degree top arc (muted track plus a tone-colored value arc) for a 0-100 value, the percent readout in the open center of the semicircle, and an optional label below the graphic.","android":"A semicircular dial: a 180 degree top arc (muted track plus a tone-colored value arc) for a 0-100 value, the percent readout in the open center of the semicircle, and an optional label below the graphic."}},{"slug":"geo-map","name":"GeoMap","category":"charts","description":"A world map with a bubble per place, its area proportional to its count, over coastlines and country borders precomputed at build time. Optionally zoomable, merging crowded places into one bubble that splits as you zoom in.","source":"src/charts/geo-map/geo-map.md","url":"https://canvas.nannier.com/ai/4.2.0/components/geo-map.md","humanUrl":"https://canvas.nannier.com/components/geo-map","exports":["GeoMap","GeoMapPoint","GeoMapProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"GeoMapProps","props":[{"name":"points","type":"GeoMapPoint[]","required":true,"description":"The places to plot; every bubble takes the primary token."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the map."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default map size).","default":"false","group":0},{"name":"detailed","type":"boolean | undefined","required":false,"description":"Bordered geography panel with individually outlined place bubbles and an inline readout.","default":"false","group":0},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":0},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats the flagged and accessible counts (data formatting, not styling).","group":0},{"name":"selected","type":"number | null | undefined","required":false,"description":"Press-to-inspect: the selected point index (controlled). Pass null for none.","group":0},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Press-to-inspect: the initially selected point (uncontrolled).","group":0},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press selects a point (or clears it with null).","group":0},{"name":"zoomable","type":"boolean | undefined","required":false,"description":"Zoom and pan the map, and aggregate crowded places into one bubble that splits into its members as the map is driven in. The wheel zooms about the pointer, two fingers pinch, a drag pans once zoomed, and the zoom controls and arrow keys give the same reach without a pointer.","default":"false","group":0},{"name":"zoom","type":"number | undefined","required":false,"description":"The zoom factor, 1 (the whole world) upward (controlled). Needs `zoomable`.","group":0},{"name":"defaultZoom","type":"number | undefined","required":false,"description":"The zoom factor the map opens at (uncontrolled). Needs `zoomable`.","group":0},{"name":"onZoomChange","type":"((zoom: number) => void) | undefined","required":false,"description":"Fired whenever the zoom factor changes, by gesture, control or key.","group":0},{"name":"onSelectPlaces","type":"((indices: number[]) => void) | undefined","required":false,"description":"Fired alongside `onSelect` with EVERY point index inside the pressed bubble. A single place reports one index and an aggregated bubble reports all of its members, so `onSelect`'s own meaning never silently changes.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Density","pickOne":false,"note":"Density (omit for the default map size)."}],"inherits":[]}],"platformNotes":{"web":"A world map with a bubble per place, its area proportional to its count, over coastlines and country borders precomputed at build time. Optionally zoomable, merging crowded places into one bubble that splits as you zoom in.\n\nThe land silhouette and the shared country borders are two paths precomputed from Natural Earth 1:50m (no runtime fetch, no map dependency, no tiles), and each point is a circle at its projected coordinate whose AREA is proportional to its count, so doubling the count doubles the disc rather than its width.\n\nAdd `zoomable` and the wheel zooms about the pointer, two fingers pinch, a drag pans, and places too close together to draw separately merge into one bubble carrying their summed count, splitting into their members as you zoom in.\n\nSingle-identity encoding, so there is no tone axis and no legend. Press a bubble to flag its label and count (the others dim); the accessible name carries the biggest places with their values, because a screen reader user cannot see bubbles.\n\n`detailed` frames the geography and outlines every place separately, keeping all places visible while an inline readout identifies the selected city. Zoom, pan and keyboard controls remain available.","ios":"A world map with a bubble per place, its area proportional to its count, over coastlines and country borders precomputed at build time. Optionally zoomable, merging crowded places into one bubble that splits as you zoom in.\n\nThe land silhouette and the shared country borders are two paths precomputed from Natural Earth 1:50m (no runtime fetch, no map dependency, no tiles), and each point is a circle at its projected coordinate whose AREA is proportional to its count, so doubling the count doubles the disc rather than its width.\n\nAdd `zoomable` and the wheel zooms about the pointer, two fingers pinch, a drag pans, and places too close together to draw separately merge into one bubble carrying their summed count, splitting into their members as you zoom in.\n\nSingle-identity encoding, so there is no tone axis and no legend. Press a bubble to flag its label and count (the others dim); the accessible name carries the biggest places with their values, because a screen reader user cannot see bubbles.\n\n`detailed` frames the geography and outlines every place separately, keeping all places visible while an inline readout identifies the selected city. Zoom, pan and keyboard controls remain available.","android":"A world map with a bubble per place, its area proportional to its count, over coastlines and country borders precomputed at build time. Optionally zoomable, merging crowded places into one bubble that splits as you zoom in.\n\nThe land silhouette and the shared country borders are two paths precomputed from Natural Earth 1:50m (no runtime fetch, no map dependency, no tiles), and each point is a circle at its projected coordinate whose AREA is proportional to its count, so doubling the count doubles the disc rather than its width.\n\nAdd `zoomable` and the wheel zooms about the pointer, two fingers pinch, a drag pans, and places too close together to draw separately merge into one bubble carrying their summed count, splitting into their members as you zoom in.\n\nSingle-identity encoding, so there is no tone axis and no legend. Press a bubble to flag its label and count (the others dim); the accessible name carries the biggest places with their values, because a screen reader user cannot see bubbles.\n\n`detailed` frames the geography and outlines every place separately, keeping all places visible while an inline readout identifies the selected city. Zoom, pan and keyboard controls remain available."}},{"slug":"grid","name":"Grid","category":"atoms","description":"The container-measured auto-fit tile grid. `minTileWidth` sets the floor (default 240): the grid fits as many equal-width columns of at least that width as its own measured container allows, and re-fits as the container changes, so the same grid renders three-up on a desktop, two-up on a tablet, and a single column on a phone with no breakpoint at the call site.","source":"src/atoms/grid/grid.md","url":"https://canvas.nannier.com/ai/4.2.0/components/grid.md","humanUrl":"https://canvas.nannier.com/components/grid","exports":["Grid","GridItem","GridItemProps","GridProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"GridProps","props":[{"name":"flow","type":"boolean | undefined","required":false,"description":"Natural card heights with the original Argus subpixel width allowance.","default":"false"},{"name":"rowsCozy","type":"boolean | undefined","required":false,"description":"Separate vertical rhythm for wrapped rows.","default":"false"},{"name":"rowsSection","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"fine","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"dense","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"compact","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"close","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"nested","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"comfortable","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"balanced","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"roomy","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"airy","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"spacious","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"generous","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"section","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"panel","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"page","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"apart","type":"boolean | undefined","required":false,"description":"The step between side-by-side panels of one composition (32).","default":"false"},{"name":"ample","type":"boolean | undefined","required":false,"description":"The step between a section page's hero and its body, and between the hero's halves (40).","default":"false"},{"name":"broad","type":"boolean | undefined","required":false,"description":"The gap between the two halves of a page-wide split (48): the hand-off's hero grid.","default":"false"},{"name":"chapter","type":"boolean | undefined","required":false,"description":"The widest gap step (64), between a page's chapters; wins over every other step.","default":"false"},{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"minTileWidth","type":"number | undefined","required":false,"description":"Minimum tile width in px (default 240): the grid fits as many columns of at least this width as its measured container allows (auto-fit).","default":"240"},{"name":"columns","type":"number | undefined","required":false,"description":"Column cap: never more than this many columns (the desktop count). The count still drops below the cap as the container narrows, so a capped grid still collapses to one column on phones."},{"name":"flush","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`): Row/Column's axis and precedence.","default":"false","group":0},{"name":"tight","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`): Row/Column's axis and precedence.","default":"false","group":0},{"name":"snug","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`): Row/Column's axis and precedence.","default":"false","group":0},{"name":"cozy","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`): Row/Column's axis and precedence.","default":"false","group":0},{"name":"relaxed","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`): Row/Column's axis and precedence.","default":"false","group":0},{"name":"loose","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`): Row/Column's axis and precedence.","default":"false","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"For sizing/composition only (e.g. `maxWidth` to bound the grid), never a restyle hook; layout comes from the props above.","group":0}],"groups":[{"title":"Gap scale","pickOne":true,"note":"Gap scale (pick one; default `snug`): Row/Column's axis and precedence."}],"inherits":[]},{"name":"GridItemProps","props":[{"name":"full","type":"boolean | undefined","required":false,"description":"Span the whole row.","default":"false"},{"name":"raised","type":"boolean | undefined","required":false,"description":"Stack above adjacent resting cells.","default":"false"},{"name":"front","type":"boolean | undefined","required":false,"description":"Stack above a raised banner while lifting.","default":"false"},{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"wide","type":"boolean | undefined","required":false,"description":"Span two cells when the grid has more than one column (a hero tile). One cell in a one-column grid.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the item element."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"The container-measured auto-fit tile grid. `minTileWidth` sets the floor\n(default 240): the grid fits as many equal-width columns of at least that width\nas its own measured container allows, and re-fits as the container changes, so\nthe same grid renders three-up on a desktop, two-up on a tablet, and a single\ncolumn on a phone with no breakpoint at the call site.\n\n`columns` caps the count at the desktop number, the gap scale is Row and\nColumn's own (`flush` / `tight` / `snug` / `cozy` / `relaxed` / `loose`), and a\n`GridItem` child with `wide` spans two cells. The grid spans its parent's full\nwidth (it is a FILL component, so it needs no wrapper to reach the edges), and\nits tiles are equal-height as well as equal-width: every cell stretches to the\nheight of the row it wrapped onto, and a `Card` in a cell grows to fill it, so a\nrow of cards shares a flush bottom edge however unevenly their content runs (CSS\nGrid's `align-items: stretch`). A field or a hug component keeps its own height.\nEqual-width tiles belong here; content-sized rows that should stack at narrow\nwidths belong to `Row stacks`.\n\n`flow` preserves natural card heights and the original Argus one-pixel allowance\nwhen fitting columns. `GridItem full` spans a whole row; `raised` and `front` keep\nbanner and lifted-card shadows above adjacent cells. `rowsCozy` and `rowsSection`\nset the vertical rhythm to 12 or 26 independently of the horizontal gap.\n\nThe shared gap scale also includes `comfortable` (10), `roomy` (14), `generous`\n(22), `panel` (28), `apart` (32), `ample` (40, the step under a section page's hero) and\n`broad` (48), preserving the original application layout measurements,\nand Row and Column's widest step, `chapter` (64), which wins over every other step.","ios":"The container-measured auto-fit tile grid. `minTileWidth` sets the floor\n(default 240): the grid fits as many equal-width columns of at least that width\nas its own measured container allows, and re-fits as the container changes, so\nthe same grid renders three-up on a desktop, two-up on a tablet, and a single\ncolumn on a phone with no breakpoint at the call site.\n\n`columns` caps the count at the desktop number, the gap scale is Row and\nColumn's own (`flush` / `tight` / `snug` / `cozy` / `relaxed` / `loose`), and a\n`GridItem` child with `wide` spans two cells. The grid spans its parent's full\nwidth (it is a FILL component, so it needs no wrapper to reach the edges), and\nits tiles are equal-height as well as equal-width: every cell stretches to the\nheight of the row it wrapped onto, and a `Card` in a cell grows to fill it, so a\nrow of cards shares a flush bottom edge however unevenly their content runs (CSS\nGrid's `align-items: stretch`). A field or a hug component keeps its own height.\nEqual-width tiles belong here; content-sized rows that should stack at narrow\nwidths belong to `Row stacks`.\n\n`flow` preserves natural card heights and the original Argus one-pixel allowance\nwhen fitting columns. `GridItem full` spans a whole row; `raised` and `front` keep\nbanner and lifted-card shadows above adjacent cells. `rowsCozy` and `rowsSection`\nset the vertical rhythm to 12 or 26 independently of the horizontal gap.\n\nThe shared gap scale also includes `comfortable` (10), `roomy` (14), `generous`\n(22), `panel` (28), `apart` (32), `ample` (40, the step under a section page's hero) and\n`broad` (48), preserving the original application layout measurements,\nand Row and Column's widest step, `chapter` (64), which wins over every other step.","android":"The container-measured auto-fit tile grid. `minTileWidth` sets the floor\n(default 240): the grid fits as many equal-width columns of at least that width\nas its own measured container allows, and re-fits as the container changes, so\nthe same grid renders three-up on a desktop, two-up on a tablet, and a single\ncolumn on a phone with no breakpoint at the call site.\n\n`columns` caps the count at the desktop number, the gap scale is Row and\nColumn's own (`flush` / `tight` / `snug` / `cozy` / `relaxed` / `loose`), and a\n`GridItem` child with `wide` spans two cells. The grid spans its parent's full\nwidth (it is a FILL component, so it needs no wrapper to reach the edges), and\nits tiles are equal-height as well as equal-width: every cell stretches to the\nheight of the row it wrapped onto, and a `Card` in a cell grows to fill it, so a\nrow of cards shares a flush bottom edge however unevenly their content runs (CSS\nGrid's `align-items: stretch`). A field or a hug component keeps its own height.\nEqual-width tiles belong here; content-sized rows that should stack at narrow\nwidths belong to `Row stacks`.\n\n`flow` preserves natural card heights and the original Argus one-pixel allowance\nwhen fitting columns. `GridItem full` spans a whole row; `raised` and `front` keep\nbanner and lifted-card shadows above adjacent cells. `rowsCozy` and `rowsSection`\nset the vertical rhythm to 12 or 26 independently of the horizontal gap.\n\nThe shared gap scale also includes `comfortable` (10), `roomy` (14), `generous`\n(22), `panel` (28), `apart` (32), `ample` (40, the step under a section page's hero) and\n`broad` (48), preserving the original application layout measurements,\nand Row and Column's widest step, `chapter` (64), which wins over every other step."}},{"slug":"grid-lists","name":"GridList","category":"molecules","description":"Tiled card grids for people directories, item collections, and image galleries.","source":"src/molecules/grid-lists/grid-lists.md","url":"https://canvas.nannier.com/ai/4.2.0/components/grid-lists.md","humanUrl":"https://canvas.nannier.com/components/grid-lists","exports":["GridList","GridListAction","GridListItem","GridListProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"GridListProps","props":[{"name":"items","type":"GridListItem[]","required":true,"description":"The tiles to render, one card per entry."},{"name":"cols3","type":"boolean | undefined","required":false,"description":"Columns (pick one; default is three-up).","default":"false","group":0},{"name":"cols2","type":"boolean | undefined","required":false,"description":"Columns (pick one; default is three-up).","default":"false","group":0},{"name":"gallery","type":"boolean | undefined","required":false,"description":"Gallery mode: render each tile as a borderless thumbnail (a square color block from `item.color`, with a left-aligned filename and size below). Avatars, badges, and actions are not shown in this mode. Omit for the default people/card tile.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density modifier: tighter gap and tile padding.","default":"false","group":1},{"name":"onPressItem","type":"((index: number) => void) | undefined","required":false,"description":"Make each tile a tappable target (open a detail, select a tile). When set, every tile renders as a Pressable with a button role and a pressed affordance, so a tappable grid needs no hand-rolled Pressable.","group":1},{"name":"label","type":"string | undefined","required":false,"description":"The grid's accessible name (e.g. \"Team members\"): a screen reader announces it with the list of tiles. A `virtualized` grid needs one: on the web its scroller is a keyboard stop while the tiles overflow, and Chromium names an unnamed stop from the text of every tile it has rendered.","group":1},{"name":"virtualized","type":"boolean | undefined","required":false,"description":"Render the tiles through a windowed `FlatList` instead of mounting every tile up front, for large grids. Give the grid a bounded height (via `style`, e.g. `{ maxHeight: 480 }`) so it can scroll; without one it warns and renders eagerly anyway. Default (omitted) mounts all tiles, unchanged. On the web, while the tiles overflow, the windowed grid is a keyboard tab stop the keyboard can scroll, and it draws the focus ring around itself while it has keyboard focus.","default":"false","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Columns","pickOne":true,"note":"Columns (pick one; default is three-up)."},{"title":"Density modifier","pickOne":false,"note":"Density modifier: tighter gap and tile padding."}],"inherits":[]}],"platformNotes":{"web":"Tiled card grids for people directories, item collections, and image galleries.\n\nThe tiles are a list, as in Tailwind UI, and each tile is one of its items: a\nscreen reader announces the list with its number of tiles and moves through it\ntile by tile. A tappable tile is a button inside its item.\nThe `label` prop names the list (for example \"Team members\").\n\nA `virtualized` grid with a bounded height scrolls its tiles on its own. On the\nweb, while those tiles overflow, the grid is a keyboard tab stop (before the\ntiles themselves when `onPressItem` or tile actions make them buttons), the\nkeyboard can scroll it, and while it has keyboard focus the grid, which has no\ncard around it, draws the theme's focus ring around itself. Only the tiles near\nits viewport are mounted, and each says where it sits in the whole grid, so a\nscreen reader still counts every tile. Give a windowed grid a `label`: focused,\na list with no name is named in Chromium from the text of every tile it has\nrendered, so the kit warns in development when it has none.","ios":"Tiled card grids for people directories, item collections, and image galleries.\n\nThe tiles are a list, as in Tailwind UI, and each tile is one of its items: a\nscreen reader announces the list with its number of tiles and moves through it\ntile by tile. A tappable tile is a button inside its item.\nThe `label` prop names the list (for example \"Team members\").\n\nA `virtualized` grid with a bounded height scrolls its tiles on its own. On the\nweb, while those tiles overflow, the grid is a keyboard tab stop (before the\ntiles themselves when `onPressItem` or tile actions make them buttons), the\nkeyboard can scroll it, and while it has keyboard focus the grid, which has no\ncard around it, draws the theme's focus ring around itself. Only the tiles near\nits viewport are mounted, and each says where it sits in the whole grid, so a\nscreen reader still counts every tile. Give a windowed grid a `label`: focused,\na list with no name is named in Chromium from the text of every tile it has\nrendered, so the kit warns in development when it has none.","android":"Tiled card grids for people directories, item collections, and image galleries.\n\nThe tiles are a list, as in Tailwind UI, and each tile is one of its items: a\nscreen reader announces the list with its number of tiles and moves through it\ntile by tile. A tappable tile is a button inside its item.\nThe `label` prop names the list (for example \"Team members\").\n\nA `virtualized` grid with a bounded height scrolls its tiles on its own. On the\nweb, while those tiles overflow, the grid is a keyboard tab stop (before the\ntiles themselves when `onPressItem` or tile actions make them buttons), the\nkeyboard can scroll it, and while it has keyboard focus the grid, which has no\ncard around it, draws the theme's focus ring around itself. Only the tiles near\nits viewport are mounted, and each says where it sits in the whole grid, so a\nscreen reader still counts every tile. Give a windowed grid a `label`: focused,\na list with no name is named in Chromium from the text of every tile it has\nrendered, so the kit warns in development when it has none."}},{"slug":"heatmap","name":"Heatmap","category":"charts","description":"Density cells whose fill encodes each value, in seven-row columns inside the chart frame, titled by `label` (or `caption`) and closed by a less-to-more legend; `plain` strips the frame for nesting inside a card. Pass `calendar` for a GitHub-style contribution graph: each cell is a day, and a press or hover inspects its count and date. The calendar layout IS the kit's activity calendar, so a contribution graph needs no separate component.","source":"src/charts/heatmap/heatmap.md","url":"https://canvas.nannier.com/ai/4.2.0/components/heatmap.md","humanUrl":"https://canvas.nannier.com/components/heatmap","exports":["Heatmap","HeatmapProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"HeatmapProps","props":[{"name":"values","type":"HeatmapValue[]","required":true,"description":"The cells: intensities 0–1, or `{ value, count?, date?, label? }` for inspectable data."},{"name":"label","type":"string | undefined","required":false,"description":"What the grid measures (e.g. \"Contribution activity\"); leads the accessible name."},{"name":"calendar","type":"boolean | undefined","required":false,"description":"GitHub-style: the cells are days, each inspectable for its count and date.","default":"false"},{"name":"detailed","type":"boolean | undefined","required":false,"description":"Unframed contribution calendar with the authored month, weekday and level styling.","default":"false"},{"name":"caption","type":"string | undefined","required":false,"description":"A summary line above the grid (e.g. \"248 contributions in the last year\"); shown in place of `label`."},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false"},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Hide the less-to-more legend row.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"For sizing/composition only."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"Density cells whose fill encodes each value, in seven-row columns inside the chart frame, titled by `label` (or `caption`) and closed by a less-to-more legend; `plain` strips the frame for nesting inside a card. Pass `calendar` for a GitHub-style contribution graph: each cell is a day, and a press or hover inspects its count and date. The calendar layout IS the kit's activity calendar, so a contribution graph needs no separate component.\n\n`detailed` keeps contribution-calendar cells at their authored size, unframed, with compact month and weekday labels and the contribution-count color levels. A narrow parent scrolls the same calendar.","ios":"Density cells whose fill encodes each value, in seven-row columns inside the chart frame, titled by `label` (or `caption`) and closed by a less-to-more legend; `plain` strips the frame for nesting inside a card. Pass `calendar` for a GitHub-style contribution graph: each cell is a day, and a press or hover inspects its count and date. The calendar layout IS the kit's activity calendar, so a contribution graph needs no separate component.\n\n`detailed` keeps contribution-calendar cells at their authored size, unframed, with compact month and weekday labels and the contribution-count color levels. A narrow parent scrolls the same calendar.","android":"Density cells whose fill encodes each value, in seven-row columns inside the chart frame, titled by `label` (or `caption`) and closed by a less-to-more legend; `plain` strips the frame for nesting inside a card. Pass `calendar` for a GitHub-style contribution graph: each cell is a day, and a press or hover inspects its count and date. The calendar layout IS the kit's activity calendar, so a contribution graph needs no separate component.\n\n`detailed` keeps contribution-calendar cells at their authored size, unframed, with compact month and weekday labels and the contribution-count color levels. A narrow parent scrolls the same calendar."}},{"slug":"histogram","name":"Histogram","category":"charts","description":"An auto-binned frequency distribution: pass raw sample `values` and the chart bins them into nice-edged uniform buckets (Sturges' rule by default, `bins` to override) and draws contiguous bars on a numeric axis. Press or scrub a bar to inspect its range and count. The accessible name lists every bin with its bounds and tally.","source":"src/charts/histogram/histogram.md","url":"https://canvas.nannier.com/ai/4.2.0/components/histogram.md","humanUrl":"https://canvas.nannier.com/components/histogram","exports":["Histogram","HistogramProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"HistogramProps","props":[{"name":"values","type":"number[]","required":true,"description":"Raw sample values; the chart bins them."},{"name":"bins","type":"number | undefined","required":false,"description":"Bucket count override. Defaults to Sturges' rule on the sample size."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"label","type":"string | undefined","required":false,"description":"Names the distribution (e.g. \"Response times\"); leads the accessible name."},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (pick one; default primary). Precedence: success > destructive.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (pick one; default primary). Precedence: success > destructive.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":1},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":1},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":2},{"name":"hideAxes","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":2},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats bin edges in ticks, the flag, and the accessible name.","group":2},{"name":"selected","type":"number | null | undefined","required":false,"description":"Press-to-inspect: the selected bin index (controlled). Pass null for none.","group":2},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Press-to-inspect: the initially selected bin (uncontrolled).","group":2},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press selects a bin (or clears it with null).","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":2}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (pick one; default primary). Precedence: success > destructive."},{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."},{"title":"Furniture visibility","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"An auto-binned frequency distribution: pass raw sample `values` and the chart bins them into nice-edged uniform buckets (Sturges' rule by default, `bins` to override) and draws contiguous bars on a numeric axis. Press or scrub a bar to inspect its range and count. The accessible name lists every bin with its bounds and tally.","ios":"An auto-binned frequency distribution: pass raw sample `values` and the chart bins them into nice-edged uniform buckets (Sturges' rule by default, `bins` to override) and draws contiguous bars on a numeric axis. Press or scrub a bar to inspect its range and count. The accessible name lists every bin with its bounds and tally.","android":"An auto-binned frequency distribution: pass raw sample `values` and the chart bins them into nice-edged uniform buckets (Sturges' rule by default, `bins` to override) and draws contiguous bars on a numeric axis. Press or scrub a bar to inspect its range and count. The accessible name lists every bin with its bounds and tally."}},{"slug":"icon","name":"Icon","category":"atoms","description":"Lucide-style outline. 1.75 stroke width, rounded caps. The stroke defaults to the theme foreground token and tracks light and dark automatically; pick other hues with the semantic color booleans (`primary`, `destructive`, `success`, `warning`, `muted`, `subtle`; that order is the precedence). `muted` is the third ink (`subtle-foreground`) and `subtle` the second (`muted-foreground`), the names Typography gives the same two inks. Inside a control that owns a label ink (a Button's `iconLeft` and `iconRight` slots) a glyph with no tone takes that ink instead, the way the hand-off's icons inherit `currentColor`: the primary's contrast ink on a primary button, the muted ink on a quiet one. The precedence is the explicit tone, then the host's ink, then the foreground, so a toned glyph keeps its tone anywhere.","source":"src/atoms/icon/icon.md","url":"https://canvas.nannier.com/ai/4.2.0/components/icon.md","humanUrl":"https://canvas.nannier.com/components/icon","exports":["ICON_CATEGORIES","ICON_NAMES","Icon","IconCategory","IconName","IconProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"IconProps","props":[{"name":"disclosure","type":"boolean | undefined","required":false,"description":"Rotate the glyph as an Argus disclosure indicator.","default":"false"},{"name":"expanded","type":"boolean | undefined","required":false,"description":"Open state of a disclosure indicator.","default":"false"},{"name":"heavyStroke","type":"boolean | undefined","required":false,"description":"Strong action/link stroke from the Argus reference.","default":"false"},{"name":"boldStroke","type":"boolean | undefined","required":false,"description":"Standard emphasized metadata stroke.","default":"false"},{"name":"mediumStroke","type":"boolean | undefined","required":false,"description":"The medium toolbar stroke.","default":"false"},{"name":"regularStroke","type":"boolean | undefined","required":false,"description":"The fine navigation stroke.","default":"false"},{"name":"primary","type":"boolean | undefined","required":false,"description":"Color axis: pass one (default foreground). First match wins.","default":"false","group":0},{"name":"primaryForeground","type":"boolean | undefined","required":false,"description":"Contrast color for a glyph on a primary surface (e.g. a primary button).","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"success","type":"boolean | undefined","required":false,"description":"Positive/green status (matches Alert's success tone, scheme-aware).","default":"false","group":0},{"name":"warning","type":"boolean | undefined","required":false,"description":"Caution/amber status (the warning token, scheme-aware; matches Alert/Toast warning).","default":"false","group":0},{"name":"muted","type":"boolean | undefined","required":false,"description":"The third ink (`subtle-foreground`, the hand-off's `--tx3`): a glyph that recedes.","default":"false","group":0},{"name":"subtle","type":"boolean | undefined","required":false,"description":"The second ink (`muted-foreground`, the hand-off's `--tx2`), as Typography's `subtle`.","default":"false","group":0},{"name":"cell","type":"boolean | undefined","required":false,"description":"The glyph centred in a square cell that fills its parent (a Grid tile of a glyph gallery) at a 10 px corner. On the web a hovered cell takes the accent's soft wash and its glyph the accent ink.","default":"false","group":0},{"name":"size","type":"number | undefined","required":false,"description":"Single-glyph size in px (default 24).","group":1},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for a MEANINGFUL standalone icon (one that conveys information not repeated in adjacent text, e.g. an icon-only button's glyph). Marks the glyph `role=\"img\"` with this label on web and native.","group":1},{"name":"decorative","type":"boolean | undefined","required":false,"description":"Mark a DECORATIVE/ornamental glyph (one paired with a text label, a separator chevron, an empty-state illustration) so assistive tech skips it. Hides it via aria-hidden on web and importantForAccessibility on native.","default":"false","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1},{"name":"accessibility","type":"boolean | undefined","required":false,"description":"`accessibility`"},{"name":"activity","type":"boolean | undefined","required":false,"description":"`activity`"},{"name":"alarmClock","type":"boolean | undefined","required":false,"description":"`alarm-clock`"},{"name":"alertTriangle","type":"boolean | undefined","required":false,"description":"`triangle-alert`"},{"name":"alignLeft","type":"boolean | undefined","required":false,"description":"`text-align-start`"},{"name":"anchor","type":"boolean | undefined","required":false,"description":"`anchor`"},{"name":"apple","type":"boolean | undefined","required":false,"description":"`apple`"},{"name":"appWindow","type":"boolean | undefined","required":false,"description":"`app-window`"},{"name":"archive","type":"boolean | undefined","required":false,"description":"`archive`"},{"name":"arrowDown","type":"boolean | undefined","required":false,"description":"`arrow-down`"},{"name":"arrowDownLeft","type":"boolean | undefined","required":false,"description":"`arrow-down-left`"},{"name":"arrowDownRight","type":"boolean | undefined","required":false,"description":"`arrow-down-right`"},{"name":"arrowLeft","type":"boolean | undefined","required":false,"description":"`arrow-left`"},{"name":"arrowRight","type":"boolean | undefined","required":false,"description":"`arrow-right`"},{"name":"arrowUp","type":"boolean | undefined","required":false,"description":"`arrow-up`"},{"name":"arrowUpLeft","type":"boolean | undefined","required":false,"description":"`arrow-up-left`"},{"name":"arrowUpRight","type":"boolean | undefined","required":false,"description":"`arrow-up-right`"},{"name":"asterisk","type":"boolean | undefined","required":false,"description":"`asterisk`"},{"name":"atSign","type":"boolean | undefined","required":false,"description":"`at-sign`"},{"name":"award","type":"boolean | undefined","required":false,"description":"`award`"},{"name":"baby","type":"boolean | undefined","required":false,"description":"`baby`"},{"name":"badge","type":"boolean | undefined","required":false,"description":"`badge`"},{"name":"badgeCheck","type":"boolean | undefined","required":false,"description":"`badge-check`"},{"name":"banknote","type":"boolean | undefined","required":false,"description":"`banknote`"},{"name":"barChart2","type":"boolean | undefined","required":false,"description":"`chart-no-axes-column`"},{"name":"battery","type":"boolean | undefined","required":false,"description":"`battery`"},{"name":"batteryCharging","type":"boolean | undefined","required":false,"description":"`battery-charging`"},{"name":"batteryFull","type":"boolean | undefined","required":false,"description":"`battery-full`"},{"name":"batteryLow","type":"boolean | undefined","required":false,"description":"`battery-low`"},{"name":"bell","type":"boolean | undefined","required":false,"description":"`bell`"},{"name":"bellOff","type":"boolean | undefined","required":false,"description":"`bell-off`"},{"name":"bellRing","type":"boolean | undefined","required":false,"description":"`bell-ring`"},{"name":"bike","type":"boolean | undefined","required":false,"description":"`bike`"},{"name":"binary","type":"boolean | undefined","required":false,"description":"`binary`"},{"name":"bird","type":"boolean | undefined","required":false,"description":"`bird`"},{"name":"blend","type":"boolean | undefined","required":false,"description":"`blend`"},{"name":"bluetooth","type":"boolean | undefined","required":false,"description":"`bluetooth`"},{"name":"book","type":"boolean | undefined","required":false,"description":"`book`"},{"name":"bookmark","type":"boolean | undefined","required":false,"description":"`bookmark`"},{"name":"bookOpen","type":"boolean | undefined","required":false,"description":"`book-open`"},{"name":"bookOpenText","type":"boolean | undefined","required":false,"description":"`book-open-text`"},{"name":"bot","type":"boolean | undefined","required":false,"description":"`bot`"},{"name":"box","type":"boolean | undefined","required":false,"description":"`box`"},{"name":"braces","type":"boolean | undefined","required":false,"description":"`braces`"},{"name":"brackets","type":"boolean | undefined","required":false,"description":"`brackets`"},{"name":"briefcase","type":"boolean | undefined","required":false,"description":"`briefcase`"},{"name":"brush","type":"boolean | undefined","required":false,"description":"`brush`"},{"name":"bug","type":"boolean | undefined","required":false,"description":"`bug`"},{"name":"building","type":"boolean | undefined","required":false,"description":"`building`"},{"name":"building2","type":"boolean | undefined","required":false,"description":"`building-2`"},{"name":"calculator","type":"boolean | undefined","required":false,"description":"`calculator`"},{"name":"calendar","type":"boolean | undefined","required":false,"description":"`calendar`"},{"name":"calendarCheck","type":"boolean | undefined","required":false,"description":"`calendar-check`"},{"name":"calendarClock","type":"boolean | undefined","required":false,"description":"`calendar-clock`"},{"name":"calendarDays","type":"boolean | undefined","required":false,"description":"`calendar-days`"},{"name":"camera","type":"boolean | undefined","required":false,"description":"`camera`"},{"name":"car","type":"boolean | undefined","required":false,"description":"`car`"},{"name":"carrot","type":"boolean | undefined","required":false,"description":"`carrot`"},{"name":"cast","type":"boolean | undefined","required":false,"description":"`cast`"},{"name":"cat","type":"boolean | undefined","required":false,"description":"`cat`"},{"name":"chartArea","type":"boolean | undefined","required":false,"description":"`chart-area`"},{"name":"chartBar","type":"boolean | undefined","required":false,"description":"`chart-bar`"},{"name":"chartColumn","type":"boolean | undefined","required":false,"description":"`chart-column`"},{"name":"chartLine","type":"boolean | undefined","required":false,"description":"`chart-line`"},{"name":"chartPie","type":"boolean | undefined","required":false,"description":"`chart-pie`"},{"name":"check","type":"boolean | undefined","required":false,"description":"`check`"},{"name":"checkSquare","type":"boolean | undefined","required":false,"description":"`square-check`"},{"name":"chevronDown","type":"boolean | undefined","required":false,"description":"`chevron-down`"},{"name":"chevronLeft","type":"boolean | undefined","required":false,"description":"`chevron-left`"},{"name":"chevronRight","type":"boolean | undefined","required":false,"description":"`chevron-right`"},{"name":"chevronsLeft","type":"boolean | undefined","required":false,"description":"`chevrons-left`"},{"name":"chevronsLeftRight","type":"boolean | undefined","required":false,"description":"`chevrons-left-right`"},{"name":"chevronsRight","type":"boolean | undefined","required":false,"description":"`chevrons-right`"},{"name":"chevronsUpDown","type":"boolean | undefined","required":false,"description":"`chevrons-up-down`"},{"name":"chevronUp","type":"boolean | undefined","required":false,"description":"`chevron-up`"},{"name":"circle","type":"boolean | undefined","required":false,"description":"`circle`"},{"name":"circleAlert","type":"boolean | undefined","required":false,"description":"`circle-alert`"},{"name":"circleCheck","type":"boolean | undefined","required":false,"description":"`circle-check`"},{"name":"circleCheckBig","type":"boolean | undefined","required":false,"description":"`circle-check-big`"},{"name":"circleDashed","type":"boolean | undefined","required":false,"description":"`circle-dashed`"},{"name":"circleDot","type":"boolean | undefined","required":false,"description":"`circle-dot`"},{"name":"circleMinus","type":"boolean | undefined","required":false,"description":"`circle-minus`"},{"name":"circlePlay","type":"boolean | undefined","required":false,"description":"`circle-play`"},{"name":"circlePlus","type":"boolean | undefined","required":false,"description":"`circle-plus`"},{"name":"circleQuestionMark","type":"boolean | undefined","required":false,"description":"`circle-question-mark`"},{"name":"circleUser","type":"boolean | undefined","required":false,"description":"`circle-user`"},{"name":"circleX","type":"boolean | undefined","required":false,"description":"`circle-x`"},{"name":"clapperboard","type":"boolean | undefined","required":false,"description":"`clapperboard`"},{"name":"clipboard","type":"boolean | undefined","required":false,"description":"`clipboard`"},{"name":"clipboardCheck","type":"boolean | undefined","required":false,"description":"`clipboard-check`"},{"name":"clipboardCopy","type":"boolean | undefined","required":false,"description":"`clipboard-copy`"},{"name":"clipboardList","type":"boolean | undefined","required":false,"description":"`clipboard-list`"},{"name":"clock","type":"boolean | undefined","required":false,"description":"`clock`"},{"name":"clock3","type":"boolean | undefined","required":false,"description":"`clock-3`"},{"name":"cloud","type":"boolean | undefined","required":false,"description":"`cloud`"},{"name":"cloudDownload","type":"boolean | undefined","required":false,"description":"`cloud-download`"},{"name":"cloudLightning","type":"boolean | undefined","required":false,"description":"`cloud-lightning`"},{"name":"cloudRain","type":"boolean | undefined","required":false,"description":"`cloud-rain`"},{"name":"cloudSnow","type":"boolean | undefined","required":false,"description":"`cloud-snow`"},{"name":"cloudSun","type":"boolean | undefined","required":false,"description":"`cloud-sun`"},{"name":"cloudUpload","type":"boolean | undefined","required":false,"description":"`cloud-upload`"},{"name":"code","type":"boolean | undefined","required":false,"description":"`code`"},{"name":"codeXml","type":"boolean | undefined","required":false,"description":"`code-xml`"},{"name":"coffee","type":"boolean | undefined","required":false,"description":"`coffee`"},{"name":"cog","type":"boolean | undefined","required":false,"description":"`cog`"},{"name":"coins","type":"boolean | undefined","required":false,"description":"`coins`"},{"name":"columns2","type":"boolean | undefined","required":false,"description":"`columns-2`"},{"name":"command","type":"boolean | undefined","required":false,"description":"`command`"},{"name":"compass","type":"boolean | undefined","required":false,"description":"`compass`"},{"name":"contact","type":"boolean | undefined","required":false,"description":"`contact`"},{"name":"copy","type":"boolean | undefined","required":false,"description":"`copy`"},{"name":"cornerDownRight","type":"boolean | undefined","required":false,"description":"`corner-down-right`"},{"name":"cpu","type":"boolean | undefined","required":false,"description":"`cpu`"},{"name":"creditCard","type":"boolean | undefined","required":false,"description":"`credit-card`"},{"name":"cross","type":"boolean | undefined","required":false,"description":"`cross`"},{"name":"crosshair","type":"boolean | undefined","required":false,"description":"`crosshair`"},{"name":"crown","type":"boolean | undefined","required":false,"description":"`crown`"},{"name":"database","type":"boolean | undefined","required":false,"description":"`database`"},{"name":"diamond","type":"boolean | undefined","required":false,"description":"`diamond`"},{"name":"disc","type":"boolean | undefined","required":false,"description":"`disc`"},{"name":"divide","type":"boolean | undefined","required":false,"description":"`divide`"},{"name":"dog","type":"boolean | undefined","required":false,"description":"`dog`"},{"name":"dollarSign","type":"boolean | undefined","required":false,"description":"`dollar-sign`"},{"name":"download","type":"boolean | undefined","required":false,"description":"`download`"},{"name":"drill","type":"boolean | undefined","required":false,"description":"`drill`"},{"name":"droplet","type":"boolean | undefined","required":false,"description":"`droplet`"},{"name":"droplets","type":"boolean | undefined","required":false,"description":"`droplets`"},{"name":"earth","type":"boolean | undefined","required":false,"description":"`earth`"},{"name":"ellipsisVertical","type":"boolean | undefined","required":false,"description":"`ellipsis-vertical`"},{"name":"equal","type":"boolean | undefined","required":false,"description":"`equal`"},{"name":"eraser","type":"boolean | undefined","required":false,"description":"`eraser`"},{"name":"euro","type":"boolean | undefined","required":false,"description":"`euro`"},{"name":"expand","type":"boolean | undefined","required":false,"description":"`expand`"},{"name":"externalLink","type":"boolean | undefined","required":false,"description":"`external-link`"},{"name":"eye","type":"boolean | undefined","required":false,"description":"`eye`"},{"name":"eyeOff","type":"boolean | undefined","required":false,"description":"`eye-off`"},{"name":"factory","type":"boolean | undefined","required":false,"description":"`factory`"},{"name":"fastForward","type":"boolean | undefined","required":false,"description":"`fast-forward`"},{"name":"feather","type":"boolean | undefined","required":false,"description":"`feather`"},{"name":"file","type":"boolean | undefined","required":false,"description":"`file`"},{"name":"fileCheck","type":"boolean | undefined","required":false,"description":"`file-check`"},{"name":"fileCode","type":"boolean | undefined","required":false,"description":"`file-code`"},{"name":"fileImage","type":"boolean | undefined","required":false,"description":"`file-image`"},{"name":"fileInput","type":"boolean | undefined","required":false,"description":"`file-input`"},{"name":"fileOutput","type":"boolean | undefined","required":false,"description":"`file-output`"},{"name":"filePen","type":"boolean | undefined","required":false,"description":"`file-pen`"},{"name":"filePlus","type":"boolean | undefined","required":false,"description":"`file-plus`"},{"name":"files","type":"boolean | undefined","required":false,"description":"`files`"},{"name":"fileSearch","type":"boolean | undefined","required":false,"description":"`file-search`"},{"name":"fileText","type":"boolean | undefined","required":false,"description":"`file-text`"},{"name":"fileX","type":"boolean | undefined","required":false,"description":"`file-x`"},{"name":"film","type":"boolean | undefined","required":false,"description":"`film`"},{"name":"filter","type":"boolean | undefined","required":false,"description":"`funnel`"},{"name":"fish","type":"boolean | undefined","required":false,"description":"`fish`"},{"name":"flag","type":"boolean | undefined","required":false,"description":"`flag`"},{"name":"flagTriangleRight","type":"boolean | undefined","required":false,"description":"`flag-triangle-right`"},{"name":"flame","type":"boolean | undefined","required":false,"description":"`flame`"},{"name":"flashlight","type":"boolean | undefined","required":false,"description":"`flashlight`"},{"name":"flower","type":"boolean | undefined","required":false,"description":"`flower`"},{"name":"folder","type":"boolean | undefined","required":false,"description":"`folder`"},{"name":"folderCheck","type":"boolean | undefined","required":false,"description":"`folder-check`"},{"name":"folderOpen","type":"boolean | undefined","required":false,"description":"`folder-open`"},{"name":"folderPlus","type":"boolean | undefined","required":false,"description":"`folder-plus`"},{"name":"footprints","type":"boolean | undefined","required":false,"description":"`footprints`"},{"name":"forward","type":"boolean | undefined","required":false,"description":"`forward`"},{"name":"frown","type":"boolean | undefined","required":false,"description":"`frown`"},{"name":"fuel","type":"boolean | undefined","required":false,"description":"`fuel`"},{"name":"gauge","type":"boolean | undefined","required":false,"description":"`gauge`"},{"name":"gem","type":"boolean | undefined","required":false,"description":"`gem`"},{"name":"gift","type":"boolean | undefined","required":false,"description":"`gift`"},{"name":"gitBranch","type":"boolean | undefined","required":false,"description":"`git-branch`"},{"name":"gitCommitHorizontal","type":"boolean | undefined","required":false,"description":"`git-commit-horizontal`"},{"name":"gitCompare","type":"boolean | undefined","required":false,"description":"`git-compare`"},{"name":"gitMerge","type":"boolean | undefined","required":false,"description":"`git-merge`"},{"name":"gitPullRequest","type":"boolean | undefined","required":false,"description":"`git-pull-request`"},{"name":"globe","type":"boolean | undefined","required":false,"description":"`globe`"},{"name":"graduationCap","type":"boolean | undefined","required":false,"description":"`graduation-cap`"},{"name":"grip","type":"boolean | undefined","required":false,"description":"`grip`"},{"name":"gripHorizontal","type":"boolean | undefined","required":false,"description":"`grip-horizontal`"},{"name":"gripVertical","type":"boolean | undefined","required":false,"description":"`grip-vertical`"},{"name":"group","type":"boolean | undefined","required":false,"description":"`group`"},{"name":"hammer","type":"boolean | undefined","required":false,"description":"`hammer`"},{"name":"hand","type":"boolean | undefined","required":false,"description":"`hand`"},{"name":"handGrab","type":"boolean | undefined","required":false,"description":"`hand-grab`"},{"name":"handshake","type":"boolean | undefined","required":false,"description":"`handshake`"},{"name":"hardDrive","type":"boolean | undefined","required":false,"description":"`hard-drive`"},{"name":"hash","type":"boolean | undefined","required":false,"description":"`hash`"},{"name":"headphones","type":"boolean | undefined","required":false,"description":"`headphones`"},{"name":"heart","type":"boolean | undefined","required":false,"description":"`heart`"},{"name":"heartHandshake","type":"boolean | undefined","required":false,"description":"`heart-handshake`"},{"name":"heartPulse","type":"boolean | undefined","required":false,"description":"`heart-pulse`"},{"name":"hexagon","type":"boolean | undefined","required":false,"description":"`hexagon`"},{"name":"history","type":"boolean | undefined","required":false,"description":"`history`"},{"name":"home","type":"boolean | undefined","required":false,"description":"`house`"},{"name":"hourglass","type":"boolean | undefined","required":false,"description":"`hourglass`"},{"name":"idCard","type":"boolean | undefined","required":false,"description":"`id-card`"},{"name":"image","type":"boolean | undefined","required":false,"description":"`image`"},{"name":"images","type":"boolean | undefined","required":false,"description":"`images`"},{"name":"inbox","type":"boolean | undefined","required":false,"description":"`inbox`"},{"name":"info","type":"boolean | undefined","required":false,"description":"`info`"},{"name":"keyboard","type":"boolean | undefined","required":false,"description":"`keyboard`"},{"name":"keyRound","type":"boolean | undefined","required":false,"description":"`key-round`"},{"name":"landmark","type":"boolean | undefined","required":false,"description":"`landmark`"},{"name":"laptop","type":"boolean | undefined","required":false,"description":"`laptop`"},{"name":"layers","type":"boolean | undefined","required":false,"description":"`layers`"},{"name":"layout","type":"boolean | undefined","required":false,"description":"`panels-top-left`"},{"name":"layoutDashboard","type":"boolean | undefined","required":false,"description":"`layout-dashboard`"},{"name":"layoutGrid","type":"boolean | undefined","required":false,"description":"`layout-grid`"},{"name":"layoutList","type":"boolean | undefined","required":false,"description":"`layout-list`"},{"name":"leaf","type":"boolean | undefined","required":false,"description":"`leaf`"},{"name":"library","type":"boolean | undefined","required":false,"description":"`library`"},{"name":"lifeBuoy","type":"boolean | undefined","required":false,"description":"`life-buoy`"},{"name":"lightbulb","type":"boolean | undefined","required":false,"description":"`lightbulb`"},{"name":"link","type":"boolean | undefined","required":false,"description":"`link`"},{"name":"link2","type":"boolean | undefined","required":false,"description":"`link-2`"},{"name":"list","type":"boolean | undefined","required":false,"description":"`list`"},{"name":"listChecks","type":"boolean | undefined","required":false,"description":"`list-checks`"},{"name":"listOrdered","type":"boolean | undefined","required":false,"description":"`list-ordered`"},{"name":"listTree","type":"boolean | undefined","required":false,"description":"`list-tree`"},{"name":"loader","type":"boolean | undefined","required":false,"description":"`loader`"},{"name":"loaderCircle","type":"boolean | undefined","required":false,"description":"`loader-circle`"},{"name":"locate","type":"boolean | undefined","required":false,"description":"`locate`"},{"name":"lock","type":"boolean | undefined","required":false,"description":"`lock`"},{"name":"lockOpen","type":"boolean | undefined","required":false,"description":"`lock-open`"},{"name":"logIn","type":"boolean | undefined","required":false,"description":"`log-in`"},{"name":"logOut","type":"boolean | undefined","required":false,"description":"`log-out`"},{"name":"mail","type":"boolean | undefined","required":false,"description":"`mail`"},{"name":"mailOpen","type":"boolean | undefined","required":false,"description":"`mail-open`"},{"name":"mailPlus","type":"boolean | undefined","required":false,"description":"`mail-plus`"},{"name":"map","type":"boolean | undefined","required":false,"description":"`map`"},{"name":"mapPin","type":"boolean | undefined","required":false,"description":"`map-pin`"},{"name":"maximize","type":"boolean | undefined","required":false,"description":"`maximize`"},{"name":"maximize2","type":"boolean | undefined","required":false,"description":"`maximize-2`"},{"name":"medal","type":"boolean | undefined","required":false,"description":"`medal`"},{"name":"megaphone","type":"boolean | undefined","required":false,"description":"`megaphone`"},{"name":"meh","type":"boolean | undefined","required":false,"description":"`meh`"},{"name":"memoryStick","type":"boolean | undefined","required":false,"description":"`memory-stick`"},{"name":"menu","type":"boolean | undefined","required":false,"description":"`menu`"},{"name":"messageCircle","type":"boolean | undefined","required":false,"description":"`message-circle`"},{"name":"messageSquare","type":"boolean | undefined","required":false,"description":"`message-square`"},{"name":"messageSquareText","type":"boolean | undefined","required":false,"description":"`message-square-text`"},{"name":"messageSquareWarning","type":"boolean | undefined","required":false,"description":"`message-square-warning`"},{"name":"messagesSquare","type":"boolean | undefined","required":false,"description":"`messages-square`"},{"name":"mic","type":"boolean | undefined","required":false,"description":"`mic`"},{"name":"micOff","type":"boolean | undefined","required":false,"description":"`mic-off`"},{"name":"milestone","type":"boolean | undefined","required":false,"description":"`milestone`"},{"name":"minimize","type":"boolean | undefined","required":false,"description":"`minimize`"},{"name":"minimize2","type":"boolean | undefined","required":false,"description":"`minimize-2`"},{"name":"minus","type":"boolean | undefined","required":false,"description":"`minus`"},{"name":"monitor","type":"boolean | undefined","required":false,"description":"`monitor`"},{"name":"moon","type":"boolean | undefined","required":false,"description":"`moon`"},{"name":"moreHorizontal","type":"boolean | undefined","required":false,"description":"`ellipsis`"},{"name":"mouse","type":"boolean | undefined","required":false,"description":"`mouse`"},{"name":"mousePointerClick","type":"boolean | undefined","required":false,"description":"`mouse-pointer-click`"},{"name":"move","type":"boolean | undefined","required":false,"description":"`move`"},{"name":"move3d","type":"boolean | undefined","required":false,"description":"`move-3d`"},{"name":"moveHorizontal","type":"boolean | undefined","required":false,"description":"`move-horizontal`"},{"name":"moveVertical","type":"boolean | undefined","required":false,"description":"`move-vertical`"},{"name":"music","type":"boolean | undefined","required":false,"description":"`music`"},{"name":"navigation","type":"boolean | undefined","required":false,"description":"`navigation`"},{"name":"newspaper","type":"boolean | undefined","required":false,"description":"`newspaper`"},{"name":"notebook","type":"boolean | undefined","required":false,"description":"`notebook`"},{"name":"octagon","type":"boolean | undefined","required":false,"description":"`octagon`"},{"name":"paintbrush","type":"boolean | undefined","required":false,"description":"`paintbrush`"},{"name":"palette","type":"boolean | undefined","required":false,"description":"`palette`"},{"name":"panelRight","type":"boolean | undefined","required":false,"description":"`panel-right`"},{"name":"paperclip","type":"boolean | undefined","required":false,"description":"`paperclip`"},{"name":"pause","type":"boolean | undefined","required":false,"description":"`pause`"},{"name":"pen","type":"boolean | undefined","required":false,"description":"`pen`"},{"name":"pencil","type":"boolean | undefined","required":false,"description":"`pencil`"},{"name":"pencilRuler","type":"boolean | undefined","required":false,"description":"`pencil-ruler`"},{"name":"pentagon","type":"boolean | undefined","required":false,"description":"`pentagon`"},{"name":"penTool","type":"boolean | undefined","required":false,"description":"`pen-tool`"},{"name":"percent","type":"boolean | undefined","required":false,"description":"`percent`"},{"name":"phone","type":"boolean | undefined","required":false,"description":"`phone`"},{"name":"phoneCall","type":"boolean | undefined","required":false,"description":"`phone-call`"},{"name":"phoneOff","type":"boolean | undefined","required":false,"description":"`phone-off`"},{"name":"piggyBank","type":"boolean | undefined","required":false,"description":"`piggy-bank`"},{"name":"pill","type":"boolean | undefined","required":false,"description":"`pill`"},{"name":"pipette","type":"boolean | undefined","required":false,"description":"`pipette`"},{"name":"plane","type":"boolean | undefined","required":false,"description":"`plane`"},{"name":"play","type":"boolean | undefined","required":false,"description":"`play`"},{"name":"plug","type":"boolean | undefined","required":false,"description":"`plug`"},{"name":"plugZap","type":"boolean | undefined","required":false,"description":"`plug-zap`"},{"name":"plus","type":"boolean | undefined","required":false,"description":"`plus`"},{"name":"podcast","type":"boolean | undefined","required":false,"description":"`podcast`"},{"name":"pointer","type":"boolean | undefined","required":false,"description":"`pointer`"},{"name":"power","type":"boolean | undefined","required":false,"description":"`power`"},{"name":"printer","type":"boolean | undefined","required":false,"description":"`printer`"},{"name":"qrCode","type":"boolean | undefined","required":false,"description":"`qr-code`"},{"name":"radio","type":"boolean | undefined","required":false,"description":"`radio`"},{"name":"rainbow","type":"boolean | undefined","required":false,"description":"`rainbow`"},{"name":"receipt","type":"boolean | undefined","required":false,"description":"`receipt`"},{"name":"redo","type":"boolean | undefined","required":false,"description":"`redo`"},{"name":"redo2","type":"boolean | undefined","required":false,"description":"`redo-2`"},{"name":"refreshCcw","type":"boolean | undefined","required":false,"description":"`refresh-ccw`"},{"name":"refreshCw","type":"boolean | undefined","required":false,"description":"`refresh-cw`"},{"name":"repeat","type":"boolean | undefined","required":false,"description":"`repeat`"},{"name":"reply","type":"boolean | undefined","required":false,"description":"`reply`"},{"name":"rewind","type":"boolean | undefined","required":false,"description":"`rewind`"},{"name":"rocket","type":"boolean | undefined","required":false,"description":"`rocket`"},{"name":"rotateCcw","type":"boolean | undefined","required":false,"description":"`rotate-ccw`"},{"name":"rotateCw","type":"boolean | undefined","required":false,"description":"`rotate-cw`"},{"name":"route","type":"boolean | undefined","required":false,"description":"`route`"},{"name":"rss","type":"boolean | undefined","required":false,"description":"`rss`"},{"name":"ruler","type":"boolean | undefined","required":false,"description":"`ruler`"},{"name":"save","type":"boolean | undefined","required":false,"description":"`save`"},{"name":"scale","type":"boolean | undefined","required":false,"description":"`scale`"},{"name":"scan","type":"boolean | undefined","required":false,"description":"`scan`"},{"name":"scanLine","type":"boolean | undefined","required":false,"description":"`scan-line`"},{"name":"scissors","type":"boolean | undefined","required":false,"description":"`scissors`"},{"name":"scrollText","type":"boolean | undefined","required":false,"description":"`scroll-text`"},{"name":"search","type":"boolean | undefined","required":false,"description":"`search`"},{"name":"send","type":"boolean | undefined","required":false,"description":"`send`"},{"name":"server","type":"boolean | undefined","required":false,"description":"`server`"},{"name":"settings","type":"boolean | undefined","required":false,"description":"`settings`"},{"name":"settings2","type":"boolean | undefined","required":false,"description":"`settings-2`"},{"name":"share","type":"boolean | undefined","required":false,"description":"`share`"},{"name":"share2","type":"boolean | undefined","required":false,"description":"`share-2`"},{"name":"shield","type":"boolean | undefined","required":false,"description":"`shield`"},{"name":"shieldAlert","type":"boolean | undefined","required":false,"description":"`shield-alert`"},{"name":"shieldCheck","type":"boolean | undefined","required":false,"description":"`shield-check`"},{"name":"ship","type":"boolean | undefined","required":false,"description":"`ship`"},{"name":"shoppingBag","type":"boolean | undefined","required":false,"description":"`shopping-bag`"},{"name":"shoppingCart","type":"boolean | undefined","required":false,"description":"`shopping-cart`"},{"name":"shrink","type":"boolean | undefined","required":false,"description":"`shrink`"},{"name":"sigma","type":"boolean | undefined","required":false,"description":"`sigma`"},{"name":"skipBack","type":"boolean | undefined","required":false,"description":"`skip-back`"},{"name":"skipForward","type":"boolean | undefined","required":false,"description":"`skip-forward`"},{"name":"slidersHorizontal","type":"boolean | undefined","required":false,"description":"`sliders-horizontal`"},{"name":"slidersVertical","type":"boolean | undefined","required":false,"description":"`sliders-vertical`"},{"name":"smartphone","type":"boolean | undefined","required":false,"description":"`smartphone`"},{"name":"smile","type":"boolean | undefined","required":false,"description":"`smile`"},{"name":"snowflake","type":"boolean | undefined","required":false,"description":"`snowflake`"},{"name":"sparkles","type":"boolean | undefined","required":false,"description":"`sparkles`"},{"name":"speaker","type":"boolean | undefined","required":false,"description":"`speaker`"},{"name":"sprout","type":"boolean | undefined","required":false,"description":"`sprout`"},{"name":"square","type":"boolean | undefined","required":false,"description":"`square`"},{"name":"squareArrowOutUpRight","type":"boolean | undefined","required":false,"description":"`square-arrow-out-up-right`"},{"name":"squarePen","type":"boolean | undefined","required":false,"description":"`square-pen`"},{"name":"squarePlay","type":"boolean | undefined","required":false,"description":"`square-play`"},{"name":"squarePlus","type":"boolean | undefined","required":false,"description":"`square-plus`"},{"name":"squareTerminal","type":"boolean | undefined","required":false,"description":"`square-terminal`"},{"name":"squareX","type":"boolean | undefined","required":false,"description":"`square-x`"},{"name":"star","type":"boolean | undefined","required":false,"description":"`star`"},{"name":"starHalf","type":"boolean | undefined","required":false,"description":"`star-half`"},{"name":"stethoscope","type":"boolean | undefined","required":false,"description":"`stethoscope`"},{"name":"stickyNote","type":"boolean | undefined","required":false,"description":"`sticky-note`"},{"name":"store","type":"boolean | undefined","required":false,"description":"`store`"},{"name":"sun","type":"boolean | undefined","required":false,"description":"`sun`"},{"name":"sunrise","type":"boolean | undefined","required":false,"description":"`sunrise`"},{"name":"sunset","type":"boolean | undefined","required":false,"description":"`sunset`"},{"name":"syringe","type":"boolean | undefined","required":false,"description":"`syringe`"},{"name":"table","type":"boolean | undefined","required":false,"description":"`table`"},{"name":"tablet","type":"boolean | undefined","required":false,"description":"`tablet`"},{"name":"tag","type":"boolean | undefined","required":false,"description":"`tag`"},{"name":"tags","type":"boolean | undefined","required":false,"description":"`tags`"},{"name":"target","type":"boolean | undefined","required":false,"description":"`target`"},{"name":"terminal","type":"boolean | undefined","required":false,"description":"`terminal`"},{"name":"textAlignCenter","type":"boolean | undefined","required":false,"description":"`text-align-center`"},{"name":"textAlignJustify","type":"boolean | undefined","required":false,"description":"`text-align-justify`"},{"name":"textCursorInput","type":"boolean | undefined","required":false,"description":"`text-cursor-input`"},{"name":"thermometer","type":"boolean | undefined","required":false,"description":"`thermometer`"},{"name":"thumbsDown","type":"boolean | undefined","required":false,"description":"`thumbs-down`"},{"name":"thumbsUp","type":"boolean | undefined","required":false,"description":"`thumbs-up`"},{"name":"ticket","type":"boolean | undefined","required":false,"description":"`ticket`"},{"name":"timer","type":"boolean | undefined","required":false,"description":"`timer`"},{"name":"toggleLeft","type":"boolean | undefined","required":false,"description":"`toggle-left`"},{"name":"toggleRight","type":"boolean | undefined","required":false,"description":"`toggle-right`"},{"name":"trainFront","type":"boolean | undefined","required":false,"description":"`train-front`"},{"name":"trash","type":"boolean | undefined","required":false,"description":"`trash`"},{"name":"trash2","type":"boolean | undefined","required":false,"description":"`trash-2`"},{"name":"treePine","type":"boolean | undefined","required":false,"description":"`tree-pine`"},{"name":"trees","type":"boolean | undefined","required":false,"description":"`trees`"},{"name":"trendingDown","type":"boolean | undefined","required":false,"description":"`trending-down`"},{"name":"trendingUp","type":"boolean | undefined","required":false,"description":"`trending-up`"},{"name":"triangle","type":"boolean | undefined","required":false,"description":"`triangle`"},{"name":"trophy","type":"boolean | undefined","required":false,"description":"`trophy`"},{"name":"truck","type":"boolean | undefined","required":false,"description":"`truck`"},{"name":"type","type":"boolean | undefined","required":false,"description":"`type`"},{"name":"umbrella","type":"boolean | undefined","required":false,"description":"`umbrella`"},{"name":"undo","type":"boolean | undefined","required":false,"description":"`undo`"},{"name":"undo2","type":"boolean | undefined","required":false,"description":"`undo-2`"},{"name":"unlink","type":"boolean | undefined","required":false,"description":"`unlink`"},{"name":"upload","type":"boolean | undefined","required":false,"description":"`upload`"},{"name":"usb","type":"boolean | undefined","required":false,"description":"`usb`"},{"name":"user","type":"boolean | undefined","required":false,"description":"`user`"},{"name":"userCheck","type":"boolean | undefined","required":false,"description":"`user-check`"},{"name":"userCog","type":"boolean | undefined","required":false,"description":"`user-cog`"},{"name":"userPlus","type":"boolean | undefined","required":false,"description":"`user-plus`"},{"name":"userRound","type":"boolean | undefined","required":false,"description":"`user-round`"},{"name":"users","type":"boolean | undefined","required":false,"description":"`users`"},{"name":"usersRound","type":"boolean | undefined","required":false,"description":"`users-round`"},{"name":"userX","type":"boolean | undefined","required":false,"description":"`user-x`"},{"name":"utensils","type":"boolean | undefined","required":false,"description":"`utensils`"},{"name":"variable","type":"boolean | undefined","required":false,"description":"`variable`"},{"name":"video","type":"boolean | undefined","required":false,"description":"`video`"},{"name":"volume","type":"boolean | undefined","required":false,"description":"`volume`"},{"name":"volume1","type":"boolean | undefined","required":false,"description":"`volume-1`"},{"name":"volume2","type":"boolean | undefined","required":false,"description":"`volume-2`"},{"name":"volumeX","type":"boolean | undefined","required":false,"description":"`volume-x`"},{"name":"wallet","type":"boolean | undefined","required":false,"description":"`wallet`"},{"name":"wand","type":"boolean | undefined","required":false,"description":"`wand`"},{"name":"wandSparkles","type":"boolean | undefined","required":false,"description":"`wand-sparkles`"},{"name":"warehouse","type":"boolean | undefined","required":false,"description":"`warehouse`"},{"name":"watch","type":"boolean | undefined","required":false,"description":"`watch`"},{"name":"wifi","type":"boolean | undefined","required":false,"description":"`wifi`"},{"name":"wifiOff","type":"boolean | undefined","required":false,"description":"`wifi-off`"},{"name":"wind","type":"boolean | undefined","required":false,"description":"`wind`"},{"name":"wrench","type":"boolean | undefined","required":false,"description":"`wrench`"},{"name":"x","type":"boolean | undefined","required":false,"description":"`x`"},{"name":"zap","type":"boolean | undefined","required":false,"description":"`zap`"},{"name":"zoomIn","type":"boolean | undefined","required":false,"description":"`zoom-in`"},{"name":"zoomOut","type":"boolean | undefined","required":false,"description":"`zoom-out`"}],"groups":[{"title":"Color axis","pickOne":false,"note":"Color axis: pass one (default foreground). First match wins."},{"title":"Single-glyph size in px","pickOne":false,"note":"Single-glyph size in px (default 24)."}],"inherits":[]}],"platformNotes":{"web":"Lucide-style outline. 1.75 stroke width, rounded caps. The stroke defaults to the theme foreground token and tracks light and dark automatically; pick other hues with the semantic color booleans (`primary`, `destructive`, `success`, `warning`, `muted`, `subtle`; that order is the precedence). `muted` is the third ink (`subtle-foreground`) and `subtle` the second (`muted-foreground`), the names Typography gives the same two inks. Inside a control that owns a label ink (a Button's `iconLeft` and `iconRight` slots) a glyph with no tone takes that ink instead, the way the hand-off's icons inherit `currentColor`: the primary's contrast ink on a primary button, the muted ink on a quiet one. The precedence is the explicit tone, then the host's ink, then the foreground, so a toned glyph keeps its tone anywhere.","ios":"Lucide-style outline. 1.75 stroke width, rounded caps. The stroke defaults to the theme foreground token and tracks light and dark automatically; pick other hues with the semantic color booleans (`primary`, `destructive`, `success`, `warning`, `muted`, `subtle`; that order is the precedence). `muted` is the third ink (`subtle-foreground`) and `subtle` the second (`muted-foreground`), the names Typography gives the same two inks. Inside a control that owns a label ink (a Button's `iconLeft` and `iconRight` slots) a glyph with no tone takes that ink instead, the way the hand-off's icons inherit `currentColor`: the primary's contrast ink on a primary button, the muted ink on a quiet one. The precedence is the explicit tone, then the host's ink, then the foreground, so a toned glyph keeps its tone anywhere.","android":"Lucide-style outline. 1.75 stroke width, rounded caps. The stroke defaults to the theme foreground token and tracks light and dark automatically; pick other hues with the semantic color booleans (`primary`, `destructive`, `success`, `warning`, `muted`, `subtle`; that order is the precedence). `muted` is the third ink (`subtle-foreground`) and `subtle` the second (`muted-foreground`), the names Typography gives the same two inks. Inside a control that owns a label ink (a Button's `iconLeft` and `iconRight` slots) a glyph with no tone takes that ink instead, the way the hand-off's icons inherit `currentColor`: the primary's contrast ink on a primary button, the muted ink on a quiet one. The precedence is the explicit tone, then the host's ink, then the foreground, so a toned glyph keeps its tone anywhere."}},{"slug":"image","name":"Image","category":"atoms","description":"Displays a local or remote image. Set the `source` (`{ uri }`) and a size, then choose how it fills its box with a fit prop: `cover` (the default) fills the box and crops the overflow, while `contain` fits the whole image inside and letterboxes the spare space.","source":"src/atoms/image/image.md","url":"https://canvas.nannier.com/ai/4.2.0/components/image.md","humanUrl":"https://canvas.nannier.com/components/image","exports":["Image","ImageProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ImageProps","props":[{"name":"source","type":"ImageSourcePropType | undefined","required":false,"description":"The image to display: a remote `{ uri }`, or a bundled asset from `require(...)`."},{"name":"contain","type":"boolean | undefined","required":false,"description":"Fit: fit the whole image inside the box, letterboxing the spare space (pick one).","default":"false","group":0},{"name":"cover","type":"boolean | undefined","required":false,"description":"Fit: fill the box, cropping any overflow. The default when no fit is set (pick one).","default":"false","group":0},{"name":"stretch","type":"boolean | undefined","required":false,"description":"Fit: fill the box by distorting the aspect ratio (pick one).","default":"false","group":0},{"name":"center","type":"boolean | undefined","required":false,"description":"Fit: center at intrinsic size, scaling down only when larger than the box (pick one).","default":"false","group":0},{"name":"repeat","type":"boolean | undefined","required":false,"description":"Fit: tile the image at its intrinsic size to fill the box (pick one).","default":"false","group":0},{"name":"none","type":"boolean | undefined","required":false,"description":"Fit: show at intrinsic size with no scaling (pick one).","default":"false","group":0},{"name":"width","type":"DimensionValue | undefined","required":false,"description":"Width of the image box (px, or a percent string like `\"100%\"`). Images have no intrinsic layout size.","group":0},{"name":"height","type":"DimensionValue | undefined","required":false,"description":"Height of the image box (px, or a percent string).","group":0},{"name":"radius","type":"ImageRadius | undefined","required":false,"description":"Corner radius from the kit's radius scale (pick one): none, sm, md, lg, xl, 2xl, 3xl, full.","group":0},{"name":"style","type":"StyleProp<ImageStyle>","required":false,"description":"Composition only (aspectRatio, layout within a parent). Size comes from `width` / `height`, rounding from `radius`.","group":0},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the image, the same name `alt` gives (and it wins when both are set). On iOS and Android React Native makes an image its own accessibility element for `alt` (or `accessible`), so prefer `alt` for an image that stands on its own.","group":0},{"name":"alt","type":"string | undefined","required":false,"description":"The image's alt text: a named image is announced as an image with this name on every platform (the web's <img alt>, the image role natively). With no name here or in `accessibilityLabel` the image is decorative, and assistive tech skips it.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the underlying image.","group":0},{"name":"accessible","type":"boolean | undefined","required":false,"description":"When true, indicates that the view is an accessibility element. By default, all the touchable elements are accessible.","default":"false"},{"name":"accessibilityActions","type":"readonly Readonly<{ name: AccessibilityActionName | string; label?: string | undefined; }>[] | undefined","required":false,"description":"Provides an array of custom actions available for accessibility."},{"name":"aria-label","type":"string | undefined","required":false,"description":"Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel https://github.com/facebook/react-native/issues/34424"},{"name":"blurRadius","type":"number | undefined","required":false,"description":"blurRadius: the blur radius of the blur filter added to the image"},{"name":"accessibilityRole","type":"AccessibilityRole | undefined","required":false,"description":"Accessibility Role tells a person using either VoiceOver on iOS or TalkBack on Android the type of element that is focused on."},{"name":"capInsets","type":"Insets | undefined","required":false,"description":"When the image is resized, the corners of the size specified by capInsets will stay a fixed size, but the center content and borders of the image will be stretched. This is useful for creating resizable rounded buttons, shadows, and other resizable assets. More info on Apple documentation"},{"name":"accessibilityState","type":"AccessibilityState | undefined","required":false,"description":"Accessibility State tells a person using either VoiceOver on iOS or TalkBack on Android the state of the element currently focused on."},{"name":"onProgress","type":"((event: ImageProgressEventIOS) => void) | undefined","required":false,"description":"Invoked on download progress with {nativeEvent: {loaded, total}}"},{"name":"aria-busy","type":"boolean | undefined","required":false,"description":"alias for accessibilityState see https://reactnative.dev/docs/accessibility#accessibilitystate","default":"false"},{"name":"aria-checked","type":"boolean | \"mixed\" | undefined","required":false,"description":""},{"name":"aria-disabled","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"aria-expanded","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"aria-selected","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"onPartialLoad","type":"(() => void) | undefined","required":false,"description":"Invoked when a partial load of the image is complete. The definition of what constitutes a \"partial load\" is loader specific though this is meant for progressive JPEG loads."},{"name":"accessibilityHint","type":"string | undefined","required":false,"description":"An accessibility hint helps users understand what will happen when they perform an action on the accessibility element when that result is not obvious from the accessibility label."},{"name":"accessibilityValue","type":"AccessibilityValue | undefined","required":false,"description":"Represents the current value of a component. It can be a textual description of a component's value, or for range-based components, such as sliders and progress bars, it contains range information (minimum, current, and maximum)."},{"name":"aria-valuemax","type":"number | undefined","required":false,"description":""},{"name":"aria-valuemin","type":"number | undefined","required":false,"description":""},{"name":"aria-valuenow","type":"number | undefined","required":false,"description":""},{"name":"aria-valuetext","type":"string | undefined","required":false,"description":""},{"name":"onAccessibilityAction","type":"((event: AccessibilityActionEvent) => void) | undefined","required":false,"description":"When `accessible` is true, the system will try to invoke this function when the user performs an accessibility custom action."},{"name":"importantForAccessibility","type":"\"auto\" | \"yes\" | \"no\" | \"no-hide-descendants\" | undefined","required":false,"description":"[Android] Controlling if a view fires accessibility events and if it is reported to accessibility services."},{"name":"resizeMethod","type":"\"scale\" | \"none\" | \"auto\" | \"resize\" | undefined","required":false,"description":"The mechanism that should be used to resize the image when the image's dimensions differ from the image view's dimensions. Defaults to `auto`. - `auto`: Use heuristics to pick between `resize` and `scale`. - `resize`: A software operation which changes the encoded image in memory before it gets decoded. This should be used instead of `scale` when the image is much larger than the view. - `scale`: The image gets drawn downscaled or upscaled. Compared to `resize`, `scale` is faster (usually hardware accelerated) and produces higher quality images. This should be used if the image is smaller than the view. It should also be used if the image is slightly bigger than the view. - `none`: No sampling is performed and the image is displayed in its full resolution. This should only be used in rare circumstances because it is considered unsafe as Android will throw a runtime exception when trying to render images that consume too much memory. More details about `resize` and `scale` can be found at http://frescolib.org/docs/resizing-rotating.html."},{"name":"aria-hidden","type":"boolean | undefined","required":false,"description":"A value indicating whether the accessibility elements contained within this accessibility element are hidden.","default":"false"},{"name":"aria-modal","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"fadeDuration","type":"number | undefined","required":false,"description":"Duration of fade in animation in ms. Defaults to 300"},{"name":"role","type":"Role | undefined","required":false,"description":"Indicates to accessibility services to treat UI component like a specific role."},{"name":"id","type":"string | undefined","required":false,"description":"Used to reference react managed images from native code."},{"name":"onLayout","type":"((event: LayoutChangeEvent) => void) | undefined","required":false,"description":"onLayout function Invoked on mount and layout changes with {nativeEvent: { layout: {x, y, width, height} }}."},{"name":"onError","type":"((error: ImageErrorEvent) => void) | undefined","required":false,"description":"Invoked on load error with {nativeEvent: {error}}"},{"name":"onLoad","type":"((event: ImageLoadEvent) => void) | undefined","required":false,"description":"Invoked when load completes successfully { source: { uri, height, width } }."},{"name":"onLoadEnd","type":"(() => void) | undefined","required":false,"description":"Invoked when load either succeeds or fails"},{"name":"onLoadStart","type":"(() => void) | undefined","required":false,"description":"Invoked on load start"},{"name":"progressiveRenderingEnabled","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"borderRadius","type":"number | undefined","required":false,"description":""},{"name":"borderTopLeftRadius","type":"number | undefined","required":false,"description":""},{"name":"borderTopRightRadius","type":"number | undefined","required":false,"description":""},{"name":"borderBottomLeftRadius","type":"number | undefined","required":false,"description":""},{"name":"borderBottomRightRadius","type":"number | undefined","required":false,"description":""},{"name":"accessibilityLabelledBy","type":"string | string[] | undefined","required":false,"description":"Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props, the text is read aloud. The value should should match the nativeID of the related element."},{"name":"aria-labelledby","type":"string | undefined","required":false,"description":"Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props, the text is read aloud. The value should should match the nativeID of the related element."},{"name":"accessibilityLiveRegion","type":"\"none\" | \"polite\" | \"assertive\" | undefined","required":false,"description":"Indicates to accessibility services whether the user should be notified when this view changes. Works for Android API >= 19 only."},{"name":"src","type":"string | undefined","required":false,"description":"A string representing the resource identifier for the image. Similar to src from HTML. See https://reactnative.dev/docs/image#src"},{"name":"srcSet","type":"string | undefined","required":false,"description":"Similar to srcset from HTML. See https://reactnative.dev/docs/image#srcset"},{"name":"aria-live","type":"\"polite\" | \"assertive\" | \"off\" | undefined","required":false,"description":"Indicates to accessibility services whether the user should be notified when this view changes. Works for Android API >= 19 only."},{"name":"loadingIndicatorSource","type":"ImageURISource | undefined","required":false,"description":"similarly to `source`, this property represents the resource used to render the loading indicator for the image, displayed until image is ready to be displayed, typically after when it got downloaded from network."},{"name":"nativeID","type":"string | undefined","required":false,"description":"Used to reference react managed images from native code."},{"name":"defaultSource","type":"number | ImageURISource | undefined","required":false,"description":"A static image to display while downloading the final image off the network."},{"name":"screenReaderFocusable","type":"boolean | undefined","required":false,"description":"Enables the view to be screen reader focusable, not keyboard focusable.","default":"false"},{"name":"accessibilityElementsHidden","type":"boolean | undefined","required":false,"description":"A Boolean value indicating whether the accessibility elements contained within this accessibility element are hidden to the screen reader.","default":"false"},{"name":"crossOrigin","type":"\"anonymous\" | \"use-credentials\" | undefined","required":false,"description":"Adds the CORS related header to the request. Similar to crossorigin from HTML. See https://reactnative.dev/docs/image#crossorigin"},{"name":"accessibilityViewIsModal","type":"boolean | undefined","required":false,"description":"A Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver.","default":"false"},{"name":"tintColor","type":"ColorValue | undefined","required":false,"description":"Changes the color of all the non-transparent pixels to the tintColor. See https://reactnative.dev/docs/image#tintcolor"},{"name":"onAccessibilityEscape","type":"(() => void) | undefined","required":false,"description":"When accessible is true, the system will invoke this function when the user performs the escape gesture (scrub with two fingers)."},{"name":"referrerPolicy","type":"\"origin\" | \"no-referrer\" | \"no-referrer-when-downgrade\" | \"origin-when-cross-origin\" | \"same-origin\" | \"strict-origin\" | \"strict-origin-when-cross-origin\" | \"unsafe-url\" | undefined","required":false,"description":"A string indicating which referrer to use when fetching the resource. Similar to referrerpolicy from HTML. See https://reactnative.dev/docs/image#referrerpolicy"},{"name":"onAccessibilityTap","type":"(() => void) | undefined","required":false,"description":"When `accessible` is true, the system will try to invoke this function when the user performs accessibility tap gesture."},{"name":"onMagicTap","type":"(() => void) | undefined","required":false,"description":"When accessible is true, the system will invoke this function when the user performs the magic tap gesture."},{"name":"accessibilityIgnoresInvertColors","type":"boolean | undefined","required":false,"description":"https://reactnative.dev/docs/accessibility#accessibilityignoresinvertcolorsios","default":"false"},{"name":"accessibilityLanguage","type":"string | undefined","required":false,"description":"By using the accessibilityLanguage property, the screen reader will understand which language to use while reading the element's label, value and hint. The provided string value must follow the BCP 47 specification (https://www.rfc-editor.org/info/bcp47). https://reactnative.dev/docs/accessibility#accessibilitylanguage-ios"},{"name":"accessibilityShowsLargeContentViewer","type":"boolean | undefined","required":false,"description":"A Boolean value that indicates whether or not to show the item in the large content viewer. Available on iOS 13.0+ https://reactnative.dev/docs/accessibility#accessibilityshowslargecontentviewer","default":"false"},{"name":"accessibilityLargeContentTitle","type":"string | undefined","required":false,"description":"When `accessibilityShowsLargeContentViewer` is set, this string will be used as title for the large content viewer. https://reactnative.dev/docs/accessibility#accessibilitylargecontenttitle"},{"name":"accessibilityRespondsToUserInteraction","type":"boolean | undefined","required":false,"description":"Blocks the user from interacting with the component through keyboard while still allowing screen reader to interact with it if this View is still accessible.","default":"false"}],"groups":[{"title":"Fit","pickOne":true,"note":"Fit (pick one; default `cover`). Chooses how the image is sized to fill its box. When more than one is set, first match wins in the order below."}],"inherits":[]}],"platformNotes":{"web":"Displays a local or remote image. Set the `source` (`{ uri }`) and a size, then choose how it fills its box with a fit prop: `cover` (the default) fills the box and crops the overflow, while `contain` fits the whole image inside and letterboxes the spare space.\n\n`stretch`, `center`, `repeat`, and `none` cover the rarer fits. `repeat` tiles a bundled asset (or a `{ uri, width, height }` source) at its point size on every platform, drawing the density variant that matches the screen (`grain@2x.png` on a 2x screen) into each tile; a box with no size of its own is one tile. A remote image with no stated size keeps React Native's own repeat. Remote images load over the network; bundle local assets with `require`. Name an image that carries content with `alt`, and it is announced as an image with that name on every platform; an image with no name is decorative, and assistive tech skips it. The v4 hand-off rounds a standalone photo at 12 (`radius=\"xl\"`); Image draws no corner of its own, so a photo inside a Card or a Video keeps its host's corner. For a circular identity photo with an initials fallback, reach for `<Avatar src=\"…\" name=\"…\" />` rather than rounding a bare Image.","ios":"Displays a local or remote image. Set the `source` (`{ uri }`) and a size, then choose how it fills its box with a fit prop: `cover` (the default) fills the box and crops the overflow, while `contain` fits the whole image inside and letterboxes the spare space.\n\n`stretch`, `center`, `repeat`, and `none` cover the rarer fits. `repeat` tiles a bundled asset (or a `{ uri, width, height }` source) at its point size on every platform, drawing the density variant that matches the screen (`grain@2x.png` on a 2x screen) into each tile; a box with no size of its own is one tile. A remote image with no stated size keeps React Native's own repeat. Remote images load over the network; bundle local assets with `require`. Name an image that carries content with `alt`, and it is announced as an image with that name on every platform; an image with no name is decorative, and assistive tech skips it. The v4 hand-off rounds a standalone photo at 12 (`radius=\"xl\"`); Image draws no corner of its own, so a photo inside a Card or a Video keeps its host's corner. For a circular identity photo with an initials fallback, reach for `<Avatar src=\"…\" name=\"…\" />` rather than rounding a bare Image.","android":"Displays a local or remote image. Set the `source` (`{ uri }`) and a size, then choose how it fills its box with a fit prop: `cover` (the default) fills the box and crops the overflow, while `contain` fits the whole image inside and letterboxes the spare space.\n\n`stretch`, `center`, `repeat`, and `none` cover the rarer fits. `repeat` tiles a bundled asset (or a `{ uri, width, height }` source) at its point size on every platform, drawing the density variant that matches the screen (`grain@2x.png` on a 2x screen) into each tile; a box with no size of its own is one tile. A remote image with no stated size keeps React Native's own repeat. Remote images load over the network; bundle local assets with `require`. Name an image that carries content with `alt`, and it is announced as an image with that name on every platform; an image with no name is decorative, and assistive tech skips it. The v4 hand-off rounds a standalone photo at 12 (`radius=\"xl\"`); Image draws no corner of its own, so a photo inside a Card or a Video keeps its host's corner. For a circular identity photo with an initials fallback, reach for `<Avatar src=\"…\" name=\"…\" />` rather than rounding a bare Image."}},{"slug":"input","name":"Input","category":"atoms","description":"The Input component is a React Native text field with semantic boolean props (`error`, `small`, `large`, `compact`, `disabled`), plus prefix/suffix addons, overlaid icons (`leadingIcon` / `trailingIcon` with any Canvas glyph as `icon`), a `passwordToggle` eye for a `secureTextEntry` value, a `clearable` clear button, and a `shortcut` keycap. Input is single-line; for multi-line entry use the dedicated Textarea.","source":"src/atoms/input/input.md","url":"https://canvas.nannier.com/ai/4.2.0/components/input.md","humanUrl":"https://canvas.nannier.com/components/input","exports":["Input","InputProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"InputProps","props":[{"name":"value","type":"string | undefined","required":false,"description":"Current text value (controlled). Omit and use `defaultValue` for uncontrolled use."},{"name":"onChangeText","type":"((text: string) => void) | undefined","required":false,"description":"Called with the new text on each keystroke."},{"name":"placeholder","type":"string | undefined","required":false,"description":"Placeholder shown while the field is empty."},{"name":"label","type":"string | undefined","required":false,"description":"The field's persistent label. Its placement is platform-adaptive: iOS and web render it ABOVE the field (the static title the Field/Form composers produce today); Android renders the Material 3 in-container FLOATING label (centered like a placeholder at rest, floating to the top once the field is focused or filled). The label is the field's programmatic name (wired via both accessibilityLabel and aria-labelledby), so a placeholder is no longer needed for the accessible name."},{"name":"search","type":"boolean | undefined","required":false,"description":"A toolbar search field with a magnifier and a tracked uppercase empty prompt on web.","default":"false"},{"name":"eyebrow","type":"boolean | undefined","required":false,"description":"Dense uppercase eyebrow label where the skin offers it.","default":"false"},{"name":"systemFocus","type":"boolean | undefined","required":false,"description":"Preserve the system focus outline on a framed field.","default":"false"},{"name":"soft","type":"boolean | undefined","required":false,"description":"Use the brand’s softer entry-well fill where the skin provides it.","default":"false"},{"name":"required","type":"boolean | undefined","required":false,"description":"Marks the field as required: appends a destructive \"*\" to the label (decorative, never in the accessible name) and announces the field as required, through aria-required on the web and with the word in its name (\"Full name, required\") on iOS and Android. The star takes effect only alongside `label`.","default":"false"},{"name":"error","type":"boolean | undefined","required":false,"description":"State (orthogonal). `error` (alias `invalid`) flags a validation problem.","default":"false","group":0},{"name":"invalid","type":"boolean | undefined","required":false,"description":"State (orthogonal). `error` (alias `invalid`) flags a validation problem.","default":"false","group":0},{"name":"disabled","type":"boolean | undefined","required":false,"description":"State (orthogonal). `error` (alias `invalid`) flags a validation problem.","default":"false","group":0},{"name":"readOnly","type":"boolean | undefined","required":false,"description":"Read-only: shows the value but blocks editing without the dimmed look.","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium field).","default":"false","group":1},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium field).","default":"false","group":1},{"name":"compact","type":"boolean | undefined","required":false,"description":"A compact outlined well: 40 high with a 14px value by default; small is 32/13, large is 48/16. Keeps the platform's field corner and places labels above.","default":"false","group":1},{"name":"prefix","type":"string | undefined","required":false,"description":"Leading addon content (e.g. \"https://\", \"$\", an icon glyph).","group":2},{"name":"suffix","type":"string | undefined","required":false,"description":"Trailing addon content (e.g. \"@canvas.dev\", \"USD\", \"Copy\").","group":2},{"name":"leadingIcon","type":"boolean | undefined","required":false,"description":"Render `icon` as a passive glyph inside the left of the field.","group":3},{"name":"trailingIcon","type":"boolean | undefined","required":false,"description":"Render `icon` as a passive glyph inside the right of the field.","default":"false","group":3},{"name":"icon","type":"keyof IconGlyphProps | undefined","required":false,"description":"Glyph name for leadingIcon/trailingIcon: any Canvas glyph (e.g. \"search\", \"mail\", \"lock\", \"phone\", \"calendar\", \"creditCard\").","group":3},{"name":"action","type":"boolean | undefined","required":false,"description":"Render the suffix as a pressable action button rather than a passive label.","default":"false","group":3},{"name":"onActionPress","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Called when the action suffix is pressed (action only).","group":3},{"name":"passwordToggle","type":"boolean | undefined","required":false,"description":"A trailing eye button that reveals and re-masks a `secureTextEntry` value (the password field's show/hide toggle). The field starts masked; the button is announced as \"Show password\" / \"Hide password\". Takes effect only with `secureTextEntry`.","default":"false","group":3},{"name":"clearable","type":"boolean | undefined","required":false,"description":"A trailing clear button (a circled x) that empties the field, shown while the field holds text (the search field's clear affordance). Works in both the controlled and the uncontrolled mode: it clears the native field and reports \"\" through `onChangeText`.","default":"false","group":3},{"name":"shortcut","type":"string | undefined","required":false,"description":"A keyboard shortcut hint at the field's end: a compact flat keycap (`<Kbd small flat>`, the 20 px `tiny` cap on a `small` field) after the value and any inline suffix, before the trailing glyphs, the hint a search field shows for the key that focuses it (`shortcut=\"⌘K\"`). Pass the keys as Kbd's `keys` takes them: `\"⌘K\"` is one cap, `\"⌘ K\"` two. A hint only: bind the key yourself.","group":3},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the field when there is no programmatically-associated visible label. Maps to accessibilityLabel + the aria-label web alias on the underlying TextInput, so a Form/Field control is announced with its name.","group":3},{"name":"aria-labelledby","type":"string | undefined","required":false,"description":"ID of the visible label element that names this field (its `nativeID`). react-native-web forwards aria-labelledby to the DOM input; prefer this over accessibilityLabel when a visible <Text> label is present so the label and field are programmatically linked.","group":3},{"name":"aria-describedby","type":"string | undefined","required":false,"description":"ID of the helper/error text that describes this field (its `nativeID`), so a screen reader reads the hint after the field name.","group":3},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":3},{"name":"textContentType","type":"\"none\" | \"name\" | \"URL\" | \"addressCity\" | \"addressCityAndState\" | \"addressState\" | \"countryName\" | \"creditCardNumber\" | \"creditCardExpiration\" | \"creditCardExpirationMonth\" | \"creditCardExpirationYear\" | \"creditCardSecurityCode\" | \"creditCardType\" | \"creditCardName\" | \"creditCardGivenName\" | \"creditCardMiddleName\" | \"creditCardFamilyName\" | \"emailAddress\" | \"familyName\" | \"fullStreetAddress\" | \"givenName\" | \"jobTitle\" | \"location\" | \"middleName\" | \"namePrefix\" | \"nameSuffix\" | \"nickname\" | \"organizationName\" | \"postalCode\" | \"streetAddressLine1\" | \"streetAddressLine2\" | \"sublocality\" | \"telephoneNumber\" | \"username\" | \"password\" | \"newPassword\" | \"oneTimeCode\" | \"birthdate\" | \"birthdateDay\" | \"birthdateMonth\" | \"birthdateYear\" | \"cellularEID\" | \"cellularIMEI\" | \"dateTime\" | \"flightNumber\" | \"shipmentTrackingNumber\" | undefined","required":false,"description":"Give the keyboard and the system information about the expected semantic meaning for the content that users enter. To disable autofill, set textContentType to `none`. Possible values for `textContentType` are: - `'none'` - `'URL'` - `'addressCity'` - `'addressCityAndState'` - `'addressState'` - `'countryName'` - `'creditCardNumber'` - `'creditCardExpiration'` (iOS 17+) - `'creditCardExpirationMonth'` (iOS 17+) - `'creditCardExpirationYear'` (iOS 17+) - `'creditCardSecurityCode'` (iOS 17+) - `'creditCardType'` (iOS 17+) - `'creditCardName'` (iOS 17+) - `'creditCardGivenName'` (iOS 17+) - `'creditCardMiddleName'` (iOS 17+) - `'creditCardFamilyName'` (iOS 17+) - `'emailAddress'` - `'familyName'` - `'fullStreetAddress'` - `'givenName'` - `'jobTitle'` - `'location'` - `'middleName'` - `'name'` - `'namePrefix'` - `'nameSuffix'` - `'nickname'` - `'organizationName'` - `'postalCode'` - `'streetAddressLine1'` - `'streetAddressLine2'` - `'sublocality'` - `'telephoneNumber'` - `'username'` - `'password'` - `'newPassword'` - `'oneTimeCode'` - `'birthdate'` (iOS 17+) - `'birthdateDay'` (iOS 17+) - `'birthdateMonth'` (iOS 17+) - `'birthdateYear'` (iOS 17+) - `'cellularEID'` (iOS 17.4+) - `'cellularIMEI'` (iOS 17.4+) - `'dateTime'` (iOS 15+) - `'flightNumber'` (iOS 15+) - `'shipmentTrackingNumber'` (iOS 15+)"},{"name":"autoCapitalize","type":"\"none\" | \"sentences\" | \"words\" | \"characters\" | undefined","required":false,"description":"Can tell TextInput to automatically capitalize certain characters. characters: all characters, words: first letter of each word sentences: first letter of each sentence (default) none: don't auto capitalize anything https://reactnative.dev/docs/textinput#autocapitalize"},{"name":"autoComplete","type":"\"country\" | \"name\" | \"off\" | \"nickname\" | \"username\" | \"password\" | \"2fa-app-otp\" | \"additional-name\" | \"address-line1\" | \"address-line2\" | \"birthdate-day\" | \"birthdate-full\" | \"birthdate-month\" | \"birthdate-year\" | \"cc-csc\" | \"cc-exp\" | \"cc-exp-day\" | \"cc-exp-month\" | \"cc-exp-year\" | \"cc-number\" | \"cc-name\" | \"cc-given-name\" | \"cc-middle-name\" | \"cc-family-name\" | \"cc-type\" | \"current-password\" | \"email\" | \"email-otp\" | \"flight-confirmation-code\" | \"flight-number\" | \"family-name\" | \"gender\" | \"gift-card-number\" | \"gift-card-pin\" | \"given-name\" | \"honorific-prefix\" | \"honorific-suffix\" | \"loyalty-account-number\" | \"name-family\" | \"name-given\" | \"name-middle\" | \"name-middle-initial\" | \"name-prefix\" | \"name-suffix\" | \"new-password\" | \"one-time-code\" | \"organization\" | \"organization-title\" | \"password-new\" | \"postal-address\" | \"postal-address-country\" | \"postal-address-dependent-locality\" | \"postal-address-extended\" | \"postal-address-extended-postal-code\" | \"postal-address-locality\" | \"postal-address-region\" | \"postal-address-unit\" | \"postal-code\" | \"promo-code\" | \"street-address\" | \"sms-otp\" | \"tel\" | \"tel-country-code\" | \"tel-national\" | \"tel-device\" | \"upi-vpa\" | \"url\" | \"wifi-password\" | \"username-new\" | undefined","required":false,"description":"Specifies autocomplete hints for the system, so it can provide autofill. On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content. To disable autocomplete, set autoComplete to off. The following values work across platforms: - `additional-name` - `address-line1` - `address-line2` - `cc-number` - `country` - `current-password` - `email` - `family-name` - `given-name` - `honorific-prefix` - `honorific-suffix` - `name` - `new-password` - `off` - `one-time-code` - `postal-code` - `street-address` - `tel` - `username` The following values work on iOS only: - `nickname` - `organization` - `organization-title` - `url` The following values work on Android only: - `birthdate-day` - `birthdate-full` - `birthdate-month` - `birthdate-year` - `cc-csc` - `cc-exp` - `cc-exp-day` - `cc-exp-month` - `cc-exp-year` - `2fa-app-otp` - `email-otp` - `flight-confirmation-code` - `flight-number` - `gender` - `gift-card-number` - `gift-card-pin` - `loyalty-account-number` - `name-family` - `name-given` - `name-middle` - `name-middle-initial` - `name-prefix` - `name-suffix` - `password` - `password-new` - `postal-address` - `postal-address-country` - `postal-address-dependent-locality` - `postal-address-extended` - `postal-address-extended-postal-code` - `postal-address-locality` - `postal-address-region` - `postal-address-unit` - `promo-code` - `sms-otp` - `tel-country-code` - `tel-national` - `tel-device` - `upi-vpa` - `wifi-password` - `username-new`"},{"name":"autoCorrect","type":"boolean | undefined","required":false,"description":"If false, disables auto-correct. The default value is true.","default":"false"},{"name":"autoFocus","type":"boolean | undefined","required":false,"description":"If true, focuses the input on componentDidMount. The default value is false.","default":"false"},{"name":"defaultValue","type":"string | undefined","required":false,"description":"Provides an initial value that will change when the user starts typing. Useful for simple use-cases where you don't want to deal with listening to events and updating the value prop to keep the controlled state in sync."},{"name":"keyboardType","type":"KeyboardTypeOptions | undefined","required":false,"description":"enum(\"default\", 'numeric', 'email-address', \"ascii-capable\", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search', 'visible-password') Determines which keyboard to open, e.g.numeric. The following values work across platforms: - default - numeric - email-address - phone-pad The following values work on iOS: - ascii-capable - numbers-and-punctuation - url - number-pad - name-phone-pad - decimal-pad - twitter - web-search The following values work on Android: - visible-password"},{"name":"inputMode","type":"InputModeOptions | undefined","required":false,"description":"Works like the inputmode attribute in HTML, it determines which keyboard to open, e.g. numeric and has precedence over keyboardType."},{"name":"maxLength","type":"number | undefined","required":false,"description":"Limits the maximum number of characters that can be entered. Use this instead of implementing the logic in JS to avoid flicker."},{"name":"onBlur","type":"((e: BlurEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input is blurred Note: If you are trying to find the last value of TextInput, you can use the `onEndEditing` event, which is fired upon completion of editing."},{"name":"onFocus","type":"((e: FocusEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input is focused"},{"name":"onSubmitEditing","type":"((e: TextInputSubmitEditingEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input's submit button is pressed."},{"name":"onKeyPress","type":"((e: TextInputKeyPressEvent) => void) | undefined","required":false,"description":"Callback that is called when a key is pressed. This will be called with `{ nativeEvent: { key: keyValue } }` where keyValue is 'Enter' or 'Backspace' for respective keys and the typed-in character otherwise including ' ' for space. Fires before onChange callbacks. Note: on Android only the inputs from soft keyboard are handled, not the hardware keyboard inputs."},{"name":"returnKeyType","type":"ReturnKeyTypeOptions | undefined","required":false,"description":"enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call') Determines how the return key should look."},{"name":"secureTextEntry","type":"boolean | undefined","required":false,"description":"If true, the text input obscures the text entered so that sensitive text like passwords stay secure. The default value is false.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"Used to locate this view in end-to-end tests"},{"name":"ref","type":"React.Ref<RNTextInput>","required":false,"description":"Ref to the underlying React Native host. Supports object refs and callback refs; native methods follow the platform's behavior."},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":4},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":4}],"groups":[{"title":"State","pickOne":false,"note":"State (orthogonal). `error` (alias `invalid`) flags a validation problem."},{"title":"Size","pickOne":true,"note":"Size (pick one; default is the medium field)."},{"title":"Addons","pickOne":false,"note":"Addons. Passing any of these switches the field to the grouped layout: a single control where a leading prefix and/or trailing suffix share one outer border with the field (squared joined edges, 1px inner separators), so they read as one piece rather than detached. Addons are plain strings, so no icon library is required at this layer."},{"title":"Overlaid glyph mode","pickOne":false,"note":"Overlaid glyph mode. Unlike prefix/suffix (a bordered addon box), these float a real Lucide glyph INSIDE the field with no separator, and pad the text away from it (pl-9 / pr-9). `icon` names which glyph (see ICON_BOOL)."},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"The Input component is a React Native text field with semantic boolean props\n(`error`, `small`, `large`, `compact`, `disabled`), plus prefix/suffix addons, overlaid\nicons (`leadingIcon` / `trailingIcon` with any Canvas glyph as `icon`), a\n`passwordToggle` eye for a `secureTextEntry` value, a `clearable` clear\nbutton, and a `shortcut` keycap. Input is single-line; for multi-line entry use the\ndedicated Textarea.\n\nOn the web the eye shows what pressing it does: the open eye while the value is masked,\nthe struck-through eye once it is revealed. A field held\nfocused by an `InteractionOverride` (a docs specimen) draws the web's 1.5px accent caret,\nblinking once a second, just after its value, since no real caret shows there.\n\n`shortcut` shows a keyboard shortcut hint at the field's end, the key that focuses a\nsearch field: a compact flat keycap (`<Kbd small flat>`, the 22 px cap; `tiny`, the 20 px\ncap, on a `small` field) after the value and any inline suffix and before the trailing\nglyphs, 8 px from the field's end and 10 px from the value (8 on a small field). It takes\nthe keys as Kbd's `keys` does: `\"⌘K\"` is one cap, `\"⌘ K\"` two. It is a hint only; bind\nthe key yourself.\n\nPass `label` (and `required`) to name the field:\niOS and web render the label\nabove the control, while Android floats the Material 3 in-container label. On\nAndroid the field grows with the user's text size so the floated label never\nmeets the value, and a label longer than the field truncates on one line inside\nit while the field's accessible name stays the whole label.\nThe required star is\ndecorative: a screen reader hears the field as required,\nfrom `aria-required` on\nthe web and from its name (\"Full name, required\") on iOS and Android.\nA field fills the parent it is given; a step of its own (`xs`, `lg`, …, with\n`start` to pin it to the leading edge) or a Container step sets its measure.\nSelect and the search field share its look, and Field and Form compose that\nlabel with helper and error text.\nOn iOS the field is the native text field in\nCanvas's colors: a card-colored box with a hairline, a muted title above, a glyph\nthat tints with focus and error, and in solid mode an error wash. Under glass a\nwash would cost the field's ink its contrast over the material, so the iOS field\ntakes none (the web's field a trace in dark only), and the error border, the tinted\nglyph and a Field's message carry the state.\nA prefix or suffix addon's fill is held to\nthe same bar: under glass it is only as dense as keeps its text at 4.5:1 over the field,\nso in the browser's light palettes and on the iOS field in dark it is a faint trace.\n\nInside an overlay, Escape follows the overlay's cancellation policy. A supplied\n`onKeyPress` runs first and can call `preventDefault()` to handle Escape locally.\nCancelling an IME candidate keeps the overlay open.\n\nOn web, the field is a sunken well: 40 pixels tall (32 small, 48 large) at the\n10-pixel field corner, a hairline edge, a 12-pixel inset, a regular 14-pixel value\n(13 small) and a medium 13-pixel muted label above. The edge darkens under the\npointer, takes the accent with a soft accent halo on focus, and turns red with a\nred halo for an error; a read-only field is a dashed edge on no fill, and a\ndisabled one dims. A prefix sits in a muted box behind a divider, a passive\nsuffix is inline monospace text before the clear button (a small raised disc with\nan x), and an action suffix is a button box at the end.\n\nOn iOS the clear button is the system's gray disc with an x, inside the boxed\nsuffix segment, and the action suffix's label is a semibold 15-point brand label.\nOn Android the suffix is inline text before the circled-x clear glyph, an errored\nfield shows a red alert glyph at its end (in place of a clear or eye button), and\na read-only field drops its fill under a dashed frame with a subtle underline.\n\n`eyebrow` uses the original dense uppercase web field label, preserving its\n9.5/12.35 metrics and tracking. Other platform label treatments retain their skin.\n\n`soft` uses the brand’s entry-well fill where the skin provides it.\n`systemFocus` preserves the platform’s system focus outline. An explicit\n`accessibilityLabel` takes precedence over the visible label’s accessible name.\n\nPass `search` for the toolbar search: a magnifier, a borderless editor, and a\nuppercase prompt while empty on web. The prompt names the editor unless\n`accessibilityLabel` or `label` supplies its purpose.\niOS draws its search field\n(a 36-point muted well) and Android the Material 3 search bar (a 56-dp muted\nstadium).\n`systemFocus` preserves the system\nfocus outline for the borderless editor.","ios":"The Input component is a React Native text field with semantic boolean props\n(`error`, `small`, `large`, `compact`, `disabled`), plus prefix/suffix addons, overlaid\nicons (`leadingIcon` / `trailingIcon` with any Canvas glyph as `icon`), a\n`passwordToggle` eye for a `secureTextEntry` value, a `clearable` clear\nbutton, and a `shortcut` keycap. Input is single-line; for multi-line entry use the\ndedicated Textarea.\n\nOn the web the eye shows what pressing it does: the open eye while the value is masked,\nthe struck-through eye once it is revealed. A field held\nfocused by an `InteractionOverride` (a docs specimen) draws the web's 1.5px accent caret,\nblinking once a second, just after its value, since no real caret shows there.\n\n`shortcut` shows a keyboard shortcut hint at the field's end, the key that focuses a\nsearch field: a compact flat keycap (`<Kbd small flat>`, the 22 px cap; `tiny`, the 20 px\ncap, on a `small` field) after the value and any inline suffix and before the trailing\nglyphs, 8 px from the field's end and 10 px from the value (8 on a small field). It takes\nthe keys as Kbd's `keys` does: `\"⌘K\"` is one cap, `\"⌘ K\"` two. It is a hint only; bind\nthe key yourself.\n\nPass `label` (and `required`) to name the field:\niOS renders the label above the control.\nThe required star is\ndecorative: a screen reader hears the field as required,\nfrom its name (\"Full name, required\").\nA field fills the parent it is given; a step of its own (`xs`, `lg`, …, with\n`start` to pin it to the leading edge) or a Container step sets its measure.\nSelect and the search field share its look, and Field and Form compose that\nlabel with helper and error text.\nOn iOS the field is the native text field in\nCanvas's colors: a card-colored box with a hairline, a muted title above, a glyph\nthat tints with focus and error, and in solid mode an error wash. Under glass a\nwash would cost the field's ink its contrast over the material, so the iOS field\ntakes none (the web's field a trace in dark only), and the error border, the tinted\nglyph and a Field's message carry the state.\nA prefix or suffix addon's fill is held to\nthe same bar: under glass it is only as dense as keeps its text at 4.5:1 over the field,\nso on the iOS field in dark it is a faint trace.\n\nInside an overlay, Escape follows the overlay's cancellation policy. A supplied\n`onKeyPress` runs first and can call `preventDefault()` to handle Escape locally.\nCancelling an IME candidate keeps the overlay open.\n\nOn web, the field is a sunken well: 40 pixels tall (32 small, 48 large) at the\n10-pixel field corner, a hairline edge, a 12-pixel inset, a regular 14-pixel value\n(13 small) and a medium 13-pixel muted label above. The edge darkens under the\npointer, takes the accent with a soft accent halo on focus, and turns red with a\nred halo for an error; a read-only field is a dashed edge on no fill, and a\ndisabled one dims. A prefix sits in a muted box behind a divider, a passive\nsuffix is inline monospace text before the clear button (a small raised disc with\nan x), and an action suffix is a button box at the end.\n\nOn iOS the clear button is the system's gray disc with an x, inside the boxed\nsuffix segment, and the action suffix's label is a semibold 15-point brand label.\n\n`eyebrow` uses the original dense uppercase web field label, preserving its\n9.5/12.35 metrics and tracking. Other platform label treatments retain their skin.\n\n`soft` uses the brand’s entry-well fill where the skin provides it.\n`systemFocus` preserves the platform’s system focus outline. An explicit\n`accessibilityLabel` takes precedence over the visible label’s accessible name.\n\nPass `search` for the toolbar search: a magnifier, a borderless editor, and a\nuppercase prompt while empty on web. The prompt names the editor unless\n`accessibilityLabel` or `label` supplies its purpose.\niOS draws its search field (a 36-point muted well).\n`systemFocus` preserves the system\nfocus outline for the borderless editor.","android":"The Input component is a React Native text field with semantic boolean props\n(`error`, `small`, `large`, `compact`, `disabled`), plus prefix/suffix addons, overlaid\nicons (`leadingIcon` / `trailingIcon` with any Canvas glyph as `icon`), a\n`passwordToggle` eye for a `secureTextEntry` value, a `clearable` clear\nbutton, and a `shortcut` keycap. Input is single-line; for multi-line entry use the\ndedicated Textarea.\n\nOn the web the eye shows what pressing it does: the open eye while the value is masked,\nthe struck-through eye once it is revealed. A field held\nfocused by an `InteractionOverride` (a docs specimen) draws the web's 1.5px accent caret,\nblinking once a second, just after its value, since no real caret shows there.\n\n`shortcut` shows a keyboard shortcut hint at the field's end, the key that focuses a\nsearch field: a compact flat keycap (`<Kbd small flat>`, the 22 px cap; `tiny`, the 20 px\ncap, on a `small` field) after the value and any inline suffix and before the trailing\nglyphs, 8 px from the field's end and 10 px from the value (8 on a small field). It takes\nthe keys as Kbd's `keys` does: `\"⌘K\"` is one cap, `\"⌘ K\"` two. It is a hint only; bind\nthe key yourself.\n\nPass `label` (and `required`) to name the field:\nAndroid floats the Material 3 in-container label. The field grows with the user's text size so the floated label never meets the value, and a label longer than the field truncates on one line inside it while the field's accessible name stays the whole label.\nThe required star is\ndecorative: a screen reader hears the field as required,\nfrom its name (\"Full name, required\").\nA field fills the parent it is given; a step of its own (`xs`, `lg`, …, with\n`start` to pin it to the leading edge) or a Container step sets its measure.\nSelect and the search field share its look, and Field and Form compose that\nlabel with helper and error text.\nA prefix or suffix addon's fill is held to\nthe same bar: under glass it is only as dense as keeps its text at 4.5:1 over the field,\nso in a light palette it is a faint trace.\n\nInside an overlay, Escape follows the overlay's cancellation policy. A supplied\n`onKeyPress` runs first and can call `preventDefault()` to handle Escape locally.\nCancelling an IME candidate keeps the overlay open.\n\nOn web, the field is a sunken well: 40 pixels tall (32 small, 48 large) at the\n10-pixel field corner, a hairline edge, a 12-pixel inset, a regular 14-pixel value\n(13 small) and a medium 13-pixel muted label above. The edge darkens under the\npointer, takes the accent with a soft accent halo on focus, and turns red with a\nred halo for an error; a read-only field is a dashed edge on no fill, and a\ndisabled one dims. A prefix sits in a muted box behind a divider, a passive\nsuffix is inline monospace text before the clear button (a small raised disc with\nan x), and an action suffix is a button box at the end.\n\nOn Android the suffix is inline text before the circled-x clear glyph, an errored\nfield shows a red alert glyph at its end (in place of a clear or eye button), and\na read-only field drops its fill under a dashed frame with a subtle underline.\n\n`eyebrow` uses the original dense uppercase web field label, preserving its\n9.5/12.35 metrics and tracking. Other platform label treatments retain their skin.\n\n`soft` uses the brand’s entry-well fill where the skin provides it.\n`systemFocus` preserves the platform’s system focus outline. An explicit\n`accessibilityLabel` takes precedence over the visible label’s accessible name.\n\nPass `search` for the toolbar search: a magnifier, a borderless editor, and a\nuppercase prompt while empty on web. The prompt names the editor unless\n`accessibilityLabel` or `label` supplies its purpose.\nAndroid draws the Material 3 search bar (a 56-dp muted stadium).\n`systemFocus` preserves the system\nfocus outline for the borderless editor."}},{"slug":"input-otp","name":"InputOTP","category":"atoms","description":"A segmented one-time-code field: `length` cells display the typed characters while one underlying text input captures the keystrokes, so native SMS autofill, the one-time-code keyboard suggestion, and paste all flow into a single value.","source":"src/atoms/input-otp/input-otp.md","url":"https://canvas.nannier.com/ai/4.2.0/components/input-otp.md","humanUrl":"https://canvas.nannier.com/components/input-otp","exports":["InputOTP","InputOTPProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"InputOTPProps","props":[{"name":"length","type":"number | undefined","required":false,"description":"Number of segment cells (and the max code length). Default 6.","default":"6"},{"name":"value","type":"string | undefined","required":false,"description":"Current code (controlled). Only the typed characters, e.g. \"123\". Omit for uncontrolled use; a bare <InputOTP /> is typeable out of the box."},{"name":"defaultValue","type":"string | undefined","required":false,"description":"Starting code for the uncontrolled field. Defaults to empty.","default":"\"\""},{"name":"onChangeText","type":"((code: string) => void) | undefined","required":false,"description":"Called with the new code (cleaned, sliced to `length`) on each change (both modes)."},{"name":"onComplete","type":"((code: string) => void) | undefined","required":false,"description":"Fired once when the code reaches `length` digits."},{"name":"groups","type":"number | undefined","required":false,"description":"Split the run into groups of this many cells, separated by a dash: `length={6}` with `groups={3}` reads 123-456. Omit for one unbroken run."},{"name":"alphanumeric","type":"boolean | undefined","required":false,"description":"Accept letters as well as digits, and ask for the text keyboard instead of the number pad. Off by default: a one-time code is digits only.","default":"false"},{"name":"autoFocus","type":"boolean | undefined","required":false,"description":"Focus the field on mount.","default":"false"},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Disable input and dim the cells.","default":"false"},{"name":"masked","type":"boolean | undefined","required":false,"description":"Render a bullet (●) instead of the character, for passcode entry.","default":"false"},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium cell).","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium cell).","default":"false","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0},{"name":"ref","type":"React.Ref<RNTextInput>","required":false,"description":"Ref to the underlying React Native host. Supports object refs and callback refs; native methods follow the platform's behavior."}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default is the medium cell)."}],"inherits":[]}],"platformNotes":{"web":"A segmented one-time-code field: `length` cells display the typed characters while one underlying text input captures the keystrokes, so native SMS autofill, the one-time-code keyboard suggestion, and paste all flow into a single value.\n\nBecause that one input spans the whole row, the caret is pinned to the end of the code: tap any cell and the next character still lands in the first unfilled one, so a keystroke can never drop into the middle of a partly-entered code. It works controlled (`value` + `onChangeText`) or uncontrolled (`defaultValue`, or a bare `<InputOTP />` that is typeable out of the box); `onComplete` fires once the code reaches `length` characters. Style and shape it with semantic props: `groups` splits the run into dash-separated chunks, `alphanumeric` accepts letters as well as digits, and `small`, `large`, `masked`, `disabled` and `autoFocus` do what they say.","ios":"A segmented one-time-code field: `length` cells display the typed characters while one underlying text input captures the keystrokes, so native SMS autofill, the one-time-code keyboard suggestion, and paste all flow into a single value.\n\nBecause that one input spans the whole row, the caret is pinned to the end of the code: tap any cell and the next character still lands in the first unfilled one, so a keystroke can never drop into the middle of a partly-entered code. It works controlled (`value` + `onChangeText`) or uncontrolled (`defaultValue`, or a bare `<InputOTP />` that is typeable out of the box); `onComplete` fires once the code reaches `length` characters. Style and shape it with semantic props: `groups` splits the run into dash-separated chunks, `alphanumeric` accepts letters as well as digits, and `small`, `large`, `masked`, `disabled` and `autoFocus` do what they say.","android":"A segmented one-time-code field: `length` cells display the typed characters while one underlying text input captures the keystrokes, so native SMS autofill, the one-time-code keyboard suggestion, and paste all flow into a single value.\n\nBecause that one input spans the whole row, the caret is pinned to the end of the code: tap any cell and the next character still lands in the first unfilled one, so a keystroke can never drop into the middle of a partly-entered code. It works controlled (`value` + `onChangeText`) or uncontrolled (`defaultValue`, or a bare `<InputOTP />` that is typeable out of the box); `onComplete` fires once the code reaches `length` characters. Style and shape it with semantic props: `groups` splits the run into dash-separated chunks, `alphanumeric` accepts letters as well as digits, and `small`, `large`, `masked`, `disabled` and `autoFocus` do what they say."}},{"slug":"kbd","name":"Kbd","category":"atoms","description":"Keyboard shortcut indicator: a raised 24 px key cap with a mono label. `keys` composes a whole shortcut, one cap per key; `sequence` says \"then\" between the caps of keys pressed one after another. A shortcut reads as one accessible name (\"⌘+K\", \"G then C\"). `comfortable` pads the cap 3 px above and below its label and 8 px at the sides (25 px tall) for a key set beside what it does, as a reference's keyboard table lists it; omit it for the 24 px cap with 6 px sides.","source":"src/atoms/kbd/kbd.md","url":"https://canvas.nannier.com/ai/4.2.0/components/kbd.md","humanUrl":"https://canvas.nannier.com/components/kbd","exports":["Kbd","KbdProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"KbdProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"A single key label, rendered as one cap. Ignored when `keys` is set."},{"name":"keys","type":"string | string[] | undefined","required":false,"description":"A multi-key shortcut (a combo, pressed together), rendered as one cap per key. Pass a whitespace-separated string (`\"⌘ K\"`) or an array (`[\"⌘\", \"K\"]`). A single entry renders one cap, identical to passing that key as `children`. When set, `keys` takes precedence over `children`."},{"name":"sequence","type":"boolean | undefined","required":false,"description":"Render a key SEQUENCE (press one, then the next): the caps are separated by \"then\". Only affects the `keys` form.","default":"false"},{"name":"comfortable","type":"boolean | undefined","required":false,"description":"The comfortable cap: padded 3 px above and below its label and 8 px at the sides (25 px tall), the key the hand-off's component page sets beside a key's effect. Omit for the 24 px cap with 6 px sides.","default":"false"},{"name":"small","type":"boolean | undefined","required":false,"description":"The compact 22 px cap: 6 px sides on the small key corner, a 500 11 px label on a 20 px line (the hint a search field or a command palette shows, `<Kbd small flat>`). Size precedence: `small` > `tiny`; a size step wins over `comfortable`.","default":"false"},{"name":"tiny","type":"boolean | undefined","required":false,"description":"The compact 20 px cap: 5 px sides on the tiny key corner, a 500 10 px label on an 18 px line.","default":"false"},{"name":"flat","type":"boolean | undefined","required":false,"description":"The hint cap's edge: one pixel all round (no raised 2 px bottom) and the label in the secondary ink, the keycap a field or a menu shows beside what it opens.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"Keyboard shortcut indicator: a raised 24 px key cap with a mono label. `keys`\ncomposes a whole shortcut, one cap per key; `sequence` says \"then\" between the\ncaps of keys pressed one after another. A shortcut reads as one accessible name\n(\"⌘+K\", \"G then C\"). `comfortable` pads the cap 3 px above and below its label and\n8 px at the sides (25 px tall) for a key set beside what it does, as a reference's\nkeyboard table lists it; omit it for the 24 px cap with 6 px sides.\n\nTwo compact sizes take the cap down for a hint beside a field or a menu: `small`, the\n22 px cap with 6 px sides at a 5 px corner and a 500 11 px label, and `tiny`, the 20 px cap\nwith 5 px sides at a 4 px corner and a 500 10 px label. Size precedence is `small`, then\n`tiny`, and a size step wins over `comfortable`. `flat` is the hint cap's edge: one pixel\nall round instead of the raised 2 px bottom, and the label in the secondary ink. An\n`Input` draws its `shortcut` hint as `<Kbd small flat>` (`tiny` on a small field).","ios":"Keyboard shortcut indicator: a raised 24 px key cap with a mono label. `keys`\ncomposes a whole shortcut, one cap per key; `sequence` says \"then\" between the\ncaps of keys pressed one after another. A shortcut reads as one accessible name\n(\"⌘+K\", \"G then C\"). `comfortable` pads the cap 3 px above and below its label and\n8 px at the sides (25 px tall) for a key set beside what it does, as a reference's\nkeyboard table lists it; omit it for the 24 px cap with 6 px sides.\n\nTwo compact sizes take the cap down for a hint beside a field or a menu: `small`, the\n22 px cap with 6 px sides at a 5 px corner and a 500 11 px label, and `tiny`, the 20 px cap\nwith 5 px sides at a 4 px corner and a 500 10 px label. Size precedence is `small`, then\n`tiny`, and a size step wins over `comfortable`. `flat` is the hint cap's edge: one pixel\nall round instead of the raised 2 px bottom, and the label in the secondary ink. An\n`Input` draws its `shortcut` hint as `<Kbd small flat>` (`tiny` on a small field).","android":"Keyboard shortcut indicator: a raised 24 px key cap with a mono label. `keys`\ncomposes a whole shortcut, one cap per key; `sequence` says \"then\" between the\ncaps of keys pressed one after another. A shortcut reads as one accessible name\n(\"⌘+K\", \"G then C\"). `comfortable` pads the cap 3 px above and below its label and\n8 px at the sides (25 px tall) for a key set beside what it does, as a reference's\nkeyboard table lists it; omit it for the 24 px cap with 6 px sides.\n\nTwo compact sizes take the cap down for a hint beside a field or a menu: `small`, the\n22 px cap with 6 px sides at a 5 px corner and a 500 11 px label, and `tiny`, the 20 px cap\nwith 5 px sides at a 4 px corner and a 500 10 px label. Size precedence is `small`, then\n`tiny`, and a size step wins over `comfortable`. `flat` is the hint cap's edge: one pixel\nall round instead of the raised 2 px bottom, and the label in the secondary ink. An\n`Input` draws its `shortcut` hint as `<Kbd small flat>` (`tiny` on a small field)."}},{"slug":"line-chart","name":"LineChart","category":"charts","description":"Categorical-x series lines with nice y ticks, gridlines, and a legend for multiple series.","source":"src/charts/line-chart/line-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/line-chart.md","humanUrl":"https://canvas.nannier.com/components/line-chart","exports":["LineChart","LineChartProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"LineChartProps","props":[{"name":"dots","type":"boolean | undefined","required":false,"description":"Mark each datum with a dot.","default":"false"},{"name":"baseline","type":"number | undefined","required":false,"description":"Reference value (e.g. previous close) drawn as a dashed line. A single series with no explicit tone auto-tones success/destructive by whether its last value sits above or below the baseline - the trading-app gain/loss idiom."},{"name":"fade","type":"boolean | undefined","required":false,"description":"Soft gradient fade under the lead (first) series' line (the price-chart look).","default":"false"},{"name":"labels","type":"string[]","required":true,"description":"Category labels along the x axis, one per data column."},{"name":"series","type":"ChartSeries[]","required":true,"description":"The series to plot; colors follow the chart-1..8 tokens in fixed order, or a series' own `success`/`destructive` tone."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"max","type":"number | undefined","required":false,"description":"Y-axis maximum override. Defaults to a nice bound above the data max."},{"name":"min","type":"number | undefined","required":false,"description":"Y-axis minimum override. Defaults to 0 (or the data min when negative)."},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (single-series only; pick one; default is the primary fill).","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (single-series only; pick one; default is the primary fill).","default":"false","group":0},{"name":"curved","type":"boolean | undefined","required":false,"description":"Curve (omit for straight segments).","default":"false","group":1},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":2},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":2},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"hideAxes","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats tick labels and accessible values (data formatting, not styling).","group":3},{"name":"selected","type":"number | null | undefined","required":false,"description":"Scrub-to-inspect: the selected category index (controlled). Pass null for none.","group":3},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Scrub-to-inspect: the initially selected category (uncontrolled).","group":3},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press/scrub selects a category (or clears it with null).","group":3},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":3},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":3}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (single-series only; pick one; default is the primary fill)."},{"title":"Curve","pickOne":false,"note":"Curve (omit for straight segments)."},{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."},{"title":"Furniture visibility","pickOne":false}],"inherits":["CartesianSeriesProps"]}],"platformNotes":{"web":"Categorical-x series lines with nice y ticks, gridlines, and a legend for multiple series.\n\n`curved` draws a monotone cubic that never overshoots the data, `dots` marks each datum, and `baseline` + `fade` give the trading-app price idiom (dashed previous close, gain/loss auto tone, gradient fill). A series that means success or failure carries its own `success` / `destructive` tone instead of a ramp color. Press or scrub the plot to inspect a category.","ios":"Categorical-x series lines with nice y ticks, gridlines, and a legend for multiple series.\n\n`curved` draws a monotone cubic that never overshoots the data, `dots` marks each datum, and `baseline` + `fade` give the trading-app price idiom (dashed previous close, gain/loss auto tone, gradient fill). A series that means success or failure carries its own `success` / `destructive` tone instead of a ramp color. Press or scrub the plot to inspect a category.","android":"Categorical-x series lines with nice y ticks, gridlines, and a legend for multiple series.\n\n`curved` draws a monotone cubic that never overshoots the data, `dots` marks each datum, and `baseline` + `fade` give the trading-app price idiom (dashed previous close, gain/loss auto tone, gradient fill). A series that means success or failure carries its own `success` / `destructive` tone instead of a ramp color. Press or scrub the plot to inspect a category."}},{"slug":"listbox","name":"Listbox","category":"atoms","description":"A custom select whose options stay on screen: single or multi-select, an optional detail line under each option, and a checkmark on the chosen items. Reach for it when the options need rich rows; prefer `Select` for a simple short list.","source":"src/atoms/listbox/listbox.md","url":"https://canvas.nannier.com/ai/4.2.0/components/listbox.md","humanUrl":"https://canvas.nannier.com/components/listbox","exports":["Listbox","ListboxItem","ListboxProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ListboxProps","props":[{"name":"items","type":"ListboxItem[]","required":true,"description":"The options to render, top to bottom."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name of the option list or multi-select checkbox group. Defaults to \"Options\"."},{"name":"multi","type":"boolean | undefined","required":false,"description":"Multi-select: each row is a checkbox (a leading indicator on the web and Android, a trailing ✓ on iOS) instead of a single choice.","default":"false"},{"name":"bordered","type":"boolean | undefined","required":false,"description":"Wrap the list in a rounded, bordered content card with static glass in glass mode.","default":"false"},{"name":"small","type":"boolean | undefined","required":false,"description":"Tighter rows with smaller text.","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Taller rows.","default":"false","group":0},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Dim the list and block selection.","default":"false","group":0},{"name":"selected","type":"number | number[] | undefined","required":false,"description":"Selected option index(es) (CONTROLLED): a single index in single-select, an array of indices in multi-select. Omit for uncontrolled use.","group":0},{"name":"defaultSelected","type":"number | number[] | undefined","required":false,"description":"Initial selection for uncontrolled use (a bare listbox selects on press). Falls back to the `selected` flags on `items` when omitted.","group":0},{"name":"onChange","type":"((selected: number | number[]) => void) | undefined","required":false,"description":"Fired with the full new selection (an index in single-select, an index array in multi).","group":0},{"name":"onSelect","type":"((index: number) => void) | undefined","required":false,"description":"Fired with the pressed option's index.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root list view.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":1}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default is medium)."},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"A custom select whose options stay on screen: single or multi-select, an optional detail line under each option, and a checkmark on the chosen items. Reach for it when the options need rich rows; prefer `Select` for a simple short list.\n\nThe list fills the parent it is given; a step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container step sets its measure.\n\nNeither iOS nor Material 3 ships a listbox, so every platform draws the Canvas v4 list, in its own face:\na chosen row sits on the accent's soft wash with a 16px check at its end in the accent ink, in single and multi select alike, and the check's slot is kept on every row so a choice never reflows a label.\n\nThe rows are 10px in with a 500 14/18.2px label (13px small) over a 400 12/16.2px detail in the subtle ink, rounded concentric inside a bordered list, which is the `popover` fill behind the `field-border` hairline at the tile corner with a 4px inset. A pressed row takes the `muted` wash, and on the web a row under the pointer takes the hover wash at once.\n\nSingle-select exposes a list of selectable options. With `multi`, it exposes a checkbox group: each row owns its label, checked state, and tap target. Give either mode a meaningful `accessibilityLabel`; the fallback is \"Options\". Arrow keys and Home/End move focus within one tab stop. Single-select follows focus, while multi-select keeps the current selection until Enter or Space toggles the focused row.","ios":"A custom select whose options stay on screen: single or multi-select, an optional detail line under each option, and a checkmark on the chosen items. Reach for it when the options need rich rows; prefer `Select` for a simple short list.\n\nThe list fills the parent it is given; a step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container step sets its measure.\n\niOS ships no listbox, so it draws the Canvas v4 list, in its own face:\na chosen row sits on the accent's soft wash with a 16px check at its end in the accent ink, in single and multi select alike, and the check's slot is kept on every row so a choice never reflows a label.\n\nThe rows are 10px in with a 500 14/18.2px label (13px small) over a 400 12/16.2px detail in the subtle ink, rounded concentric inside a bordered list, which is the `popover` fill behind the `field-border` hairline at the tile corner with a 4px inset. A pressed row takes the `muted` wash, and on the web a row under the pointer takes the hover wash at once.\n\nSingle-select exposes a list of selectable options. With `multi`, it exposes a checkbox group: each row owns its label, checked state, and tap target. Give either mode a meaningful `accessibilityLabel`; the fallback is \"Options\". Arrow keys and Home/End move focus within one tab stop. Single-select follows focus, while multi-select keeps the current selection until Enter or Space toggles the focused row.","android":"A custom select whose options stay on screen: single or multi-select, an optional detail line under each option, and a checkmark on the chosen items. Reach for it when the options need rich rows; prefer `Select` for a simple short list.\n\nThe list fills the parent it is given; a step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container step sets its measure.\n\nMaterial 3 ships no listbox, so Android draws the Canvas v4 list, in its own face:\na chosen row sits on the accent's soft wash with a 16px check at its end in the accent ink, in single and multi select alike, and the check's slot is kept on every row so a choice never reflows a label.\n\nThe rows are 10px in with a 500 14/18.2px label (13px small) over a 400 12/16.2px detail in the subtle ink, rounded concentric inside a bordered list, which is the `popover` fill behind the `field-border` hairline at the tile corner with a 4px inset. A pressed row takes the `muted` wash, and on the web a row under the pointer takes the hover wash at once.\n\nSingle-select exposes a list of selectable options. With `multi`, it exposes a checkbox group: each row owns its label, checked state, and tap target. Give either mode a meaningful `accessibilityLabel`; the fallback is \"Options\". Arrow keys and Home/End move focus within one tab stop. Single-select follows focus, while multi-select keeps the current selection until Enter or Space toggles the focused row."}},{"slug":"media-objects","name":"MediaObject","category":"molecules","description":"Image or icon paired with text content. The fundamental building block for list items, notifications, and comment layouts.","source":"src/molecules/media-objects/media-objects.md","url":"https://canvas.nannier.com/ai/4.2.0/components/media-objects.md","humanUrl":"https://canvas.nannier.com/components/media-objects","exports":["MediaObject","MediaObjectProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"MediaObjectProps","props":[{"name":"title","type":"string | undefined","required":false,"description":"Primary line: the bold heading (e.g. a person's name)."},{"name":"description","type":"string | undefined","required":false,"description":"Secondary line: muted supporting text under the title (e.g. a role or email)."},{"name":"body","type":"ReactNode","required":false,"description":"Optional longer body paragraph rendered below the description."},{"name":"meta","type":"string | undefined","required":false,"description":"Trailing metadata text pinned to the right (e.g. \"2h ago\", \"admin\")."},{"name":"avatar","type":"string | undefined","required":false,"description":"Initials for the leading avatar (e.g. \"RC\"); rendered as <Avatar>{avatar}</Avatar>."},{"name":"src","type":"string | number | undefined","required":false,"description":"Photo for the leading avatar (a URI string or a bundled `require(...)` image); takes precedence over initials."},{"name":"icon","type":"ReactNode","required":false,"description":"A leading icon glyph rendered in a tinted square box (stands in for an SVG icon)."},{"name":"bareIcon","type":"boolean | undefined","required":false,"description":"Draw the `icon` node as it is, with no tinted box around it: a lead that is its own mark, such as a numbered `<Badge step>` (the Layout page's \"try in this order\" list).","default":"false"},{"name":"action","type":"ReactNode","required":false,"description":"A trailing action node (e.g. a <Button>), pinned to the right edge."},{"name":"onPress","type":"(() => void) | undefined","required":false,"description":"Make the whole row a tappable target (navigate to a detail, select a row). When set, the row renders as a Pressable with a button role and a pressed affordance, so you never hand-roll a Pressable for a tappable media row."},{"name":"center","type":"boolean | undefined","required":false,"description":"Alignment (pick one; default top-aligns with items-start).","default":"false","group":0},{"name":"start","type":"boolean | undefined","required":false,"description":"Alignment (pick one; default top-aligns with items-start).","default":"false","group":0},{"name":"reversed","type":"boolean | undefined","required":false,"description":"Direction (pick one; default leads with the media on the left).","default":"false","group":1},{"name":"leading","type":"boolean | undefined","required":false,"description":"Direction (pick one; default leads with the media on the left).","default":"false","group":1},{"name":"bordered","type":"boolean | undefined","required":false,"description":"Surface.","default":"false","group":2},{"name":"compact","type":"boolean | undefined","required":false,"description":"Menu-header density: a smaller leading avatar (28px) and title/description type stepped down one size, for a compact identity row (e.g. a menu or dropdown header). Backward-compatible; without it the row keeps its default 40px avatar and type.","default":"false","group":3},{"name":"truncate","type":"boolean | undefined","required":false,"description":"Layout.","default":"false","group":4},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":4},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":4}],"groups":[{"title":"Alignment","pickOne":true,"note":"Alignment (pick one; default top-aligns with items-start)."},{"title":"Direction","pickOne":true,"note":"Direction (pick one; default leads with the media on the left)."},{"title":"Surface","pickOne":false},{"title":"Density","pickOne":false},{"title":"Layout","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"Image or icon paired with text content. The fundamental building block for list items, notifications, and comment layouts.","ios":"Image or icon paired with text content. The fundamental building block for list items, notifications, and comment layouts.","android":"Image or icon paired with text content. The fundamental building block for list items, notifications, and comment layouts."}},{"slug":"metric-breakdown","name":"MetricBreakdown","category":"charts","description":"The decomposed-metric dashboard card: headline value, tone-aware rate, Sparkline trend, per-category share rows, and a chip footer.","source":"src/charts/metric-breakdown/metric-breakdown.md","url":"https://canvas.nannier.com/ai/4.2.0/components/metric-breakdown.md","humanUrl":"https://canvas.nannier.com/components/metric-breakdown","exports":["MetricBreakdown","MetricBreakdownChip","MetricBreakdownProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"MetricBreakdownProps","props":[{"name":"value","type":"string","required":true,"description":"The headline figure, preformatted (e.g. \"3,771\")."},{"name":"label","type":"string","required":true,"description":"Small caption over the headline (e.g. \"Tokens issued\")."},{"name":"rate","type":"string | undefined","required":false,"description":"Secondary metric, under the headline (e.g. \"1.39%\")."},{"name":"rateLabel","type":"string | undefined","required":false,"description":"Caption after the rate (e.g. \"Error rate\")."},{"name":"rateSuccess","type":"boolean | undefined","required":false,"description":"Rate tone (slot-scoped; pick one; default muted). Precedence: rateSuccess > rateWarning > rateDestructive (first match wins).","default":"false","group":0},{"name":"rateWarning","type":"boolean | undefined","required":false,"description":"Rate tone (slot-scoped; pick one; default muted). Precedence: rateSuccess > rateWarning > rateDestructive (first match wins).","default":"false","group":0},{"name":"rateDestructive","type":"boolean | undefined","required":false,"description":"Rate tone (slot-scoped; pick one; default muted). Precedence: rateSuccess > rateWarning > rateDestructive (first match wins).","default":"false","group":0},{"name":"spark","type":"number[] | undefined","required":false,"description":"Trend series rendered as a Sparkline bar strip beside the headline. Needs at least two points to draw.","group":0},{"name":"sparkUnit","type":"string | undefined","required":false,"description":"Unit suffix on the latest-value caption (e.g. \"req/s\").","group":0},{"name":"hideSparkTag","type":"boolean | undefined","required":false,"description":"Hide the latest-value tag over the trend strip (the strip alone, when the headline already carries the figure).","default":"false","group":0},{"name":"breakdown","type":"BreakdownRow[] | undefined","required":false,"description":"Per-category rows with proportional share bars.","group":0},{"name":"chips","type":"MetricBreakdownChip[] | undefined","required":false,"description":"Footer chips rendered with the kit Chip (e.g. top error codes).","group":0},{"name":"chipsLabel","type":"string | undefined","required":false,"description":"Leading caption on the chip row (e.g. \"Errors\"). Omit to hide.","group":0},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats row values and the spark tag (data formatting, not styling).","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default spacing).","default":"false","group":1},{"name":"detailed","type":"boolean | undefined","required":false,"description":"Expanded metric summary with a divided share breakdown and trend annotation.","default":"false","group":1},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Rate tone","pickOne":true,"note":"Rate tone (slot-scoped; pick one; default muted). Precedence: rateSuccess > rateWarning > rateDestructive (first match wins)."},{"title":"Density","pickOne":false,"note":"Density (omit for the default spacing)."}],"inherits":[]}],"platformNotes":{"web":"The decomposed-metric dashboard card: headline value, tone-aware rate, Sparkline trend, per-category share rows, and a chip footer.\n\nIt holds a preformatted headline `value` with its caption, an optional secondary `rate` readout under the headline (toned by `rateSuccess`, `rateWarning`, or `rateDestructive`), an optional trend strip drawn by the kit Sparkline at the header's end with a latest-value caption above it, per-category `breakdown` rows with proportional share meters and Stats-style deltas, and a `chips` footer for recent notable codes. Every section is independently optional, so one layout backs OAuth token issuance, API request volume, sign-up sources, and any metric that needs decomposition plus trend in one card.\n\n`detailed` emphasizes the value without repeating its caption, shows a trend arrow beside the rate and places the share rows under a divider. Its spark values are percentages from zero to one hundred; `rateLabel` supplies the period comparison.","ios":"The decomposed-metric dashboard card: headline value, tone-aware rate, Sparkline trend, per-category share rows, and a chip footer.\n\nIt holds a preformatted headline `value` with its caption, an optional secondary `rate` readout under the headline (toned by `rateSuccess`, `rateWarning`, or `rateDestructive`), an optional trend strip drawn by the kit Sparkline at the header's end with a latest-value caption above it, per-category `breakdown` rows with proportional share meters and Stats-style deltas, and a `chips` footer for recent notable codes. Every section is independently optional, so one layout backs OAuth token issuance, API request volume, sign-up sources, and any metric that needs decomposition plus trend in one card.\n\n`detailed` emphasizes the value without repeating its caption, shows a trend arrow beside the rate and places the share rows under a divider. Its spark values are percentages from zero to one hundred; `rateLabel` supplies the period comparison.","android":"The decomposed-metric dashboard card: headline value, tone-aware rate, Sparkline trend, per-category share rows, and a chip footer.\n\nIt holds a preformatted headline `value` with its caption, an optional secondary `rate` readout under the headline (toned by `rateSuccess`, `rateWarning`, or `rateDestructive`), an optional trend strip drawn by the kit Sparkline at the header's end with a latest-value caption above it, per-category `breakdown` rows with proportional share meters and Stats-style deltas, and a `chips` footer for recent notable codes. Every section is independently optional, so one layout backs OAuth token issuance, API request volume, sign-up sources, and any metric that needs decomposition plus trend in one card.\n\n`detailed` emphasizes the value without repeating its caption, shows a trend arrow beside the rate and places the share rows under a divider. Its spark values are percentages from zero to one hundred; `rateLabel` supplies the period comparison."}},{"slug":"navbars","name":"Navbar","category":"organisms","description":"Topbars with a brand, navigation links, and an action button. Used as the primary app-level navigation.","source":"src/organisms/navbars/navbars.md","url":"https://canvas.nannier.com/ai/4.2.0/components/navbars.md","humanUrl":"https://canvas.nannier.com/components/navbars","exports":["Navbar","NavbarProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"NavbarProps","props":[{"name":"brand","type":"string | undefined","required":false,"description":"Brand or product name shown at the left, in a semibold face."},{"name":"brandContent","type":"ReactNode","required":false,"description":"A brand ELEMENT for the left cluster (a logo mark, a workspace switcher). It LEADS the cluster, so passing it beside `brand` renders the mark first and keeps the wordmark beside it; passing it alone makes the mark the whole brand. It takes the left cluster's own gap, so it needs no wrapper."},{"name":"brandHref","type":"string | undefined","required":false,"description":"Where the brand leads (an app's home, `/`). With it, or with `onBrandPress`, the brand lockup is one link: a real anchor on the web (an `<a href>`, so middle-click and modifier-click open it in a new tab), named by `brand`, with the kit's focus ring."},{"name":"onBrandPress","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Called when the brand is pressed; on the web a modifier-click on a `brandHref` stays the browser's."},{"name":"brandDivider","type":"boolean | undefined","required":false,"description":"Draw a short vertical separator between the brand and the links (the kit `<Divider vertical inset strong />`), as the hand-off's floating docs pill does. It shows only while both the brand and the links row are on the bar, so a collapsed bar or one without links never ends its brand on a stray rule.","default":"false"},{"name":"links","type":"string[] | undefined","required":false,"description":"Ordered navigation link labels rendered in the middle row. Omit it (or pass an empty array) for a bar with no middle nav: neither the links row nor the narrow menu button that stands in for it renders."},{"name":"hrefs","type":"string[] | undefined","required":false,"description":"Destinations for `links`, by index (parallel to it). A link with an href renders as a real anchor on the web (an `<a href>`, so middle-click, modifier-click and open-in-new-tab work); natively it is ignored. A plain click still selects the link and calls `onSelect` with the press event, so an app that routes on the client calls `event.preventDefault()` there; a modifier or middle click is left to the browser and selects nothing. Omit it (or an entry) for a link without a destination."},{"name":"active","type":"number | undefined","required":false,"description":"Index of the active link (CONTROLLED; its label reads in the foreground color). Omit for uncontrolled use."},{"name":"defaultActive","type":"number | undefined","required":false,"description":"Initial active link for uncontrolled use (a bare navbar moves the active link on press)."},{"name":"actions","type":"ReactNode","required":false,"description":"Free-form trailing controls for the right cluster: a ghost search button, icon buttons, a notification dropdown, an account menu. They LEAD the cluster, ahead of the built-in `actionLabel` button and `avatar`, and take the cluster's own gap, so they need no wrapper. Keep them few and compact: the bar is a fixed height and the slot is rendered as given at every width."},{"name":"actionLabel","type":"string | undefined","required":false,"description":"Optional primary action; renders a <Button primary small> on the right."},{"name":"onAction","type":"(() => void) | undefined","required":false,"description":"Called when the action button is pressed."},{"name":"avatar","type":"string | undefined","required":false,"description":"Optional account initials/name; renders an <Avatar small> on the right."},{"name":"onSelect","type":"((index: number, event?: GestureResponderEvent) => void) | undefined","required":false,"description":"Called when a nav link is pressed, with its index, and the press event when it came from the link itself (not from the narrow menu)."},{"name":"onMenu","type":"(() => void) | undefined","required":false,"description":"The app's own navigation menu. When set, the bar leads with a menu button at every width and calls this on press, so the app can open navigation of its own (a Drawer of grouped sections). It replaces the `links` row and its narrow menu: pass one or the other."},{"name":"bordered","type":"boolean | undefined","required":false,"description":"Surface (pick one; default is the flush bottom-hairline bar).","default":"false","group":0},{"name":"floating","type":"boolean | undefined","required":false,"description":"Surface (pick one; default is the flush bottom-hairline bar).","default":"false","group":0},{"name":"bare","type":"boolean | undefined","required":false,"description":"No surface and no hairline: the bar sits clear on what is behind it. Pass it while nothing has scrolled under the bar (the scroll edge) and drop it once content does.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"The tight bar: 44px with a 5px inset and 2px between items on the web (the docs pill).","default":"false","group":1},{"name":"scrolls","type":"boolean | undefined","required":false,"description":"Keep every link at every width: the bar's content row scrolls sideways inside the bar (no scroll indicator) instead of folding the links into the narrow menu button. Pair it with `floating` and `compact` for the hand-off's docs pill.","default":"false","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook.","group":1}],"groups":[{"title":"Surface","pickOne":true,"note":"Surface (pick one; default is the flush bottom-hairline bar)."},{"title":"Density","pickOne":true,"note":"Density (pick one; default is the comfortable bar)."}],"inherits":[]}],"platformNotes":{"web":"Topbars with a brand, navigation links, and an action button. Used as the\nprimary app-level navigation.\n\nThe bar measures its own width: at and below the `sm` breakpoint (640) the links\nrow automatically collapses into a menu button opening a dropdown of the same\nlinks (the active one checkmarked), so links never clip off a phone screen;\n`active` and `onSelect` keep their contract in both renderings.\nThe menu button\nleads the bar, ahead of the logo and brand, where Material 3's top app bar puts\nits navigation icon.\nPass `scrolls` to keep every link at every width instead: the bar's content row\nthen pans sideways inside the bar, with no scroll indicator, and the links never\nfold into the menu. `onMenu` still replaces the links when both are passed.\n\nOn the web the bar is the v4 hand-off's: 56px tall with a 16px gutter, 32px\ncapsule links in the interface face, the active one (and a hovered one) on the\n`secondary` fill. `floating` lifts it as a pill on the stronger hairline with the\nmd shade.\nOn iOS and Android the bar keeps the platform's own navigation bar and\ntop app bar shape.\n\nIn glass mode the active link paints a control-layer pane\n(iOS keeps its\ninactive capsules and carries the brand fill as glass, web and Android carry\ntheir tinted tile),\nand the collapsed menu is Dropdown's dense-layer glass card\nunder the hamburger. Solid mode keeps the skin's own active tile.\n\nEither cluster takes a caller-supplied element beside its built-in parts:\n`brandContent` leads the left one with a logo mark (beside or instead of the\n`brand` wordmark) and `actions` leads the right one with free-form trailing\ncontrols (a search button, icon buttons), ahead of `actionLabel` and `avatar`.\n`links` is optional, so a console topbar with no middle nav renders neither the\nlinks row nor the menu button that stands in for it.","ios":"Topbars with a brand, navigation links, and an action button. Used as the\nprimary app-level navigation.\n\nThe bar measures its own width: at and below the `sm` breakpoint (640) the links\nrow automatically collapses into a menu button opening a dropdown of the same\nlinks (the active one checkmarked), so links never clip off a phone screen;\n`active` and `onSelect` keep their contract in both renderings.\nThe menu button leads the bar, ahead of the logo and brand.\nPass `scrolls` to keep every link at every width instead: the bar's content row\nthen pans sideways inside the bar, with no scroll indicator, and the links never\nfold into the menu. `onMenu` still replaces the links when both are passed.\n\nOn the web the bar is the v4 hand-off's: 56px tall with a 16px gutter, 32px\ncapsule links in the interface face, the active one (and a hovered one) on the\n`secondary` fill. `floating` lifts it as a pill on the stronger hairline with the\nmd shade.\nOn iOS the bar keeps the platform's own navigation bar shape.\n\nIn glass mode the active link paints a control-layer pane\n(iOS keeps its inactive capsules and carries the brand fill as glass),\nand the collapsed menu is Dropdown's dense-layer glass card\nunder the hamburger. Solid mode keeps the skin's own active tile.\n\nEither cluster takes a caller-supplied element beside its built-in parts:\n`brandContent` leads the left one with a logo mark (beside or instead of the\n`brand` wordmark) and `actions` leads the right one with free-form trailing\ncontrols (a search button, icon buttons), ahead of `actionLabel` and `avatar`.\n`links` is optional, so a console topbar with no middle nav renders neither the\nlinks row nor the menu button that stands in for it.","android":"Topbars with a brand, navigation links, and an action button. Used as the\nprimary app-level navigation.\n\nThe bar measures its own width: at and below the `sm` breakpoint (640) the links\nrow automatically collapses into a menu button opening a dropdown of the same\nlinks (the active one checkmarked), so links never clip off a phone screen;\n`active` and `onSelect` keep their contract in both renderings.\nThe menu button leads the bar, ahead of the logo and brand, where Material 3's top app bar puts its navigation icon.\nPass `scrolls` to keep every link at every width instead: the bar's content row\nthen pans sideways inside the bar, with no scroll indicator, and the links never\nfold into the menu. `onMenu` still replaces the links when both are passed.\n\nOn the web the bar is the v4 hand-off's: 56px tall with a 16px gutter, 32px\ncapsule links in the interface face, the active one (and a hovered one) on the\n`secondary` fill. `floating` lifts it as a pill on the stronger hairline with the\nmd shade.\nOn Android the bar keeps the platform's own top app bar shape.\n\nIn glass mode the active link paints a control-layer pane\n(Android carries its tinted tile),\nand the collapsed menu is Dropdown's dense-layer glass card\nunder the hamburger. Solid mode keeps the skin's own active tile.\n\nEither cluster takes a caller-supplied element beside its built-in parts:\n`brandContent` leads the left one with a logo mark (beside or instead of the\n`brand` wordmark) and `actions` leads the right one with free-form trailing\ncontrols (a search button, icon buttons), ahead of `actionLabel` and `avatar`.\n`links` is optional, so a console topbar with no middle nav renders neither the\nlinks row nor the menu button that stands in for it."}},{"slug":"pagination","name":"Pagination","category":"atoms","description":"Page-of-N navigation for tables and lists.","source":"src/atoms/pagination/pagination.md","url":"https://canvas.nannier.com/ai/4.2.0/components/pagination.md","humanUrl":"https://canvas.nannier.com/components/pagination","exports":["Pagination","PaginationProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"PaginationProps","props":[{"name":"page","type":"number | undefined","required":false,"description":"Current page, 1-based (CONTROLLED). Clamped into the 1..total range before rendering. Omit for uncontrolled use."},{"name":"defaultPage","type":"number | undefined","required":false,"description":"Initial page for uncontrolled use (a bare pagination navigates on press)."},{"name":"total","type":"number | undefined","required":false,"description":"Total number of pages."},{"name":"onChange","type":"((page: number) => void) | undefined","required":false,"description":"Fired with the next 1-based page when a control or number is pressed."},{"name":"itemCount","type":"number | undefined","required":false,"description":"Total number of items across all pages. When set, the compact and with-size indicator reads \"Showing X-Y of N\" (the item range on the current page) instead of \"Page X of N\", computed from the current page and the page size."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Collapse to Prev/Next plus a \"Page X of N\" label, no number buttons.","default":"false","group":0},{"name":"withSize","type":"boolean | undefined","required":false,"description":"Prepend a \"Rows per page\" size selector to the compact Prev/Next + \"Page X of N\" layout. Takes precedence over `compact`.","default":"false","group":0},{"name":"pageSize","type":"number | undefined","required":false,"description":"Currently selected rows-per-page value shown in the selector (CONTROLLED). Omit for uncontrolled use.","group":1},{"name":"defaultPageSize","type":"number | undefined","required":false,"description":"Initial rows-per-page value for uncontrolled use (the selector cycles on press).","group":1},{"name":"pageSizes","type":"number[] | undefined","required":false,"description":"Selectable rows-per-page values; pressing the selector advances through them.","group":1},{"name":"onPageSizeChange","type":"((size: number) => void) | undefined","required":false,"description":"Fired with the next rows-per-page value when the selector is pressed.","group":1},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium size).","default":"false","group":2},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium size).","default":"false","group":2},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium size).","default":"false","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":2}],"groups":[{"title":"Variant","pickOne":true,"note":"Variant (pick one; default is the full numbered row)."},{"title":"Content for the `withSize` selector","pickOne":false},{"title":"Size","pickOne":true,"note":"Size (pick one; default is the medium size)."}],"inherits":[]}],"platformNotes":{"web":"Page-of-N navigation for tables and lists.\n\nNeither iOS nor Android has a numbered pagination control, so every platform shows the\nsame pager:\nrounded hairline cells at 28, 34 or 40 (small, default, large), the page\nnumbers in 13px mono numerals, and the current page in the accent fill with a soft glow\nbeneath it. Previous and Next carry a chevron and a \"Prev\" / \"Next\" label beside the\nnumbers (the chevron alone at the small size and in the compact row), the truncation gap\nis a quiet text ellipsis (…), and the rows-per-page trigger sits on the field edge. A resting page\nor arrow takes the hover wash at once; a disabled pager dims as one, and in an enabled\npager the arrow at either end dims on its own.\n\nIn glass mode the current page is a brand-tinted control-layer puck behind its number;\nthe other pages and the hairline arrows paint no surface, so they stay bare. Beyond\nseven pages a page change also shifts the window (an ellipsis moves, a number appears or\ndrops out). Solid mode keeps the accent fill.","ios":"Page-of-N navigation for tables and lists.\n\niOS has no numbered pagination control, so every platform shows the same pager:\nrounded hairline cells at 28, 34 or 40 (small, default, large), the page\nnumbers in 13px mono numerals, and the current page in the accent fill with a soft glow\nbeneath it. Previous and Next carry a chevron and a \"Prev\" / \"Next\" label beside the\nnumbers (the chevron alone at the small size and in the compact row), the truncation gap\nis a quiet text ellipsis (…), and the rows-per-page trigger sits on the field edge. A resting page\nor arrow takes the hover wash at once; a disabled pager dims as one, and in an enabled\npager the arrow at either end dims on its own.\n\nIn glass mode the current page is a brand-tinted control-layer puck behind its number;\nthe other pages and the hairline arrows paint no surface, so they stay bare. Beyond\nseven pages a page change also shifts the window (an ellipsis moves, a number appears or\ndrops out). Solid mode keeps the accent fill.","android":"Page-of-N navigation for tables and lists.\n\nAndroid has no numbered pagination control, so every platform shows the same pager:\nrounded hairline cells at 28, 34 or 40 (small, default, large), the page\nnumbers in 13px mono numerals, and the current page in the accent fill with a soft glow\nbeneath it. Previous and Next carry a chevron and a \"Prev\" / \"Next\" label beside the\nnumbers (the chevron alone at the small size and in the compact row), the truncation gap\nis a quiet text ellipsis (…), and the rows-per-page trigger sits on the field edge. A resting page\nor arrow takes the hover wash at once; a disabled pager dims as one, and in an enabled\npager the arrow at either end dims on its own.\n\nIn glass mode the current page is a brand-tinted control-layer puck behind its number;\nthe other pages and the hairline arrows paint no surface, so they stay bare. Beyond\nseven pages a page change also shifts the window (an ellipsis moves, a number appears or\ndrops out). Solid mode keeps the accent fill."}},{"slug":"phone-input","name":"PhoneInput","category":"molecules","description":"A phone number field: the Input's box with a country segment at its start (the chosen country and a caret, which open a list of countries with their names and dial codes) and that country's dial code inline before the number. On the web the segment is a small chip inside the field naming the country by its ISO code, and the dial code and the number are set in the mono face, and in the country list each row is a 16px flag 10px from the name with the dial code a 12px mono note at its end; on iOS and Android it is the country's flag.","source":"src/molecules/phone-input/phone-input.md","url":"https://canvas.nannier.com/ai/4.2.0/components/phone-input.md","humanUrl":"https://canvas.nannier.com/components/phone-input","exports":["PHONE_COUNTRIES","PhoneCountry","PhoneEntryProps","PhoneInput","PhoneInputProps","flagOf"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"PhoneEntryProps","props":[{"name":"autoFocus","type":"boolean | undefined","required":false,"description":"If true, focuses the input on componentDidMount. The default value is false.","default":"false"},{"name":"defaultValue","type":"string | undefined","required":false,"description":"Provides an initial value that will change when the user starts typing. Useful for simple use-cases where you don't want to deal with listening to events and updating the value prop to keep the controlled state in sync."},{"name":"maxLength","type":"number | undefined","required":false,"description":"Limits the maximum number of characters that can be entered. Use this instead of implementing the logic in JS to avoid flicker."},{"name":"onBlur","type":"((e: BlurEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input is blurred Note: If you are trying to find the last value of TextInput, you can use the `onEndEditing` event, which is fired upon completion of editing."},{"name":"onFocus","type":"((e: FocusEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input is focused"},{"name":"onSubmitEditing","type":"((e: TextInputSubmitEditingEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input's submit button is pressed."},{"name":"onKeyPress","type":"((e: TextInputKeyPressEvent) => void) | undefined","required":false,"description":"Callback that is called when a key is pressed. This will be called with `{ nativeEvent: { key: keyValue } }` where keyValue is 'Enter' or 'Backspace' for respective keys and the typed-in character otherwise including ' ' for space. Fires before onChange callbacks. Note: on Android only the inputs from soft keyboard are handled, not the hardware keyboard inputs."},{"name":"returnKeyType","type":"ReturnKeyTypeOptions | undefined","required":false,"description":"enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call') Determines how the return key should look."},{"name":"testID","type":"string | undefined","required":false,"description":"Used to locate this view in end-to-end tests"}],"groups":[],"inherits":[]},{"name":"PhoneInputProps","props":[{"name":"value","type":"string | undefined","required":false,"description":"The national number typed so far (controlled). Omit and use `defaultValue` for uncontrolled use."},{"name":"onChangeText","type":"((text: string) => void) | undefined","required":false,"description":"Called with the new number on each keystroke."},{"name":"countries","type":"readonly PhoneCountry[] | undefined","required":false,"description":"The countries the segment offers, in the order shown. Defaults to the kit's curated `PHONE_COUNTRIES` list; pass a full, localized, or reordered list."},{"name":"country","type":"string | undefined","required":false,"description":"The selected country's ISO alpha-2 code (controlled). Omit and use `defaultCountry`."},{"name":"defaultCountry","type":"string | undefined","required":false,"description":"Initial country code for uncontrolled use. Defaults to \"US\" when the list has it, else the first row."},{"name":"onCountryChange","type":"((code: string) => void) | undefined","required":false,"description":"Called with the chosen country's code when a row is picked (both modes)."},{"name":"placeholder","type":"string | undefined","required":false,"description":"Placeholder shown while the number is empty."},{"name":"label","type":"string | undefined","required":false,"description":"The field's persistent label, rendered above the box on every platform (a grouped field never floats its label). It is the number field's programmatic name, and Field delegates its label into it."},{"name":"required","type":"boolean | undefined","required":false,"description":"Marks the field as required: a destructive \"*\" after the label (decorative, never in the accessible name), and the number field announced as required, through aria-required on the web and with the word in its name (\"Phone number, required\") on iOS and Android.","default":"false"},{"name":"error","type":"boolean | undefined","required":false,"description":"State (orthogonal). `error` (alias `invalid`) flags a validation problem.","default":"false","group":0},{"name":"invalid","type":"boolean | undefined","required":false,"description":"State (orthogonal). `error` (alias `invalid`) flags a validation problem.","default":"false","group":0},{"name":"disabled","type":"boolean | undefined","required":false,"description":"State (orthogonal). `error` (alias `invalid`) flags a validation problem.","default":"false","group":0},{"name":"readOnly","type":"boolean | undefined","required":false,"description":"Read-only: shows the number but blocks editing and the country list.","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium field).","default":"false","group":1},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium field).","default":"false","group":1},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the number field when there is no `label`.","group":1},{"name":"aria-describedby","type":"string | undefined","required":false,"description":"ID of the helper/error text that describes the field (its `nativeID`).","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1},{"name":"autoFocus","type":"boolean | undefined","required":false,"description":"If true, focuses the input on componentDidMount. The default value is false.","default":"false"},{"name":"defaultValue","type":"string | undefined","required":false,"description":"Provides an initial value that will change when the user starts typing. Useful for simple use-cases where you don't want to deal with listening to events and updating the value prop to keep the controlled state in sync."},{"name":"maxLength","type":"number | undefined","required":false,"description":"Limits the maximum number of characters that can be entered. Use this instead of implementing the logic in JS to avoid flicker."},{"name":"onBlur","type":"((e: BlurEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input is blurred Note: If you are trying to find the last value of TextInput, you can use the `onEndEditing` event, which is fired upon completion of editing."},{"name":"onFocus","type":"((e: FocusEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input is focused"},{"name":"onSubmitEditing","type":"((e: TextInputSubmitEditingEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input's submit button is pressed."},{"name":"onKeyPress","type":"((e: TextInputKeyPressEvent) => void) | undefined","required":false,"description":"Callback that is called when a key is pressed. This will be called with `{ nativeEvent: { key: keyValue } }` where keyValue is 'Enter' or 'Backspace' for respective keys and the typed-in character otherwise including ' ' for space. Fires before onChange callbacks. Note: on Android only the inputs from soft keyboard are handled, not the hardware keyboard inputs."},{"name":"returnKeyType","type":"ReturnKeyTypeOptions | undefined","required":false,"description":"enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call') Determines how the return key should look."},{"name":"testID","type":"string | undefined","required":false,"description":"Used to locate this view in end-to-end tests"},{"name":"ref","type":"React.Ref<RNTextInput>","required":false,"description":"Ref to the underlying React Native host. Supports object refs and callback refs; native methods follow the platform's behavior."},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":2}],"groups":[{"title":"State","pickOne":false,"note":"State (orthogonal). `error` (alias `invalid`) flags a validation problem."},{"title":"Size","pickOne":true,"note":"Size (pick one; default is the medium field)."},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"A phone number field: the Input's box with a country segment at its start (the\nchosen country and a caret, which open a list of countries with their names and\ndial codes) and that country's dial code inline before the number. On the web the\nsegment is a small chip inside the field naming the country by its ISO code, and\nthe dial code and the number are set in the mono face, and in the country list each\nrow is a 16px flag 10px from the name with the dial code a 12px mono note at its end;\non iOS and Android it is the\ncountry's flag.\n\nThe number and the country are each controlled (`value` / `country`) or\nself-managed (`defaultValue` / `defaultCountry`), the segment defaults to the\nkit's curated `PHONE_COUNTRIES` list (pass `countries` for a full or localized\none), and the number field asks for the phone keypad. Pass `label` (and\n`required`) to name it; `error` paints the whole box, segment included, and\nField delegates its label, required mark and error into it. The required star is\ndecorative: a screen reader hears the number field as required,\nfrom\n`aria-required` on the web and from its name (\"Phone number, required\") on iOS and\nAndroid.\nOn iOS the field is\ndrawn to the iOS input-field reference: the white box, the flag and gray caret\nsegment with its state-coloured divider, the dial code in the placeholder gray.\n\nIn glass mode the country list is a dense-layer glass card under the box; the\nbox, its segment and its number stay in place. A pick commits the country and\nreturns focus to the number at once, and a field that becomes disabled or\nread-only while the list is open closes it. Solid mode paints the skin's own list.","ios":"A phone number field: the Input's box with a country segment at its start (the\nchosen country and a caret, which open a list of countries with their names and\ndial codes) and that country's dial code inline before the number. On the web the\nsegment is a small chip inside the field naming the country by its ISO code, and\nthe dial code and the number are set in the mono face, and in the country list each\nrow is a 16px flag 10px from the name with the dial code a 12px mono note at its end;\nin the app it is the country's flag.\n\nThe number and the country are each controlled (`value` / `country`) or\nself-managed (`defaultValue` / `defaultCountry`), the segment defaults to the\nkit's curated `PHONE_COUNTRIES` list (pass `countries` for a full or localized\none), and the number field asks for the phone keypad. Pass `label` (and\n`required`) to name it; `error` paints the whole box, segment included, and\nField delegates its label, required mark and error into it. The required star is\ndecorative: a screen reader hears the number field as required,\nfrom its name (\"Phone number, required\").\nOn iOS the field is\ndrawn to the iOS input-field reference: the white box, the flag and gray caret\nsegment with its state-coloured divider, the dial code in the placeholder gray.\n\nIn glass mode the country list is a dense-layer glass card under the box; the\nbox, its segment and its number stay in place. A pick commits the country and\nreturns focus to the number at once, and a field that becomes disabled or\nread-only while the list is open closes it. Solid mode paints the skin's own list.","android":"A phone number field: the Input's box with a country segment at its start (the\nchosen country and a caret, which open a list of countries with their names and\ndial codes) and that country's dial code inline before the number. On the web the\nsegment is a small chip inside the field naming the country by its ISO code, and\nthe dial code and the number are set in the mono face, and in the country list each\nrow is a 16px flag 10px from the name with the dial code a 12px mono note at its end;\nin the app it is the country's flag.\n\nThe number and the country are each controlled (`value` / `country`) or\nself-managed (`defaultValue` / `defaultCountry`), the segment defaults to the\nkit's curated `PHONE_COUNTRIES` list (pass `countries` for a full or localized\none), and the number field asks for the phone keypad. Pass `label` (and\n`required`) to name it; `error` paints the whole box, segment included, and\nField delegates its label, required mark and error into it. The required star is\ndecorative: a screen reader hears the number field as required,\nfrom its name (\"Phone number, required\").\n\nIn glass mode the country list is a dense-layer glass card under the box; the\nbox, its segment and its number stay in place. A pick commits the country and\nreturns focus to the number at once, and a field that becomes disabled or\nread-only while the list is open closes it. Solid mode paints the skin's own list."}},{"slug":"pie-chart","name":"PieChart","category":"charts","description":"Proportional composition as arc slices in the `chart-1`..`chart-8` token colors, with a percent legend. `donut` centers the total (or the selected slice while inspecting); pressing a slice dims the others.","source":"src/charts/pie-chart/pie-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/pie-chart.md","humanUrl":"https://canvas.nannier.com/components/pie-chart","exports":["PieChart","PieChartProps","StackedSegment"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"PieChartProps","props":[{"name":"slices","type":"StackedSegment[]","required":true,"description":"The slices, in order; each takes its share of the circle."},{"name":"label","type":"string | undefined","required":false,"description":"What the pie measures (e.g. \"Traffic sources\"); leads the accessible name."},{"name":"donut","type":"boolean | undefined","required":false,"description":"Draw an annular ring with the total and label centered inside.","default":"false"},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Hide the legend (the labelled dots beside percentages).","default":"false"},{"name":"detailed","type":"boolean | undefined","required":false,"description":"Spread names and shares into a value column beside a compact composition disc.","default":"false"},{"name":"compact","type":"boolean | undefined","required":false,"description":"Smaller diameter.","default":"false"},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false"},{"name":"selected","type":"number | null | undefined","required":false,"description":"Press-to-inspect: the selected slice index (controlled). Pass null for none."},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Press-to-inspect: the initially selected slice (uncontrolled)."},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press selects a slice (or clears it with null)."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"For sizing/composition only."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"Proportional composition as arc slices in the `chart-1`..`chart-8` token colors, with a percent legend. `donut` centers the total (or the selected slice while inspecting); pressing a slice dims the others.","ios":"Proportional composition as arc slices in the `chart-1`..`chart-8` token colors, with a percent legend. `donut` centers the total (or the selected slice while inspecting); pressing a slice dims the others.","android":"Proportional composition as arc slices in the `chart-1`..`chart-8` token colors, with a percent legend. `donut` centers the total (or the selected slice while inspecting); pressing a slice dims the others."}},{"slug":"popover","name":"Popover","category":"atoms","description":"Floating panel with a title, supporting text, rich content such as form fields, and a single follow-up action, anchored to its trigger. Pass children to host custom content in the panel body, between the description and the action.","source":"src/atoms/popover/popover.md","url":"https://canvas.nannier.com/ai/4.2.0/components/popover.md","humanUrl":"https://canvas.nannier.com/components/popover","exports":["Popover","PopoverProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"PopoverProps","props":[{"name":"anchorRef","type":"RefObject<View | null> | undefined","required":false,"description":"An existing trigger to anchor against; omits the built-in trigger and wrapper."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Explicit name for a panel with custom content."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Compact web application panel with an outside hairline and scrolling content.","default":"false"},{"name":"comfortable","type":"boolean | undefined","required":false,"description":"Roomier compact-panel content inset.","default":"false"},{"name":"anchored","type":"boolean | undefined","required":false,"description":"Keep the card anchored on narrow windows instead of adapting to a sheet.","default":"false"},{"name":"alignEnd","type":"boolean | undefined","required":false,"description":"Align the trailing edge of the card to its trigger.","default":"false"},{"name":"panelWidth","type":"number | undefined","required":false,"description":"Floating card width, clamped inside the overlay outlet."},{"name":"maxHeight","type":"number | undefined","required":false,"description":"Maximum height of the floating card; its compact contents scroll within it."},{"name":"trigger","type":"string | undefined","required":false,"description":"Label for the trigger button."},{"name":"title","type":"string | undefined","required":false,"description":"Heading shown at the top of the floating card."},{"name":"description","type":"string | undefined","required":false,"description":"Supporting line beneath the title."},{"name":"children","type":"ReactNode","required":false,"description":"Custom panel content (an input, a form row, any node), rendered in the card body between the description and the action row. Composes with the data-driven props."},{"name":"actionLabel","type":"string | undefined","required":false,"description":"When set, renders a primary action button at the bottom of the card."},{"name":"top","type":"boolean | undefined","required":false,"description":"Anchor the card ABOVE the trigger (it flips below when the room above is short). Placement axis: `top` > `bottom`.","default":"false"},{"name":"bottom","type":"boolean | undefined","required":false,"description":"Anchor the card BELOW the trigger, the default (it flips above when the room below is short).","default":"false"},{"name":"inline","type":"boolean | undefined","required":false,"description":"Static mode: render the card on its own with no trigger button (an always-visible inline panel). When set, the card is always shown and `open` is ignored. With `top` or `bottom` it points its beak at what it belongs to (below it with `top`, above it with `bottom`), from the end edge with `alignEnd`.","default":"false"},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Omit for uncontrolled (the trigger toggles it).","default":"false"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"Floating panel with a title, supporting text, rich content such as form fields, and a single follow-up action, anchored to its trigger. Pass children to host custom content in the panel body, between the description and the action.\n\nOn the web and Android the panel is the v4 card:\n280 wide at the menu corner, the field\nhairline and the large shadow, a 15px display heading over its 14px description in the\nmuted ink, and in solid mode a small diamond beak on the edge facing its trigger.\niOS\nkeeps the iPad popover, a rounder borderless card with a tapered beak toward its\ntrigger.\n\nThe triggered card opens below its button by default and above it with `top`; either\nway it flips to the other side when its own lacks room, and the beak follows the\nside it took. At phone width a triggered card that can close is presented as a sheet\non the bottom edge of the window, over the tab bar and a dimming scrim that glass on the\nweb also blurs,\nits content kept clear of the home indicator: Dark Factory's sheet on the web, the iOS sheet on iPhone and\nthe Material 3 bottom sheet on Android.\n\nIn glass mode the triggered card is a functional-layer glass panel beside its\nbutton, and the sheet a dense-layer one, legible over its scrim; focus enters once the\ncard's placement has committed, and the `inline` card is a static in-flow panel. Solid\nmode paints the skin's own panel.\n\nAn existing control can own the trigger: pass its `anchorRef` and drive `open`\nwith `onOpenChange`. The popover then adds no trigger or layout wrapper. Name\ncustom content with `accessibilityLabel`. `compact` uses the original Argus panel\ninset and outside hairline on web, with scrolling contents; `comfortable` gives\nits filter panel more room. `panelWidth` and `maxHeight` bound the overlay.\n`anchored` keeps a floating card at narrow widths, and `alignEnd` follows the\ntrigger’s trailing edge.","ios":"Floating panel with a title, supporting text, rich content such as form fields, and a single follow-up action, anchored to its trigger. Pass children to host custom content in the panel body, between the description and the action.\n\niOS\nkeeps the iPad popover, a rounder borderless card with a tapered beak toward its\ntrigger.\n\nThe triggered card opens below its button by default and above it with `top`; either\nway it flips to the other side when its own lacks room, and the beak follows the\nside it took. At phone width a triggered card that can close is presented as a sheet\non the bottom edge of the window, over the tab bar and a dimming scrim that glass on the\nweb also blurs,\nits content kept clear of the home indicator: the iOS sheet on iPhone.\n\nIn glass mode the triggered card is a functional-layer glass panel beside its\nbutton, and the sheet a dense-layer one, legible over its scrim; focus enters once the\ncard's placement has committed, and the `inline` card is a static in-flow panel. Solid\nmode paints the skin's own panel.\n\nAn existing control can own the trigger: pass its `anchorRef` and drive `open`\nwith `onOpenChange`. The popover then adds no trigger or layout wrapper. Name\ncustom content with `accessibilityLabel`. `compact` uses the original Argus panel\ninset and outside hairline on web, with scrolling contents; `comfortable` gives\nits filter panel more room. `panelWidth` and `maxHeight` bound the overlay.\n`anchored` keeps a floating card at narrow widths, and `alignEnd` follows the\ntrigger’s trailing edge.","android":"Floating panel with a title, supporting text, rich content such as form fields, and a single follow-up action, anchored to its trigger. Pass children to host custom content in the panel body, between the description and the action.\n\nOn Android the panel is the v4 card:\n280 wide at the menu corner, the field\nhairline and the large shadow, a 15px display heading over its 14px description in the\nmuted ink, and in solid mode a small diamond beak on the edge facing its trigger.\n\nThe triggered card opens below its button by default and above it with `top`; either\nway it flips to the other side when its own lacks room, and the beak follows the\nside it took. At phone width a triggered card that can close is presented as a sheet\non the bottom edge of the window, over the tab bar and a dimming scrim that glass on the\nweb also blurs,\nits content kept clear of the home indicator: the Material 3 bottom sheet.\n\nIn glass mode the triggered card is a functional-layer glass panel beside its\nbutton, and the sheet a dense-layer one, legible over its scrim; focus enters once the\ncard's placement has committed, and the `inline` card is a static in-flow panel. Solid\nmode paints the skin's own panel.\n\nAn existing control can own the trigger: pass its `anchorRef` and drive `open`\nwith `onOpenChange`. The popover then adds no trigger or layout wrapper. Name\ncustom content with `accessibilityLabel`. `compact` uses the original Argus panel\ninset and outside hairline on web, with scrolling contents; `comfortable` gives\nits filter panel more room. `panelWidth` and `maxHeight` bound the overlay.\n`anchored` keeps a floating card at narrow widths, and `alignEnd` follows the\ntrigger’s trailing edge."}},{"slug":"pressable","name":"Pressable","category":"atoms","description":"The touchable primitive: wraps content, fires `onPress`, and exposes the press state to its style for feedback.","source":"src/atoms/pressable/pressable.md","url":"https://canvas.nannier.com/ai/4.2.0/components/pressable.md","humanUrl":"https://canvas.nannier.com/components/pressable","exports":["InteractionOverride","InteractionOverrideProps","Pressable"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"InteractionOverrideProps","groups":[],"inherits":[],"props":[{"name":"hovered","type":"boolean | undefined","required":false,"description":"Every kit control in the subtree renders as if a pointer hovered it."},{"name":"focused","type":"boolean | undefined","required":false,"description":"Every kit control in the subtree renders its keyboard focus (the focus ring, or the field's own focused look)."},{"name":"pressed","type":"boolean | undefined","required":false,"description":"Every kit control in the subtree renders as if it were held down."},{"name":"children","type":"ReactNode","required":false,"description":"The subtree that resolves the pinned states."}]}],"platformNotes":{"web":"The touchable primitive: wraps content, fires `onPress`, and exposes the press state to its style for feedback.\n\nThe kit's interactive components (Button, plus the tappable Card, Stats, GridList, MediaObject, and StackedList rows) cover the common cases and keep branding consistent, so prefer them; Pressable stays for full flexibility when you need a custom interaction the kit doesn't provide. Its style prop accepts a function of the press state, `({ pressed }) => style`, so you can show press feedback with no extra wrapper; style it with tokens to stay on-brand.\n\nPass `focusable={false}` for a surface only a pointer should reach, such as a row whose keyboard path is a button inside it: it still presses, and it leaves the tab order on the web too, where react-native-web's own Pressable would keep it a tab stop. A Pressable with the `link` role presses on Enter (and not on Space), as a link does, on the web too: react-native-web's own Pressable leaves that key to the browser, which activates only a link that has an `href`.","ios":"The touchable primitive: wraps content, fires `onPress`, and exposes the press state to its style for feedback.\n\nThe kit's interactive components (Button, plus the tappable Card, Stats, GridList, MediaObject, and StackedList rows) cover the common cases and keep branding consistent, so prefer them; Pressable stays for full flexibility when you need a custom interaction the kit doesn't provide. Its style prop accepts a function of the press state, `({ pressed }) => style`, so you can show press feedback with no extra wrapper; style it with tokens to stay on-brand.\n\nPass `focusable={false}` for a surface only a pointer should reach, such as a row whose keyboard path is a button inside it: it still presses, and it leaves the tab order on the web too, where react-native-web's own Pressable would keep it a tab stop. A Pressable with the `link` role presses on Enter (and not on Space), as a link does, on the web too: react-native-web's own Pressable leaves that key to the browser, which activates only a link that has an `href`.","android":"The touchable primitive: wraps content, fires `onPress`, and exposes the press state to its style for feedback.\n\nThe kit's interactive components (Button, plus the tappable Card, Stats, GridList, MediaObject, and StackedList rows) cover the common cases and keep branding consistent, so prefer them; Pressable stays for full flexibility when you need a custom interaction the kit doesn't provide. Its style prop accepts a function of the press state, `({ pressed }) => style`, so you can show press feedback with no extra wrapper; style it with tokens to stay on-brand.\n\nPass `focusable={false}` for a surface only a pointer should reach, such as a row whose keyboard path is a button inside it: it still presses, and it leaves the tab order on the web too, where react-native-web's own Pressable would keep it a tab stop. A Pressable with the `link` role presses on Enter (and not on Space), as a link does, on the web too: react-native-web's own Pressable leaves that key to the browser, which activates only a link that has an `href`."}},{"slug":"progress","name":"Progress","category":"atoms","description":"Determinate and indeterminate progress bars: a rounded bar that reports how far a task has gotten, or that work is underway.","source":"src/atoms/progress/progress.md","url":"https://canvas.nannier.com/ai/4.2.0/components/progress.md","humanUrl":"https://canvas.nannier.com/components/progress","exports":["Progress","ProgressProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ProgressProps","props":[{"name":"value","type":"number | undefined","required":false,"description":"Completion as a 0..1 fraction (clamped). Ignored when `indeterminate`. Defaults to 0."},{"name":"segments","type":"number | undefined","required":false,"description":"A fixed number of discrete dashes, filled by the same fractional value."},{"name":"indeterminate","type":"boolean | undefined","required":false,"description":"Indeterminate mode: ignore `value` and animate a sliding bar (a spinner on iOS).","default":"false"},{"name":"children","type":"ReactNode","required":false,"description":"Optional title line rendered ABOVE the bar. Supplying it (with or without a `description`/`showValue`) builds the stacked header inside the control, so the caller never hand-composes a Row/Column + Typography around the bar. This is the \"components own their label anatomy\" contract, mirroring Checkbox/Radio/Switch's `description` slot."},{"name":"description","type":"ReactNode","required":false,"description":"Optional muted secondary line rendered under the title."},{"name":"showValue","type":"boolean | undefined","required":false,"description":"Render the percent (derived from `value`) as a right-aligned readout on the title line. Indeterminate has no measurable value, so this renders nothing then.","default":"false"},{"name":"status","type":"ReactNode","required":false,"description":"A short status word on the title line, in the percent readout's place and type (\"indeterminate\", \"strong\", \"paused\"): what the bar means right now, where `description` is a sentence under the title. It shows while indeterminate too, and when both are passed the status wins the readout slot over `showValue`."},{"name":"warning","type":"boolean | undefined","required":false,"description":"Tone axis (the active fill color; pick one, default is the call-to-action fill). `warning` paints the bar in the warning color, `danger` in the destructive color, for a metric over a soft threshold or a hard limit (a WIP meter over its cap); the track stays neutral. Pair with copy: the tone adds no accessible value.","default":"false","group":0},{"name":"danger","type":"boolean | undefined","required":false,"description":"Tone axis (the active fill color; pick one, default is the call-to-action fill). `warning` paints the bar in the warning color, `danger` in the destructive color, for a metric over a soft threshold or a hard limit (a WIP meter over its cap); the track stays neutral. Pair with copy: the tone adds no accessible value.","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"Size axis (track thickness; pick one, default is the medium track).","default":"false","group":1},{"name":"large","type":"boolean | undefined","required":false,"description":"Size axis (track thickness; pick one, default is the medium track).","default":"false","group":1},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible description of what is progressing.","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":2}],"groups":[{"title":"Tone axis","pickOne":true,"note":"Tone axis (the active fill color; pick one, default is the call-to-action fill). `warning` paints the bar in the warning color, `danger` in the destructive color, for a metric over a soft threshold or a hard limit (a WIP meter over its cap); the track stays neutral. Pair with copy: the tone adds no accessible value."},{"title":"Size axis","pickOne":true,"note":"Size axis (track thickness; pick one, default is the medium track)."},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"Determinate and indeterminate progress bars: a rounded bar that reports how far a task has gotten, or that work is underway.\n\nThe bar fills the parent it is given; a step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container step sets its measure.\n\nName the task with string `children`, or pass `accessibilityLabel` when the visible title is omitted or contains rich content.\n\n`segments` displays a fixed number of discrete 13×5 dashes with three pixels\nbetween them. It uses the same 0–1 `value`, intent fill and accessible percentage.\nIndeterminate wins over discrete segments; a labelled segmented meter retains its header.","ios":"Determinate and indeterminate progress bars: a rounded bar that reports how far a task has gotten, or that work is underway.\n\nThe bar fills the parent it is given; a step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container step sets its measure.\n\nName the task with string `children`, or pass `accessibilityLabel` when the visible title is omitted or contains rich content.\n\n`segments` displays a fixed number of discrete 13×5 dashes with three pixels\nbetween them. It uses the same 0–1 `value`, intent fill and accessible percentage.\nIndeterminate wins over discrete segments; a labelled segmented meter retains its header.","android":"Determinate and indeterminate progress bars: a rounded bar that reports how far a task has gotten, or that work is underway.\n\nThe bar fills the parent it is given; a step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container step sets its measure.\n\nName the task with string `children`, or pass `accessibilityLabel` when the visible title is omitted or contains rich content.\n\n`segments` displays a fixed number of discrete 13×5 dashes with three pixels\nbetween them. It uses the same 0–1 `value`, intent fill and accessible percentage.\nIndeterminate wins over discrete segments; a labelled segmented meter retains its header."}},{"slug":"progress-ring","name":"ProgressRing","category":"charts","description":"A full-circle completion ring, the Gauge's sibling: a muted track ring, a tone-colored value arc revealed clockwise from 12 o'clock with rounded caps, the whole-percent readout centered inside, and an optional label below the graphic. The same 0-100 value contract, tone axis, and rounding rules as Gauge, in the circular anatomy that reads as \"completion\" rather than \"level\".","source":"src/charts/progress-ring/progress-ring.md","url":"https://canvas.nannier.com/ai/4.2.0/components/progress-ring.md","humanUrl":"https://canvas.nannier.com/components/progress-ring","exports":["ProgressRing","ProgressRingProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ProgressRingProps","props":[{"name":"value","type":"number","required":true,"description":"The value to display, 0-100."},{"name":"label","type":"string | undefined","required":false,"description":"A short caption beneath the number (e.g. \"Complete\")."},{"name":"primary","type":"boolean | undefined","required":false,"description":"Tone of the value arc (pick one; default primary). Precedence when several are passed: success > warning > destructive (first match wins).","default":"false","group":0},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone of the value arc (pick one; default primary). Precedence when several are passed: success > warning > destructive (first match wins).","default":"false","group":0},{"name":"warning","type":"boolean | undefined","required":false,"description":"Tone of the value arc (pick one; default primary). Precedence when several are passed: success > warning > destructive (first match wins).","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone of the value arc (pick one; default primary). Precedence when several are passed: success > warning > destructive (first match wins).","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default 168 ring; compact is 106).","default":"false","group":1},{"name":"stacked","type":"boolean | undefined","required":false,"description":"Set the label under the ring, centred, instead of beside it (a row of rings, each named underneath).","default":"false","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"For sizing/composition only.","group":1}],"groups":[{"title":"Tone of the value arc","pickOne":true,"note":"Tone of the value arc (pick one; default primary). Precedence when several are passed: success > warning > destructive (first match wins)."},{"title":"Density","pickOne":false,"note":"Density (omit for the default 168 ring; compact is 106)."}],"inherits":[]}],"platformNotes":{"web":"A full-circle completion ring, the Gauge's sibling: a muted track ring, a tone-colored value arc revealed clockwise from 12 o'clock with rounded caps, the whole-percent readout centered inside, and an optional label below the graphic. The same 0-100 value contract, tone axis, and rounding rules as Gauge, in the circular anatomy that reads as \"completion\" rather than \"level\".","ios":"A full-circle completion ring, the Gauge's sibling: a muted track ring, a tone-colored value arc revealed clockwise from 12 o'clock with rounded caps, the whole-percent readout centered inside, and an optional label below the graphic. The same 0-100 value contract, tone axis, and rounding rules as Gauge, in the circular anatomy that reads as \"completion\" rather than \"level\".","android":"A full-circle completion ring, the Gauge's sibling: a muted track ring, a tone-colored value arc revealed clockwise from 12 o'clock with rounded caps, the whole-percent readout centered inside, and an optional label below the graphic. The same 0-100 value contract, tone axis, and rounding rules as Gauge, in the circular anatomy that reads as \"completion\" rather than \"level\"."}},{"slug":"qrcode","name":"QRCode","category":"atoms","description":"Encodes a string as a scannable QR code. Built on react-native-svg, so it renders the same on iOS, Android, and the web. The code stays a fixed dark-on-white card so any camera can read it, whatever the app theme.","source":"src/atoms/qrcode/qrcode.md","url":"https://canvas.nannier.com/ai/4.2.0/components/qrcode.md","humanUrl":"https://canvas.nannier.com/components/qrcode","exports":["QRCode","QRCodeProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-qrcode-svg","range":">=6","optional":true},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"QRCodeProps","props":[{"name":"value","type":"string","required":true,"description":"The string to encode: a URL, plain text, a token, etc."},{"name":"small","type":"boolean | undefined","required":false,"description":"A compact 96px code.","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"A large 200px code.","default":"false","group":0},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Spoken equivalent for screen readers. A QR code is camera-only content, so without a label assistive tech announces nothing. Defaults to `QR code encoding ${value}`; pass a generic label (e.g. \"QR code\") when surfacing the raw value is undesirable.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Size axis","pickOne":true,"note":"Size axis (pick one; default is the medium 140px code)."}],"inherits":[]}],"platformNotes":{"web":"Encodes a string as a scannable QR code. Built on react-native-svg,\nso it renders the same on iOS, Android, and the web.\nThe code stays a fixed dark-on-white card so any camera can read it, whatever the app theme.","ios":"Encodes a string as a scannable QR code. Built on react-native-svg,\nso it renders the same on every platform Canvas supports.\nThe code stays a fixed dark-on-white card so any camera can read it, whatever the app theme.","android":"Encodes a string as a scannable QR code. Built on react-native-svg,\nso it renders the same on every platform Canvas supports.\nThe code stays a fixed dark-on-white card so any camera can read it, whatever the app theme."}},{"slug":"radar-chart","name":"RadarChart","category":"charts","description":"A polygonal multi-axis comparison: concentric rings at nice tick fractions, a spoke per axis, and one closed polygon per series (ramp stroke over a soft matching wash), with the spoke labels just beyond the outer ring. Values align to `axes` by index and the accessible name folds every axis and value; press-to-inspect is deferred scope for this chart.","source":"src/charts/radar-chart/radar-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/radar-chart.md","humanUrl":"https://canvas.nannier.com/components/radar-chart","exports":["RadarChart","RadarChartProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"RadarChartProps","props":[{"name":"axes","type":"string[]","required":true,"description":"Spoke labels, clockwise from 12 o'clock."},{"name":"series","type":"ChartSeries[]","required":true,"description":"One polygon per series; values aligned to `axes` by index."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"max","type":"number | undefined","required":false,"description":"Outer-ring maximum. Defaults to a nice bound above the data max."},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (single-series only; pick one; default primary). Precedence: success > destructive.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (single-series only; pick one; default primary). Precedence: success > destructive.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":1},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":1},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Hide the series legend (multi-series charts show one by default).","default":"false","group":1},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"Hide the rings and spokes (the labels always render).","default":"false","group":1},{"name":"spokes","type":"boolean | undefined","required":false,"description":"Join each outer vertex to the center with a radial guide.","default":"false","group":1},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats accessible values (data formatting, not styling).","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (single-series only; pick one; default primary). Precedence: success > destructive."},{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."}],"inherits":[]}],"platformNotes":{"web":"A polygonal multi-axis comparison: concentric rings at nice tick fractions, a spoke per axis, and one closed polygon per series (ramp stroke over a soft matching wash), with the spoke labels just beyond the outer ring. Values align to `axes` by index and the accessible name folds every axis and value; press-to-inspect is deferred scope for this chart.","ios":"A polygonal multi-axis comparison: concentric rings at nice tick fractions, a spoke per axis, and one closed polygon per series (ramp stroke over a soft matching wash), with the spoke labels just beyond the outer ring. Values align to `axes` by index and the accessible name folds every axis and value; press-to-inspect is deferred scope for this chart.","android":"A polygonal multi-axis comparison: concentric rings at nice tick fractions, a spoke per axis, and one closed polygon per series (ramp stroke over a soft matching wash), with the spoke labels just beyond the outer ring. Values align to `axes` by index and the accessible name folds every axis and value; press-to-inspect is deferred scope for this chart."}},{"slug":"radial-bar-chart","name":"RadialBarChart","category":"charts","description":"Concentric arc rings, one per category, outermost first: each pairs a muted full-circle track with a ramp-colored value arc revealed clockwise from 12 o'clock, and a column legend carries the formatted values. Every ring sweeps against the same `max` (the largest entry by default), so the chart compares attainment, not shares. Press a ring to select it (the others dim); press elsewhere to clear.","source":"src/charts/radial-bar-chart/radial-bar-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/radial-bar-chart.md","humanUrl":"https://canvas.nannier.com/components/radial-bar-chart","exports":["RadialBarChart","RadialBarChartProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"RadialBarChartProps","props":[{"name":"data","type":"StackedSegment[]","required":true,"description":"One ring per entry, outer to inner."},{"name":"label","type":"string | undefined","required":false,"description":"What the rings measure (e.g. \"Platform activation\"); leads the accessible name."},{"name":"max","type":"number | undefined","required":false,"description":"The value of a full sweep. Defaults to the largest entry."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default 160 disc; compact is 120).","default":"false","group":0},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":0},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Hide the value legend (the accessible name still carries every value).","default":"false","group":0},{"name":"detailed","type":"boolean | undefined","required":false,"description":"A compact disc with a separate value column and shared maximum caption.","default":"false","group":0},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats legend values (data formatting, not styling).","group":0},{"name":"selected","type":"number | null | undefined","required":false,"description":"Press-to-inspect: the selected ring index (controlled). Pass null for none.","group":0},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Press-to-inspect: the initially selected ring (uncontrolled).","group":0},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press selects a ring (or clears it with null).","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"For sizing/composition only.","group":0}],"groups":[{"title":"Density","pickOne":false,"note":"Density (omit for the default 160 disc; compact is 120)."}],"inherits":[]}],"platformNotes":{"web":"Concentric arc rings, one per category, outermost first: each pairs a muted full-circle track with a ramp-colored value arc revealed clockwise from 12 o'clock, and a column legend carries the formatted values. Every ring sweeps against the same `max` (the largest entry by default), so the chart compares attainment, not shares. Press a ring to select it (the others dim); press elsewhere to clear.","ios":"Concentric arc rings, one per category, outermost first: each pairs a muted full-circle track with a ramp-colored value arc revealed clockwise from 12 o'clock, and a column legend carries the formatted values. Every ring sweeps against the same `max` (the largest entry by default), so the chart compares attainment, not shares. Press a ring to select it (the others dim); press elsewhere to clear.","android":"Concentric arc rings, one per category, outermost first: each pairs a muted full-circle track with a ramp-colored value arc revealed clockwise from 12 o'clock, and a column legend carries the formatted values. Every ring sweeps against the same `max` (the largest entry by default), so the chart compares attainment, not shares. Press a ring to select it (the others dim); press elsewhere to clear."}},{"slug":"radio","name":"Radio","category":"atoms","description":"Single-pick selection: stacked, inline, card-style.","source":"src/atoms/radio/radio.md","url":"https://canvas.nannier.com/ai/4.2.0/components/radio.md","humanUrl":"https://canvas.nannier.com/components/radio","exports":["Radio","RadioGroup","RadioGroupProps","RadioProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"RadioGroupProps","props":[{"name":"value","type":"string | number | undefined","required":false,"description":"The selected option's value (CONTROLLED). Omit for uncontrolled use."},{"name":"defaultValue","type":"string | number | undefined","required":false,"description":"Initial selected value for uncontrolled use (a bare group selects on press)."},{"name":"onChange","type":"((value: string | number) => void) | undefined","required":false,"description":"Fired with the newly selected option's value."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Disable every radio in the group.","default":"false"},{"name":"row","type":"boolean | undefined","required":false,"description":"Lay the options out in a wrapping row instead of the default column. iOS keeps its checkmark list vertical (a list has no row form); `card` options still sit in a row there.","default":"false"},{"name":"equal","type":"boolean | undefined","required":false,"description":"With `row`: the options share the row equally and never wrap, a tile picker's even columns (card tiles 10 apart, plain options 20).","default":"false"},{"name":"inlineLabel","type":"boolean | undefined","required":false,"description":"With `row` and a `label`: the label sits at the start of the row, before the options and centred on them, in the 500 13 px muted ink (a short setting's inline choice: \"Digest ( ) Daily (o) Weekly\"), instead of as a heading above. The `description` is not shown inline.","default":"false"},{"name":"label","type":"string | undefined","required":false,"description":"The group's name, rendered as a heading above the options. It also becomes the radiogroup's accessible name, so a screen reader announces what the set of options is about before reading them. The group owns this label anatomy; never hand-compose a heading Text beside a bare group."},{"name":"description","type":"ReactNode","required":false,"description":"Optional muted supporting line rendered under the label."},{"name":"children","type":"ReactNode","required":false,"description":"The `<Radio value=\"…\">` options that make up the group."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the group container."},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook."}],"groups":[],"inherits":[]},{"name":"RadioProps","props":[{"name":"value","type":"string | number | undefined","required":false,"description":"This option's value within a RadioGroup. When the radio sits inside a `<RadioGroup>`, its checked state and selection are driven by the group matching this value; ignored for a standalone radio."},{"name":"checked","type":"boolean | undefined","required":false,"description":"Whether this control is the selected option (controlled; standalone use).","default":"false"},{"name":"selected","type":"boolean | undefined","required":false,"description":"Alias for `checked`, for callers that think in terms of \"selected\".","default":"false"},{"name":"onChange","type":"((checked: boolean, event: GestureResponderEvent) => void) | undefined","required":false,"description":"Fired on press with the next checked value (always true for a radio). Web keyboard activation supports Space on release and Enter; RadioGroup also handles arrows."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the pressable row."},{"name":"children","type":"ReactNode","required":false,"description":"Label text (the option's title) shown beside the control."},{"name":"description","type":"ReactNode","required":false,"description":"Optional muted secondary line rendered under the label, for the common title-plus-description option (a plan picker, a settings choice). Supplying it builds the stacked title/description layout inside the control, so the caller never hand-composes a Row + Column + two Typography nodes per option."},{"name":"card","type":"boolean | undefined","required":false,"description":"Render the whole control as a selectable option CARD: the mark (the ring, or the trailing check on iOS) plus the title and description sit inside Card chrome (bordered, padded), and the ENTIRE card is the tap target. When this radio is the chosen option, the card takes Card's own `selected` treatment (a primary border and a soft primary tint), so the whole tile reads as chosen, not just the mark. Pairs with `description` for a plan/tier picker, and is still group-wired through `value` inside a `<RadioGroup>`.","default":"false"},{"name":"meta","type":"ReactNode","required":false,"description":"A trailing detail on the title's line (a version, a price, a status pill): a string is set in the small mono meta type in the subtle ink, a node (a `Badge`) as it is. The title takes the row, so in a full-width option the detail sits at its end; in a `row` group's hugging option it follows the title."},{"name":"icon","type":"ReactNode","required":false,"description":"A `card` tile's icon (a kit `Icon` with no tone of its own): the tile stacks the icon and the mark on one line above the title and description. The icon takes the accent text ink while the option is chosen and the subtle ink otherwise. Ignored without `card`."},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the 18px control on the web).","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the 18px control on the web).","default":"false","group":0},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Dim the control and block presses.","default":"false","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0},{"name":"ref","type":"React.Ref<View>","required":false,"description":"Ref to the interactive radio row, preserving group navigation. Typed as a React Native View. On web, React Native Web exposes its DOM host; focus() and blur() move browser focus. Native host behavior depends on the platform and React Native version. Calling focus() does not activate the control or call accessibility focus APIs."}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default is the 18px control on the web)."}],"inherits":[]}],"platformNotes":{"web":"Single-pick selection: stacked, inline, card-style.\n\nOne job, a platform's own control: iOS has no radio button, so there a single choice is a checkmark list, the inline picker of a grouped form. Each option's label leads and the chosen option carries a trailing check, and a RadioGroup's options form one inset-grouped section with a hairline between two rows. The web and Android keep the ring, and the role is `radio` on every platform: on the web an 18 px ring (16 `small`, 22 `large`) whose edge thickens in the accent around a hollow center when chosen, on Android Material 3's 20dp ring around an accent dot.\nIn glass mode the ring keeps its solid look on every platform: a ring is a small mark inside content, not a surface, so it draws with no pane and no rim. A `card` option is a content-layer pane, as a selectable Card is.\nOn iOS the list stays vertical when the group asks for a `row` (a list has no row form), and `card` options stay tiles that mark the choice with the same trailing check.\n\nPass `ref` to access the interactive radio row, preserving group navigation. Use `useRef<ComponentRef<typeof Radio>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn the web, Space activates the focused control on key release, and Enter also activates it. Holding Space does not repeat the change. Moving focus away, disabling the control, or composing text cancels a pending Space press. RadioGroup arrow keys continue to move focus and selection.","ios":"Single-pick selection: stacked, inline, card-style.\n\nOne job, a platform's own control: iOS has no radio button, so there a single choice is a checkmark list, the inline picker of a grouped form. Each option's label leads and the chosen option carries a trailing check, and a RadioGroup's options form one inset-grouped section with a hairline between two rows. The role is `radio` on every platform.\nIn glass mode the ring keeps its solid look on every platform: a ring is a small mark inside content, not a surface, so it draws with no pane and no rim. A `card` option is a content-layer pane, as a selectable Card is.\nOn iOS the list stays vertical when the group asks for a `row` (a list has no row form), and `card` options stay tiles that mark the choice with the same trailing check.\n\nPass `ref` to access the interactive radio row, preserving group navigation. Use `useRef<ComponentRef<typeof Radio>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn the web, Space activates the focused control on key release, and Enter also activates it. Holding Space does not repeat the change. Moving focus away, disabling the control, or composing text cancels a pending Space press. RadioGroup arrow keys continue to move focus and selection.","android":"Single-pick selection: stacked, inline, card-style.\n\nOne job, a platform's own control: Android keeps the ring, Material 3's 20dp ring around an accent dot, and the role is `radio` on every platform.\nIn glass mode the ring keeps its solid look on every platform: a ring is a small mark inside content, not a surface, so it draws with no pane and no rim. A `card` option is a content-layer pane, as a selectable Card is.\n\nPass `ref` to access the interactive radio row, preserving group navigation. Use `useRef<ComponentRef<typeof Radio>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn the web, Space activates the focused control on key release, and Enter also activates it. Holding Space does not repeat the change. Moving focus away, disabling the control, or composing text cancels a pending Space press. RadioGroup arrow keys continue to move focus and selection."}},{"slug":"range-area-chart","name":"RangeAreaChart","category":"charts","description":"A min/max envelope: a translucent band between each label's `low` and `high`, an optional solid `mid` line through it, and the standard scrub-to-inspect flag showing High, Mid, and Low. The y domain hugs the data rather than anchoring at zero, since an envelope is a range idiom, not a magnitude bar. Forecast bands, error envelopes, and daily temperature ranges all read this way.","source":"src/charts/range-area-chart/range-area-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/range-area-chart.md","humanUrl":"https://canvas.nannier.com/components/range-area-chart","exports":["RangeAreaChart","RangeAreaChartProps","RangePoint"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"RangeAreaChartProps","props":[{"name":"labels","type":"string[]","required":true,"description":"Category labels along the x axis, one per data column."},{"name":"data","type":"RangePoint[]","required":true,"description":"One range per label, aligned by index."},{"name":"label","type":"string | undefined","required":false,"description":"Names the envelope (e.g. \"Forecast\"); leads the accessible name and the flag."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (pick one; default primary). Precedence: success > destructive.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (pick one; default primary). Precedence: success > destructive.","default":"false","group":0},{"name":"curved","type":"boolean | undefined","required":false,"description":"Curve (omit for straight segments).","default":"false","group":1},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":2},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":2},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"hideAxes","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":3},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats tick labels and accessible values (data formatting, not styling).","group":3},{"name":"selected","type":"number | null | undefined","required":false,"description":"Scrub-to-inspect: the selected category index (controlled). Pass null for none.","group":3},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Scrub-to-inspect: the initially selected category (uncontrolled).","group":3},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press/scrub selects a category (or clears it with null).","group":3},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":3},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":3}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (pick one; default primary). Precedence: success > destructive."},{"title":"Curve","pickOne":false,"note":"Curve (omit for straight segments)."},{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."},{"title":"Furniture visibility","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"A min/max envelope: a translucent band between each label's `low` and `high`, an optional solid `mid` line through it, and the standard scrub-to-inspect flag showing High, Mid, and Low. The y domain hugs the data rather than anchoring at zero, since an envelope is a range idiom, not a magnitude bar. Forecast bands, error envelopes, and daily temperature ranges all read this way.","ios":"A min/max envelope: a translucent band between each label's `low` and `high`, an optional solid `mid` line through it, and the standard scrub-to-inspect flag showing High, Mid, and Low. The y domain hugs the data rather than anchoring at zero, since an envelope is a range idiom, not a magnitude bar. Forecast bands, error envelopes, and daily temperature ranges all read this way.","android":"A min/max envelope: a translucent band between each label's `low` and `high`, an optional solid `mid` line through it, and the standard scrub-to-inspect flag showing High, Mid, and Low. The y domain hugs the data rather than anchoring at zero, since an envelope is a range idiom, not a magnitude bar. Forecast bands, error envelopes, and daily temperature ranges all read this way."}},{"slug":"reveal","name":"Reveal","category":"atoms","description":"An entrance for page content: what it wraps starts slightly offset and transparent, then travels into place and fades in when it reaches the viewport. It fires once and stays, so content that has arrived never leaves again.","source":"src/atoms/reveal/reveal.md","url":"https://canvas.nannier.com/ai/4.2.0/components/reveal.md","humanUrl":"https://canvas.nannier.com/components/reveal","exports":["Reveal","RevealGroup","RevealGroupProps","RevealProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"RevealGroupProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"The Reveals to stagger. Each direct child receives the next ordinal in document order, so a mapped list arrives one item after another with no per-item props."}],"groups":[],"inherits":[]},{"name":"RevealProps","props":[{"name":"fromBelow","type":"boolean | undefined","required":false,"description":"Rise into place from below. The default.","default":"false","group":0},{"name":"fromAbove","type":"boolean | undefined","required":false,"description":"Descend into place from above.","default":"false","group":0},{"name":"fromLeft","type":"boolean | undefined","required":false,"description":"Slide in from the left. Physical, and does not mirror under RTL (see above).","default":"false","group":0},{"name":"fromRight","type":"boolean | undefined","required":false,"description":"Slide in from the right. Physical, and does not mirror under RTL (see above).","default":"false","group":0},{"name":"pronounced","type":"boolean | undefined","required":false,"description":"Travel further before settling, for a hero or a section header. Omit for the default, shorter travel.","default":"false","group":0},{"name":"brisk","type":"boolean | undefined","required":false,"description":"Arrive faster, for dense sets where the eye should not wait. Omit for the default duration.","default":"false","group":0},{"name":"deepInView","type":"boolean | undefined","required":false,"description":"Wait until the element is properly inside the viewport before starting, instead of firing as it enters.","default":"false","group":0},{"name":"children","type":"ReactNode","required":false,"description":"The content to reveal.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Outer layout composition ONLY: how this wrapper sits in its parent (a `minWidth` of 0 so a grid child may shrink below its content, a `height` of 100% so cards in a row stay even, a flex share). It is NOT a restyle hook: the entrance itself is chosen entirely with the boolean props above, and the revealed content styles itself. A wrapper that cannot be told how to sit in its parent forces callers to add a second wrapper around it, which is worse.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the wrapper.","group":0}],"groups":[{"title":"Direction","pickOne":true,"note":"Direction (pick one; the content travels FROM there to its resting place). Precedence when more than one is passed: fromBelow, fromAbove, fromLeft, fromRight. Pass none for the default, which is fromBelow."}],"inherits":[]}],"platformNotes":{"web":"An entrance for page content: what it wraps starts slightly offset and transparent, then travels into place and fades in when it reaches the viewport. It fires once and stays, so content that has arrived never leaves again.\n\nDirection chooses the axis it travels from, with `fromBelow` the default and `fromAbove`, `fromLeft`, `fromRight` the alternatives (that is also the precedence order if more than one is passed). `pronounced` travels further, `brisk` arrives faster, and `deepInView` holds the entrance until the element is properly inside the viewport instead of firing as it enters.\n\nStagger is structural rather than numeric: wrap a set in `RevealGroup` and each child arrives after the one before it, so no call site ever computes a delay. `RevealGroup` renders no box of its own, so it can sit between a grid and the items the grid lays out.\n\nThe trigger is measured against the window rather than the nearest scrolling parent, so content sitting inside a short inner scroller can arrive before that scroller has been scrolled to it; reveal on the page scroll, which is what this is for. Under Reduce Motion the content renders its final frame immediately, with no measuring and no timers, and the stagger is skipped along with the motion.","ios":"An entrance for page content: what it wraps starts slightly offset and transparent, then travels into place and fades in when it reaches the viewport. It fires once and stays, so content that has arrived never leaves again.\n\nDirection chooses the axis it travels from, with `fromBelow` the default and `fromAbove`, `fromLeft`, `fromRight` the alternatives (that is also the precedence order if more than one is passed). `pronounced` travels further, `brisk` arrives faster, and `deepInView` holds the entrance until the element is properly inside the viewport instead of firing as it enters.\n\nStagger is structural rather than numeric: wrap a set in `RevealGroup` and each child arrives after the one before it, so no call site ever computes a delay. `RevealGroup` renders no box of its own, so it can sit between a grid and the items the grid lays out.\n\nThe trigger is measured against the window rather than the nearest scrolling parent, so content sitting inside a short inner scroller can arrive before that scroller has been scrolled to it; reveal on the page scroll, which is what this is for. Under Reduce Motion the content renders its final frame immediately, with no measuring and no timers, and the stagger is skipped along with the motion.","android":"An entrance for page content: what it wraps starts slightly offset and transparent, then travels into place and fades in when it reaches the viewport. It fires once and stays, so content that has arrived never leaves again.\n\nDirection chooses the axis it travels from, with `fromBelow` the default and `fromAbove`, `fromLeft`, `fromRight` the alternatives (that is also the precedence order if more than one is passed). `pronounced` travels further, `brisk` arrives faster, and `deepInView` holds the entrance until the element is properly inside the viewport instead of firing as it enters.\n\nStagger is structural rather than numeric: wrap a set in `RevealGroup` and each child arrives after the one before it, so no call site ever computes a delay. `RevealGroup` renders no box of its own, so it can sit between a grid and the items the grid lays out.\n\nThe trigger is measured against the window rather than the nearest scrolling parent, so content sitting inside a short inner scroller can arrive before that scroller has been scrolled to it; reveal on the page scroll, which is what this is for. Under Reduce Motion the content renders its final frame immediately, with no measuring and no timers, and the stagger is skipped along with the motion."}},{"slug":"row-column","name":"Row & Column","category":"atoms","description":"The layout primitives. `Row` lays children out horizontally, `Column` vertically. Both own arrangement through semantic boolean axes, a gap scale (`flush` / `tight` / `snug` / `cozy` / `relaxed` / `loose`), main-axis distribution (`center`, `between`, …), cross-axis alignment (`alignCenter`, `baseline`, …), and `wrap` / `fill` / `grow` / `shrink`, so a call site never hand-rolls `flexDirection`, `gap`, or `alignItems`.","source":"src/atoms/layout/layout.md","url":"https://canvas.nannier.com/ai/4.2.0/components/row-column.md","humanUrl":"https://canvas.nannier.com/components/row-column","exports":["Column","FlexProps","Row"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"FlexProps","props":[{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"rowsTight","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"rowsComfortable","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"rowsSnug","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"rowsCozy","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"rowsSection","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"rowsPanel","type":"boolean | undefined","required":false,"description":"A wrapped or stacked row's vertical gap of 28, apart from its main gap: the hand-off's section hero (`gap:28px 40px`), whose halves sit 40 apart beside each other and 28 apart once stacked.","default":"false"},{"name":"insetIdentity","type":"boolean | undefined","required":false,"description":"Application identity header inset.","default":"false"},{"name":"insetActions","type":"boolean | undefined","required":false,"description":"Application action footer inset.","default":"false"},{"name":"insetTheme","type":"boolean | undefined","required":false,"description":"Theme controls inset.","default":"false"},{"name":"insetStatus","type":"boolean | undefined","required":false,"description":"Status band inset.","default":"false"},{"name":"insetTabs","type":"boolean | undefined","required":false,"description":"Navigation close controls inset.","default":"false"},{"name":"fine","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"dense","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"compact","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"close","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"nested","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"comfortable","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"balanced","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"roomy","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"airy","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"spacious","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"generous","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"section","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"panel","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"page","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"apart","type":"boolean | undefined","required":false,"description":"The step between side-by-side panels of one composition (32), the hand-off's widest grid gap.","default":"false"},{"name":"ample","type":"boolean | undefined","required":false,"description":"The step between a section page's hero and the body under it, and between the hero's halves (40): the hand-off's section pages (`gap:28px 40px` on the hero, `margin-bottom:40px` under it).","default":"false"},{"name":"broad","type":"boolean | undefined","required":false,"description":"The gap between the two halves of a page-wide split (48): the hand-off's hero grid.","default":"false"},{"name":"chapter","type":"boolean | undefined","required":false,"description":"The widest gap step (64): the space between a page's chapters, the major sections of a long docs page (a component detail page's Playground, Props and Examples), wider than `page` so each chapter reads as its own block. Wins over every other gap step.","default":"false"},{"name":"flush","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`). Maps to the shared spacing tokens.","default":"false","group":0},{"name":"tight","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`). Maps to the shared spacing tokens.","default":"false","group":0},{"name":"snug","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`). Maps to the shared spacing tokens.","default":"false","group":0},{"name":"cozy","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`). Maps to the shared spacing tokens.","default":"false","group":0},{"name":"relaxed","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`). Maps to the shared spacing tokens.","default":"false","group":0},{"name":"loose","type":"boolean | undefined","required":false,"description":"Gap scale (pick one; default `snug`). Maps to the shared spacing tokens.","default":"false","group":0},{"name":"start","type":"boolean | undefined","required":false,"description":"Main-axis distribution / justifyContent (pick one; default `start`).","default":"false","group":1},{"name":"center","type":"boolean | undefined","required":false,"description":"Main-axis distribution / justifyContent (pick one; default `start`).","default":"false","group":1},{"name":"end","type":"boolean | undefined","required":false,"description":"Main-axis distribution / justifyContent (pick one; default `start`).","default":"false","group":1},{"name":"between","type":"boolean | undefined","required":false,"description":"Main-axis distribution / justifyContent (pick one; default `start`).","default":"false","group":1},{"name":"around","type":"boolean | undefined","required":false,"description":"Main-axis distribution / justifyContent (pick one; default `start`).","default":"false","group":1},{"name":"evenly","type":"boolean | undefined","required":false,"description":"Main-axis distribution / justifyContent (pick one; default `start`).","default":"false","group":1},{"name":"alignStart","type":"boolean | undefined","required":false,"description":"Cross-axis alignment / alignItems (pick one; default `stretch`, RN's native default).","default":"false","group":2},{"name":"alignCenter","type":"boolean | undefined","required":false,"description":"Cross-axis alignment / alignItems (pick one; default `stretch`, RN's native default).","default":"false","group":2},{"name":"alignEnd","type":"boolean | undefined","required":false,"description":"Cross-axis alignment / alignItems (pick one; default `stretch`, RN's native default).","default":"false","group":2},{"name":"baseline","type":"boolean | undefined","required":false,"description":"Cross-axis alignment / alignItems (pick one; default `stretch`, RN's native default).","default":"false","group":2},{"name":"stretch","type":"boolean | undefined","required":false,"description":"Cross-axis alignment / alignItems (pick one; default `stretch`, RN's native default).","default":"false","group":2},{"name":"wrap","type":"boolean | undefined","required":false,"description":"Orthogonal modifiers (stack freely).","default":"false","group":3},{"name":"fill","type":"boolean | undefined","required":false,"description":"Orthogonal modifiers (stack freely).","default":"false","group":3},{"name":"grow","type":"boolean | undefined","required":false,"description":"Orthogonal modifiers (stack freely).","default":"false","group":3},{"name":"shrink","type":"boolean | undefined","required":false,"description":"Let this box shrink below its own content width when the line runs out of room (`flexShrink: 1`), so a long text child wraps instead of overflowing. React Native gives every box `flexShrink: 0`, which is the opposite of the web's flex default: inside a Row, a Column holding a sentence keeps its MAX-CONTENT width and spills past the row's edge, where the nearest clipping ancestor cuts it mid-word. `shrink` is the opt-in that hands the row's width back to the text. Reach for it on the copy in a heading-beside-actions row, a label beside a control, any Row child whose width should follow the row rather than its own longest line. It is not `fill`. `fill` (flex: 1) also zeroes the flex BASIS, so in a `wrap` row every child then fits on one line and the actions stop wrapping below the copy; `shrink` leaves the basis at the content size, so the row still breaks where it did and only the over-wide child gives way. Redundant alongside `fill`, which already shrinks.","default":"false","group":3},{"name":"stacks","type":"boolean | undefined","required":false,"description":"Responsive (Row only): render as a Column when the row's own CONTAINER is at or below `stackBreakpoint` (default `sm` = 640). Container-measured with a viewport seed for the first frame, so a Row inside a narrow desktop column stacks too, not just on phones. When stacked, the Row IS the Column with the same props: gap, justify, align, and padding apply to the new axes, the default `stretch` cross-axis makes children full width, and `wrap` is inert. Ignored (with a DEV warning) on Column: a Column that must become a Row is a Row that stacks.","default":"false","group":3},{"name":"stackBreakpoint","type":"BreakpointKey | undefined","required":false,"description":"The breakpoint at and below which `stacks` flips to a column (default `\"sm\"`). Only meaningful with `stacks` (DEV warns without it).","group":3},{"name":"span","type":"number | undefined","required":false,"description":"Width in twelfths of the parent Row (Bootstrap `.col-n`): `span={6}` is half the row, `span={4}` a third, `span={12}` the full width. The Row measures its own width and gives this box a px cell, gaps included in the arithmetic, so two `span={6}` children plus the gap between them fill the row exactly. Spans over twelve wrap onto the next line. A Row with `stacks` ignores spans once it has stacked (every child is then full width). Only meaningful on a direct child of a Row (DEV warns elsewhere); in a Column, a width is a Container step. A child without a span, `fill`, or `grow` hugs its content (`.col-auto`): a fill component inside it collapses, so give it one of those.","group":3},{"name":"weight","type":"number | undefined","required":false,"description":"A share of the parent Row's free width, CSS grid's `minmax(0, Nfr)`: siblings with `weight={1.7}` and `weight={1}` split the row 1.7 to 1 after the gap, whatever their content, and neither holds a content floor. It is the split a ratio of twelfths cannot name (the Canvas v4 component page's anatomy is 1.7 to 1, where `span` gives 7 to 5). A positive number; it replaces `fill` and `grow` on the same box, and a box takes a `span` or a `weight`, not both. Only meaningful on a direct child of a Row (DEV warns elsewhere); once a `stacks` Row has stacked, the box is the whole line and the weight is ignored.","group":3},{"name":"indent","type":"boolean | undefined","required":false,"description":"Indent the whole stack by one control gutter (24: a control box plus the row gap), so a nested option group lines up under its parent control's label instead of its box. For nesting checkboxes/radios under a \"select all\" parent.","default":"false","group":3},{"name":"padTight","type":"boolean | undefined","required":false,"description":"Padding scale (pick one; omit for none).","default":"false","group":4},{"name":"pad","type":"boolean | undefined","required":false,"description":"Padding scale (pick one; omit for none).","default":"false","group":4},{"name":"padLoose","type":"boolean | undefined","required":false,"description":"Padding scale (pick one; omit for none).","default":"false","group":4},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":4},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Layout containers are the exception to the no-sizing rule: for sizing and composition only (a `maxWidth` on a shell, a `flex` inside an app frame), never for styling or spacing. Gap, margin, padding, and flex layout come from the props above, and the codegen guardrail rejects those keys in `style`. Prefer a Container step or a `span` where one fits.","group":4}],"groups":[{"title":"Gap scale","pickOne":true,"note":"Gap scale (pick one; default `snug`). Maps to the shared spacing tokens."},{"title":"Main-axis distribution / justifyContent","pickOne":true,"note":"Main-axis distribution / justifyContent (pick one; default `start`)."},{"title":"Cross-axis alignment / alignItems","pickOne":true,"note":"Cross-axis alignment / alignItems (pick one; default `stretch`, RN's native default)."},{"title":"Orthogonal modifiers","pickOne":false,"note":"Orthogonal modifiers (stack freely)."},{"title":"Padding scale","pickOne":true,"note":"Padding scale (pick one; omit for none)."}],"inherits":[]}],"platformNotes":{"web":"The layout primitives. `Row` lays children out horizontally, `Column`\nvertically. Both own arrangement through semantic boolean axes, a gap scale\n(`flush` / `tight` / `snug` / `cozy` / `relaxed` / `loose`), main-axis\ndistribution (`center`, `between`, …), cross-axis alignment (`alignCenter`,\n`baseline`, …), and `wrap` / `fill` / `grow` / `shrink`, so a call site never\nhand-rolls `flexDirection`, `gap`, or `alignItems`.\n\nThe Argus reference adds intermediate spacing steps without rounding its layout:\n`fine` 3, `dense` 5, `compact` 6, `close` 7, `nested` 9, `comfortable` 10,\n`balanced` 11, `roomy` 14, `airy` 18, `spacious` 20, `generous` 22,\n`section` 26, `panel` 28, `page` 30, `apart` 32 (the space between the side-by-side\npanels of one composition), `ample` 40 (between a section page's hero and the body under\nit, and between the hero's halves) and `broad` 48 (between the two halves of a page-wide split). Existing named steps keep their values.\nLarger active steps take precedence.\n\n`ample` (40) is the step between a section page's hero and the body under it, and between\nthe hero's halves (the Canvas v4 section pages). `chapter` (64) is the widest step: the\nspace between a page's chapters, the major sections of a long page (a component detail\npage's Playground, Props and Examples). It wins over every other gap step, so the\nprecedence runs `chapter` > `broad` > `ample` > `apart` > `page` > `panel` > `section` >\n`loose` and on down the scale to `flush`. Row, Column and Grid all take them.\n\n`rowsTight`, `rowsComfortable`, `rowsSnug`, `rowsCozy`, `rowsSection` and `rowsPanel` set a\nwrapped or stacked row's vertical gap to 4, 10, 8, 12, 26 and 28 independently of its main\ngap (a stacked `Row stacks` lays its children down that vertical gap, so a hero whose\nhalves sit 40 apart beside each other and 28 apart stacked is `ample rowsPanel`). Application inset\nroles preserve identity headers (24 top/horizontal, 18 bottom), action footers\n(16 vertical, 24 horizontal), theme controls (14 top, 26 horizontal), status bands\n(10 vertical, 28 horizontal), and navigation close controls (12 top/horizontal):\n`insetIdentity`, `insetActions`, `insetTheme`, `insetStatus`, and `insetTabs`.","ios":"The layout primitives. `Row` lays children out horizontally, `Column`\nvertically. Both own arrangement through semantic boolean axes, a gap scale\n(`flush` / `tight` / `snug` / `cozy` / `relaxed` / `loose`), main-axis\ndistribution (`center`, `between`, …), cross-axis alignment (`alignCenter`,\n`baseline`, …), and `wrap` / `fill` / `grow` / `shrink`, so a call site never\nhand-rolls `flexDirection`, `gap`, or `alignItems`.\n\nThe Argus reference adds intermediate spacing steps without rounding its layout:\n`fine` 3, `dense` 5, `compact` 6, `close` 7, `nested` 9, `comfortable` 10,\n`balanced` 11, `roomy` 14, `airy` 18, `spacious` 20, `generous` 22,\n`section` 26, `panel` 28, `page` 30, `apart` 32 (the space between the side-by-side\npanels of one composition), `ample` 40 (between a section page's hero and the body under\nit, and between the hero's halves) and `broad` 48 (between the two halves of a page-wide split). Existing named steps keep their values.\nLarger active steps take precedence.\n\n`ample` (40) is the step between a section page's hero and the body under it, and between\nthe hero's halves (the Canvas v4 section pages). `chapter` (64) is the widest step: the\nspace between a page's chapters, the major sections of a long page (a component detail\npage's Playground, Props and Examples). It wins over every other gap step, so the\nprecedence runs `chapter` > `broad` > `ample` > `apart` > `page` > `panel` > `section` >\n`loose` and on down the scale to `flush`. Row, Column and Grid all take them.\n\n`rowsTight`, `rowsComfortable`, `rowsSnug`, `rowsCozy`, `rowsSection` and `rowsPanel` set a\nwrapped or stacked row's vertical gap to 4, 10, 8, 12, 26 and 28 independently of its main\ngap (a stacked `Row stacks` lays its children down that vertical gap, so a hero whose\nhalves sit 40 apart beside each other and 28 apart stacked is `ample rowsPanel`). Application inset\nroles preserve identity headers (24 top/horizontal, 18 bottom), action footers\n(16 vertical, 24 horizontal), theme controls (14 top, 26 horizontal), status bands\n(10 vertical, 28 horizontal), and navigation close controls (12 top/horizontal):\n`insetIdentity`, `insetActions`, `insetTheme`, `insetStatus`, and `insetTabs`.","android":"The layout primitives. `Row` lays children out horizontally, `Column`\nvertically. Both own arrangement through semantic boolean axes, a gap scale\n(`flush` / `tight` / `snug` / `cozy` / `relaxed` / `loose`), main-axis\ndistribution (`center`, `between`, …), cross-axis alignment (`alignCenter`,\n`baseline`, …), and `wrap` / `fill` / `grow` / `shrink`, so a call site never\nhand-rolls `flexDirection`, `gap`, or `alignItems`.\n\nThe Argus reference adds intermediate spacing steps without rounding its layout:\n`fine` 3, `dense` 5, `compact` 6, `close` 7, `nested` 9, `comfortable` 10,\n`balanced` 11, `roomy` 14, `airy` 18, `spacious` 20, `generous` 22,\n`section` 26, `panel` 28, `page` 30, `apart` 32 (the space between the side-by-side\npanels of one composition), `ample` 40 (between a section page's hero and the body under\nit, and between the hero's halves) and `broad` 48 (between the two halves of a page-wide split). Existing named steps keep their values.\nLarger active steps take precedence.\n\n`ample` (40) is the step between a section page's hero and the body under it, and between\nthe hero's halves (the Canvas v4 section pages). `chapter` (64) is the widest step: the\nspace between a page's chapters, the major sections of a long page (a component detail\npage's Playground, Props and Examples). It wins over every other gap step, so the\nprecedence runs `chapter` > `broad` > `ample` > `apart` > `page` > `panel` > `section` >\n`loose` and on down the scale to `flush`. Row, Column and Grid all take them.\n\n`rowsTight`, `rowsComfortable`, `rowsSnug`, `rowsCozy`, `rowsSection` and `rowsPanel` set a\nwrapped or stacked row's vertical gap to 4, 10, 8, 12, 26 and 28 independently of its main\ngap (a stacked `Row stacks` lays its children down that vertical gap, so a hero whose\nhalves sit 40 apart beside each other and 28 apart stacked is `ample rowsPanel`). Application inset\nroles preserve identity headers (24 top/horizontal, 18 bottom), action footers\n(16 vertical, 24 horizontal), theme controls (14 top, 26 horizontal), status bands\n(10 vertical, 28 horizontal), and navigation close controls (12 top/horizontal):\n`insetIdentity`, `insetActions`, `insetTheme`, `insetStatus`, and `insetTabs`."}},{"slug":"row-menu","name":"RowMenu","category":"organisms","description":"Vertical action menu items and navigation links.","source":"src/organisms/row-menu/row-menu.md","url":"https://canvas.nannier.com/ai/4.2.0/components/row-menu.md","humanUrl":"https://canvas.nannier.com/components/row-menu","exports":["RowMenu","RowMenuItem","RowMenuProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"RowMenuProps","props":[{"name":"items","type":"RowMenuItem[]","required":true,"description":"The menu rows, top to bottom."},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Omit for uncontrolled (the trigger toggles it).","default":"false"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes."},{"name":"links","type":"boolean | undefined","required":false,"description":"Render rows as navigation links rather than action buttons.","default":"false"},{"name":"inline","type":"boolean | undefined","required":false,"description":"The menu drawn in place, with no ⋯ trigger and no overlay: the action rows in the menu's own panel, filling the width the parent gives it. With `links` it is a grouped link list instead: hairline-split rows, each ending in its `badge` or `meta` and a chevron. `open`, `onOpenChange` and `triggerLabel` do nothing here.","default":"false"},{"name":"sectionLabel","type":"string | undefined","required":false,"description":"Show a muted section label heading the menu."},{"name":"onSelect","type":"((item: RowMenuItem, index: number) => void) | undefined","required":false,"description":"Fired with the selected item and its index when a row is pressed."},{"name":"triggerLabel","type":"string | undefined","required":false,"description":"Accessible name for the icon-only ⋯ trigger. Defaults to \"More options\".","default":"\"More options\""},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"Vertical action menu items and navigation links.\n\nOn the web the ··· trigger is a 32px square on the field hairline, washed while its\nmenu is open or under the pointer, and it opens a card menu 220 wide: rows 34 tall\nwith a muted leading glyph beside the label, and a destructive row in red.\niOS and\nAndroid keep their platform context menus in the theme's colours.\n\nIn glass mode the menu is a dense-layer glass card beside its glyph; a row's\ncallback fires the moment it is pressed. Solid mode paints the skin's own menu.\nBoard's card menus are RowMenus and behave the same.","ios":"Vertical action menu items and navigation links.\n\nOn the web the ··· trigger is a 32px square on the field hairline, washed while its\nmenu is open or under the pointer, and it opens a card menu 220 wide: rows 34 tall\nwith a muted leading glyph beside the label, and a destructive row in red.\niOS keeps its platform context menu in the theme's colours.\n\nIn glass mode the menu is a dense-layer glass card beside its glyph; a row's\ncallback fires the moment it is pressed. Solid mode paints the skin's own menu.\nBoard's card menus are RowMenus and behave the same.","android":"Vertical action menu items and navigation links.\n\nOn the web the ··· trigger is a 32px square on the field hairline, washed while its\nmenu is open or under the pointer, and it opens a card menu 220 wide: rows 34 tall\nwith a muted leading glyph beside the label, and a destructive row in red.\nAndroid keeps its platform context menu in the theme's colours.\n\nIn glass mode the menu is a dense-layer glass card beside its glyph; a row's\ncallback fires the moment it is pressed. Solid mode paints the skin's own menu.\nBoard's card menus are RowMenus and behave the same."}},{"slug":"scatter-plot","name":"ScatterPlot","category":"charts","description":"Numeric x/y point clouds with nice ticks on both axes and horizontal gridlines. Multi-series clouds use the series tokens; pressing near a point rings it and flags its coordinates.","source":"src/charts/scatter-plot/scatter-plot.md","url":"https://canvas.nannier.com/ai/4.2.0/components/scatter-plot.md","humanUrl":"https://canvas.nannier.com/components/scatter-plot","exports":["ScatterPlot","ScatterPlotProps","ScatterPoint","ScatterSelection","ScatterSeries"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ScatterPlotProps","props":[{"name":"series","type":"ScatterSeries[]","required":true,"description":"The point clouds; colors follow the chart-1..8 tokens in fixed order."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (single-series only; pick one; default is the primary fill).","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (single-series only; pick one; default is the primary fill).","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":1},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":1},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":2},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":2},{"name":"hideAxes","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":2},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats tick labels and accessible values (data formatting, not styling).","group":2},{"name":"selected","type":"ScatterSelection | null | undefined","required":false,"description":"Press-to-inspect: the selected point (controlled). Pass null for none.","group":2},{"name":"defaultSelected","type":"ScatterSelection | undefined","required":false,"description":"Press-to-inspect: the initially selected point (uncontrolled).","group":2},{"name":"onSelect","type":"((selection: ScatterSelection | null) => void) | undefined","required":false,"description":"Fired when a press selects a point (or clears it with null).","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":2}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (single-series only; pick one; default is the primary fill)."},{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."},{"title":"Furniture visibility","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"Numeric x/y point clouds with nice ticks on both axes and horizontal gridlines. Multi-series clouds use the series tokens; pressing near a point rings it and flags its coordinates.","ios":"Numeric x/y point clouds with nice ticks on both axes and horizontal gridlines. Multi-series clouds use the series tokens; pressing near a point rings it and flags its coordinates.","android":"Numeric x/y point clouds with nice ticks on both axes and horizontal gridlines. Multi-series clouds use the series tokens; pressing near a point rings it and flags its coordinates."}},{"slug":"scroll-view","name":"ScrollView","category":"atoms","description":"A scrollable container for content larger than its bounds: vertical by default, `horizontal` for a row.","source":"src/atoms/scroll-view/scroll-view.md","url":"https://canvas.nannier.com/ai/4.2.0/components/scroll-view.md","humanUrl":"https://canvas.nannier.com/components/scroll-view","exports":["ScrollView"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ScrollView host props","groups":[],"inherits":[],"props":[{"name":"contentContainerStyle","type":"StyleProp<ViewStyle>","required":false,"description":"These styles will be applied to the scroll view content container which wraps all of the child views. Example: return ( <ScrollView contentContainerStyle={styles.contentContainer}> </ScrollView> ); ... const styles = StyleSheet.create({ contentContainer: { paddingVertical: 20 } });"},{"name":"innerViewRef","type":"React.RefObject<View> | undefined","required":false,"description":"A ref to the inner View element of the ScrollView. This should be used instead of calling `getInnerViewRef`."},{"name":"scrollViewRef","type":"React.RefObject<ScrollView> | undefined","required":false,"description":"A ref to the Native ScrollView component. This ref can be used to call all of ScrollView's public methods, in addition to native methods like measure, measureLayout, etc."},{"name":"decelerationRate","type":"number | \"normal\" | \"fast\" | undefined","required":false,"description":"A floating-point number that determines how quickly the scroll view decelerates after the user lifts their finger. You may also use string shortcuts `\"normal\"` and `\"fast\"` which match the underlying iOS settings for `UIScrollViewDecelerationRateNormal` and `UIScrollViewDecelerationRateFast` respectively. - `'normal'`: 0.998 on iOS, 0.985 on Android (the default) - `'fast'`: 0.99 on iOS, 0.9 on Android"},{"name":"horizontal","type":"boolean | null | undefined","required":false,"description":"When true the scroll view's children are arranged horizontally in a row instead of vertically in a column. The default value is false."},{"name":"invertStickyHeaders","type":"boolean | undefined","required":false,"description":"If sticky headers should stick at the bottom instead of the top of the ScrollView. This is usually used with inverted ScrollViews."},{"name":"keyboardDismissMode","type":"\"none\" | \"interactive\" | \"on-drag\" | undefined","required":false,"description":"Determines whether the keyboard gets dismissed in response to a drag. - 'none' (the default) drags do not dismiss the keyboard. - 'onDrag' the keyboard is dismissed when a drag begins. - 'interactive' the keyboard is dismissed interactively with the drag and moves in synchrony with the touch; dragging upwards cancels the dismissal."},{"name":"keyboardShouldPersistTaps","type":"boolean | \"handled\" | \"always\" | \"never\" | undefined","required":false,"description":"Determines when the keyboard should stay visible after a tap. - 'never' (the default), tapping outside of the focused text input when the keyboard is up dismisses the keyboard. When this happens, children won't receive the tap. - 'always', the keyboard will not dismiss automatically, and the scroll view will not catch taps, but children of the scroll view can catch taps. - 'handled', the keyboard will not dismiss automatically when the tap was handled by a children, (or captured by an ancestor). - false, deprecated, use 'never' instead - true, deprecated, use 'always' instead"},{"name":"onContentSizeChange","type":"((contentWidth: number, contentHeight: number) => void) | undefined","required":false,"description":"Called when scrollable content view of the ScrollView changes. Handler function is passed the content width and content height as parameters: (contentWidth, contentHeight) It's implemented using onLayout handler attached to the content container which this ScrollView renders."},{"name":"onScroll","type":"((event: NativeSyntheticEvent<NativeScrollEvent>) => void) | undefined","required":false,"description":"Fires at most once per frame during scrolling."},{"name":"onScrollBeginDrag","type":"((event: NativeSyntheticEvent<NativeScrollEvent>) => void) | undefined","required":false,"description":"Fires if a user initiates a scroll gesture."},{"name":"onScrollEndDrag","type":"((event: NativeSyntheticEvent<NativeScrollEvent>) => void) | undefined","required":false,"description":"Fires when a user has finished scrolling."},{"name":"onMomentumScrollEnd","type":"((event: NativeSyntheticEvent<NativeScrollEvent>) => void) | undefined","required":false,"description":"Fires when scroll view has finished moving"},{"name":"onMomentumScrollBegin","type":"((event: NativeSyntheticEvent<NativeScrollEvent>) => void) | undefined","required":false,"description":"Fires when scroll view has begun moving"},{"name":"pagingEnabled","type":"boolean | undefined","required":false,"description":"When true the scroll view stops on multiples of the scroll view's size when scrolling. This can be used for horizontal pagination. The default value is false."},{"name":"scrollEnabled","type":"boolean | undefined","required":false,"description":"When false, the content does not scroll. The default value is true"},{"name":"removeClippedSubviews","type":"boolean | undefined","required":false,"description":"Experimental: When true offscreen child views (whose `overflow` value is `hidden`) are removed from their native backing superview when offscreen. This can improve scrolling performance on long lists. The default value is false."},{"name":"showsHorizontalScrollIndicator","type":"boolean | undefined","required":false,"description":"When true, shows a horizontal scroll indicator."},{"name":"showsVerticalScrollIndicator","type":"boolean | undefined","required":false,"description":"When true, shows a vertical scroll indicator."},{"name":"stickyHeaderHiddenOnScroll","type":"boolean | undefined","required":false,"description":"When true, Sticky header is hidden when scrolling down, and dock at the top when scrolling up."},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Style"},{"name":"refreshControl","type":"React.ReactElement<RefreshControlProps, string | React.JSXElementConstructor<any>> | undefined","required":false,"description":"A RefreshControl component, used to provide pull-to-refresh functionality for the ScrollView."},{"name":"snapToInterval","type":"number | undefined","required":false,"description":"When set, causes the scroll view to stop at multiples of the value of `snapToInterval`. This can be used for paginating through children that have lengths smaller than the scroll view. Used in combination with `snapToAlignment` and `decelerationRate=\"fast\"`. Overrides less configurable `pagingEnabled` prop."},{"name":"snapToOffsets","type":"number[] | undefined","required":false,"description":"When set, causes the scroll view to stop at the defined offsets. This can be used for paginating through variously sized children that have lengths smaller than the scroll view. Typically used in combination with `decelerationRate=\"fast\"`. Overrides less configurable `pagingEnabled` and `snapToInterval` props."},{"name":"snapToStart","type":"boolean | undefined","required":false,"description":"Use in conjunction with `snapToOffsets`. By default, the beginning of the list counts as a snap offset. Set `snapToStart` to false to disable this behavior and allow the list to scroll freely between its start and the first `snapToOffsets` offset. The default value is true."},{"name":"snapToEnd","type":"boolean | undefined","required":false,"description":"Use in conjunction with `snapToOffsets`. By default, the end of the list counts as a snap offset. Set `snapToEnd` to false to disable this behavior and allow the list to scroll freely between its end and the last `snapToOffsets` offset. The default value is true."},{"name":"stickyHeaderIndices","type":"number[] | undefined","required":false,"description":"An array of child indices determining which children get docked to the top of the screen when scrolling. For example passing `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the top of the scroll view. This property is not supported in conjunction with `horizontal={true}`."},{"name":"disableIntervalMomentum","type":"boolean | undefined","required":false,"description":"When true, the scroll view stops on the next index (in relation to scroll position at release) regardless of how fast the gesture is. This can be used for horizontal pagination when the page is less than the width of the ScrollView. The default value is false."},{"name":"disableScrollViewPanResponder","type":"boolean | undefined","required":false,"description":"When true, the default JS pan responder on the ScrollView is disabled, and full control over touches inside the ScrollView is left to its child components. This is particularly useful if `snapToInterval` is enabled, since it does not follow typical touch patterns. Do not use this on regular ScrollView use cases without `snapToInterval` as it may cause unexpected touches to occur while scrolling. The default value is false."},{"name":"StickyHeaderComponent","type":"React.ComponentType<any> | undefined","required":false,"description":"A React Component that will be used to render sticky headers, should be used together with stickyHeaderIndices. You may need to set this component if your sticky header uses custom transforms, for example, when you want your list to have an animated and hidable header. If component have not been provided, the default ScrollViewStickyHeader component will be used."},{"name":"children","type":"React.ReactNode","required":false,"description":""},{"name":"hitSlop","type":"number | Insets | null | undefined","required":false,"description":"This defines how far a touch event can start away from the view. Typical interface guidelines recommend touch targets that are at least 30 - 40 points/density-independent pixels. If a Touchable view has a height of 20 the touchable height can be extended to 40 with hitSlop={{top: 10, bottom: 10, left: 0, right: 0}} NOTE The touch area never extends past the parent view bounds and the Z-index of sibling views always takes precedence if a touch hits two overlapping views."},{"name":"id","type":"string | undefined","required":false,"description":"Used to reference react managed views from native code."},{"name":"needsOffscreenAlphaCompositing","type":"boolean | undefined","required":false,"description":"Whether this view needs to rendered offscreen and composited with an alpha in order to preserve 100% correct colors and blending behavior. The default (false) falls back to drawing the component and its children with an alpha applied to the paint used to draw each element instead of rendering the full component offscreen and compositing it back with an alpha value. This default may be noticeable and undesired in the case where the View you are setting an opacity on has multiple overlapping elements (e.g. multiple overlapping Views, or text and a background). Rendering offscreen to preserve correct alpha behavior is extremely expensive and hard to debug for non-native developers, which is why it is not turned on by default. If you do need to enable this property for an animation, consider combining it with renderToHardwareTextureAndroid if the view contents are static (i.e. it doesn't need to be redrawn each frame). If that property is enabled, this View will be rendered off-screen once, saved in a hardware texture, and then composited onto the screen with an alpha each frame without having to switch rendering targets on the GPU."},{"name":"onLayout","type":"((event: LayoutChangeEvent) => void) | undefined","required":false,"description":"Invoked on mount and layout changes with {nativeEvent: { layout: {x, y, width, height}}}."},{"name":"pointerEvents","type":"\"box-none\" | \"none\" | \"box-only\" | \"auto\" | undefined","required":false,"description":" In the absence of auto property, none is much like CSS's none value. box-none is as if you had applied the CSS class: .box-none { pointer-events: none; } .box-none * { pointer-events: all; } box-only is the equivalent of .box-only { pointer-events: all; } .box-only * { pointer-events: none; } But since pointerEvents does not affect layout/appearance, and we are already deviating from the spec by adding additional modes, we opt to not include pointerEvents on style. On some platforms, we would need to implement it as a className anyways. Using style or not is an implementation detail of the platform."},{"name":"testID","type":"string | undefined","required":false,"description":"Used to locate this view in end-to-end tests."},{"name":"nativeID","type":"string | undefined","required":false,"description":"Used to reference react managed views from native code."},{"name":"collapsable","type":"boolean | undefined","required":false,"description":"Views that are only used to layout their children or otherwise don't draw anything may be automatically removed from the native hierarchy as an optimization. Set this property to false to disable this optimization and ensure that this View exists in the native view hierarchy."},{"name":"collapsableChildren","type":"boolean | undefined","required":false,"description":"Setting to false prevents direct children of the view from being removed from the native view hierarchy, similar to the effect of setting `collapsable={false}` on each child."},{"name":"onBlur","type":"((e: BlurEvent) => void) | null | undefined","required":false,"description":"Callback that is called when the view is blurred. Note: This will only be called if the view is focusable."},{"name":"onFocus","type":"((e: FocusEvent) => void) | null | undefined","required":false,"description":"Callback that is called when the view is focused. Note: This will only be called if the view is focusable."},{"name":"renderToHardwareTextureAndroid","type":"boolean | undefined","required":false,"description":"Whether this view should render itself (and all of its children) into a single hardware texture on the GPU. On Android, this is useful for animations and interactions that only modify opacity, rotation, translation, and/or scale: in those cases, the view doesn't have to be redrawn and display lists don't need to be re-executed. The texture can just be re-used and re-composited with different parameters. The downside is that this can use up limited video memory, so this prop should be set back to false at the end of the interaction/animation."},{"name":"focusable","type":"boolean | undefined","required":false,"description":"Whether this `View` should be focusable with a non-touch input device, eg. receive focus with a hardware keyboard."},{"name":"tabIndex","type":"0 | -1 | undefined","required":false,"description":"Indicates whether this `View` should be focusable with a non-touch input device, eg. receive focus with a hardware keyboard. See https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex for more details. Supports the following values: - 0 (View is focusable) - -1 (View is not focusable)"},{"name":"shouldRasterizeIOS","type":"boolean | undefined","required":false,"description":"Whether this view should be rendered as a bitmap before compositing. On iOS, this is useful for animations and interactions that do not modify this component's dimensions nor its children; for example, when translating the position of a static view, rasterization allows the renderer to reuse a cached bitmap of a static view and quickly composite it during each frame. Rasterization incurs an off-screen drawing pass and the bitmap consumes memory. Test and measure when using this property."},{"name":"isTVSelectable","type":"boolean | undefined","required":false,"description":"*(Apple TV only)* When set to true, this view will be focusable and navigable using the Apple TV remote."},{"name":"hasTVPreferredFocus","type":"boolean | undefined","required":false,"description":"*(Apple TV only)* May be set to true to force the Apple TV focus engine to move focus to this view."},{"name":"tvParallaxShiftDistanceX","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0."},{"name":"tvParallaxShiftDistanceY","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0."},{"name":"tvParallaxTiltAngle","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 0.05."},{"name":"tvParallaxMagnification","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 1.0."},{"name":"onStartShouldSetResponder","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"Does this view want to become responder on the start of a touch?"},{"name":"onMoveShouldSetResponder","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"Called for every touch move on the View when it is not the responder: does this view want to \"claim\" touch responsiveness?"},{"name":"onResponderEnd","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"If the View returns true and attempts to become the responder, one of the following will happen:"},{"name":"onResponderGrant","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"The View is now responding for touch events. This is the time to highlight and show the user what is happening"},{"name":"onResponderReject","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Something else is the responder right now and will not release it"},{"name":"onResponderMove","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"The user is moving their finger"},{"name":"onResponderRelease","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Fired at the end of the touch, ie \"touchUp\""},{"name":"onResponderStart","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onResponderTerminationRequest","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"Something else wants to become responder. Should this view release the responder? Returning true allows release"},{"name":"onResponderTerminate","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"The responder has been taken from the View. Might be taken by other views after a call to onResponderTerminationRequest, or might be taken by the OS without asking (happens with control center/ notification center on iOS)"},{"name":"onStartShouldSetResponderCapture","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern, where the deepest node is called first. That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers. This is desirable in most cases, because it makes sure all controls and buttons are usable. However, sometimes a parent will want to make sure that it becomes responder. This can be handled by using the capture phase. Before the responder system bubbles up from the deepest component, it will do a capture phase, firing on*ShouldSetResponderCapture. So if a parent View wants to prevent the child from becoming responder on a touch start, it should have a onStartShouldSetResponderCapture handler which returns true."},{"name":"onMoveShouldSetResponderCapture","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern, where the deepest node is called first. That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers. This is desirable in most cases, because it makes sure all controls and buttons are usable. However, sometimes a parent will want to make sure that it becomes responder. This can be handled by using the capture phase. Before the responder system bubbles up from the deepest component, it will do a capture phase, firing on*ShouldSetResponderCapture. So if a parent View wants to prevent the child from becoming responder on a touch start, it should have a onStartShouldSetResponderCapture handler which returns true."},{"name":"onTouchStart","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchMove","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchEnd","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchCancel","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchEndCapture","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerEnter","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerEnterCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerLeave","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerLeaveCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerMove","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerMoveCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerCancel","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerCancelCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerDown","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerDownCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerUp","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerUpCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"accessible","type":"boolean | undefined","required":false,"description":"When true, indicates that the view is an accessibility element. By default, all the touchable elements are accessible."},{"name":"accessibilityActions","type":"readonly Readonly<{ name: AccessibilityActionName | string; label?: string | undefined; }>[] | undefined","required":false,"description":"Provides an array of custom actions available for accessibility."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Overrides the text that's read by the screen reader when the user interacts with the element. By default, the label is constructed by traversing all the children and accumulating all the Text nodes separated by space."},{"name":"aria-label","type":"string | undefined","required":false,"description":"Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel https://github.com/facebook/react-native/issues/34424"},{"name":"accessibilityRole","type":"AccessibilityRole | undefined","required":false,"description":"Accessibility Role tells a person using either VoiceOver on iOS or TalkBack on Android the type of element that is focused on."},{"name":"accessibilityState","type":"AccessibilityState | undefined","required":false,"description":"Accessibility State tells a person using either VoiceOver on iOS or TalkBack on Android the state of the element currently focused on."},{"name":"aria-busy","type":"boolean | undefined","required":false,"description":"alias for accessibilityState see https://reactnative.dev/docs/accessibility#accessibilitystate"},{"name":"aria-checked","type":"boolean | \"mixed\" | undefined","required":false,"description":""},{"name":"aria-disabled","type":"boolean | undefined","required":false,"description":""},{"name":"aria-expanded","type":"boolean | undefined","required":false,"description":""},{"name":"aria-selected","type":"boolean | undefined","required":false,"description":""},{"name":"accessibilityHint","type":"string | undefined","required":false,"description":"An accessibility hint helps users understand what will happen when they perform an action on the accessibility element when that result is not obvious from the accessibility label."},{"name":"accessibilityValue","type":"AccessibilityValue | undefined","required":false,"description":"Represents the current value of a component. It can be a textual description of a component's value, or for range-based components, such as sliders and progress bars, it contains range information (minimum, current, and maximum)."},{"name":"aria-valuemax","type":"number | undefined","required":false,"description":""},{"name":"aria-valuemin","type":"number | undefined","required":false,"description":""},{"name":"aria-valuenow","type":"number | undefined","required":false,"description":""},{"name":"aria-valuetext","type":"string | undefined","required":false,"description":""},{"name":"onAccessibilityAction","type":"((event: AccessibilityActionEvent) => void) | undefined","required":false,"description":"When `accessible` is true, the system will try to invoke this function when the user performs an accessibility custom action."},{"name":"importantForAccessibility","type":"\"auto\" | \"yes\" | \"no\" | \"no-hide-descendants\" | undefined","required":false,"description":"[Android] Controlling if a view fires accessibility events and if it is reported to accessibility services."},{"name":"aria-hidden","type":"boolean | undefined","required":false,"description":"A value indicating whether the accessibility elements contained within this accessibility element are hidden."},{"name":"aria-modal","type":"boolean | undefined","required":false,"description":""},{"name":"role","type":"Role | undefined","required":false,"description":"Indicates to accessibility services to treat UI component like a specific role."},{"name":"accessibilityLabelledBy","type":"string | string[] | undefined","required":false,"description":"Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props, the text is read aloud. The value should should match the nativeID of the related element."},{"name":"aria-labelledby","type":"string | undefined","required":false,"description":"Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props, the text is read aloud. The value should should match the nativeID of the related element."},{"name":"accessibilityLiveRegion","type":"\"none\" | \"polite\" | \"assertive\" | undefined","required":false,"description":"Indicates to accessibility services whether the user should be notified when this view changes. Works for Android API >= 19 only."},{"name":"aria-live","type":"\"polite\" | \"assertive\" | \"off\" | undefined","required":false,"description":"Indicates to accessibility services whether the user should be notified when this view changes. Works for Android API >= 19 only."},{"name":"screenReaderFocusable","type":"boolean | undefined","required":false,"description":"Enables the view to be screen reader focusable, not keyboard focusable."},{"name":"accessibilityElementsHidden","type":"boolean | undefined","required":false,"description":"A Boolean value indicating whether the accessibility elements contained within this accessibility element are hidden to the screen reader."},{"name":"accessibilityViewIsModal","type":"boolean | undefined","required":false,"description":"A Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver."},{"name":"onAccessibilityEscape","type":"(() => void) | undefined","required":false,"description":"When accessible is true, the system will invoke this function when the user performs the escape gesture (scrub with two fingers)."},{"name":"onAccessibilityTap","type":"(() => void) | undefined","required":false,"description":"When `accessible` is true, the system will try to invoke this function when the user performs accessibility tap gesture."},{"name":"onMagicTap","type":"(() => void) | undefined","required":false,"description":"When accessible is true, the system will invoke this function when the user performs the magic tap gesture."},{"name":"accessibilityIgnoresInvertColors","type":"boolean | undefined","required":false,"description":"https://reactnative.dev/docs/accessibility#accessibilityignoresinvertcolorsios"},{"name":"accessibilityLanguage","type":"string | undefined","required":false,"description":"By using the accessibilityLanguage property, the screen reader will understand which language to use while reading the element's label, value and hint. The provided string value must follow the BCP 47 specification (https://www.rfc-editor.org/info/bcp47). https://reactnative.dev/docs/accessibility#accessibilitylanguage-ios"},{"name":"accessibilityShowsLargeContentViewer","type":"boolean | undefined","required":false,"description":"A Boolean value that indicates whether or not to show the item in the large content viewer. Available on iOS 13.0+ https://reactnative.dev/docs/accessibility#accessibilityshowslargecontentviewer"},{"name":"accessibilityLargeContentTitle","type":"string | undefined","required":false,"description":"When `accessibilityShowsLargeContentViewer` is set, this string will be used as title for the large content viewer. https://reactnative.dev/docs/accessibility#accessibilitylargecontenttitle"},{"name":"accessibilityRespondsToUserInteraction","type":"boolean | undefined","required":false,"description":"Blocks the user from interacting with the component through keyboard while still allowing screen reader to interact with it if this View is still accessible."},{"name":"alwaysBounceHorizontal","type":"boolean | undefined","required":false,"description":"When true the scroll view bounces horizontally when it reaches the end even if the content is smaller than the scroll view itself. The default value is true when `horizontal={true}` and false otherwise."},{"name":"alwaysBounceVertical","type":"boolean | undefined","required":false,"description":"When true the scroll view bounces vertically when it reaches the end even if the content is smaller than the scroll view itself. The default value is false when `horizontal={true}` and true otherwise."},{"name":"automaticallyAdjustContentInsets","type":"boolean | undefined","required":false,"description":"Controls whether iOS should automatically adjust the content inset for scroll views that are placed behind a navigation bar or tab bar/ toolbar. The default value is true."},{"name":"automaticallyAdjustKeyboardInsets","type":"boolean | undefined","required":false,"description":"Controls whether the ScrollView should automatically adjust its contentInset and scrollViewInsets when the Keyboard changes its size. The default value is false."},{"name":"automaticallyAdjustsScrollIndicatorInsets","type":"boolean | undefined","required":false,"description":"Controls whether iOS should automatically adjust the scroll indicator insets. The default value is true. Available on iOS 13 and later."},{"name":"bounces","type":"boolean | undefined","required":false,"description":"When true the scroll view bounces when it reaches the end of the content if the content is larger than the scroll view along the axis of the scroll direction. When false it disables all bouncing even if the `alwaysBounce*` props are true. The default value is true."},{"name":"bouncesZoom","type":"boolean | undefined","required":false,"description":"When true gestures can drive zoom past min/max and the zoom will animate to the min/max value at gesture end otherwise the zoom will not exceed the limits."},{"name":"canCancelContentTouches","type":"boolean | undefined","required":false,"description":"When false once tracking starts won't try to drag if the touch moves. The default value is true."},{"name":"centerContent","type":"boolean | undefined","required":false,"description":"When true the scroll view automatically centers the content when the content is smaller than the scroll view bounds; when the content is larger than the scroll view this property has no effect. The default value is false."},{"name":"contentInset","type":"Insets | undefined","required":false,"description":"The amount by which the scroll view content is inset from the edges of the scroll view. Defaults to {0, 0, 0, 0}."},{"name":"contentOffset","type":"PointProp | undefined","required":false,"description":"Used to manually set the starting scroll offset. The default value is {x: 0, y: 0}"},{"name":"contentInsetAdjustmentBehavior","type":"\"always\" | \"never\" | \"automatic\" | \"scrollableAxes\" | undefined","required":false,"description":"This property specifies how the safe area insets are used to modify the content area of the scroll view. The default value of this property is \"never\"."},{"name":"directionalLockEnabled","type":"boolean | undefined","required":false,"description":"When true the ScrollView will try to lock to only vertical or horizontal scrolling while dragging. The default value is false."},{"name":"indicatorStyle","type":"\"default\" | \"black\" | \"white\" | undefined","required":false,"description":"The style of the scroll indicators. - default (the default), same as black. - black, scroll indicator is black. This style is good against a white content background. - white, scroll indicator is white. This style is good against a black content background."},{"name":"maintainVisibleContentPosition","type":"{ autoscrollToTopThreshold?: number | null | undefined; minIndexForVisible: number; } | null | undefined","required":false,"description":"When set, the scroll view will adjust the scroll position so that the first child that is currently visible and at or beyond minIndexForVisible will not change position. This is useful for lists that are loading content in both directions, e.g. a chat thread, where new messages coming in might otherwise cause the scroll position to jump. A value of 0 is common, but other values such as 1 can be used to skip loading spinners or other content that should not maintain position. The optional autoscrollToTopThreshold can be used to make the content automatically scroll to the top after making the adjustment if the user was within the threshold of the top before the adjustment was made. This is also useful for chat-like applications where you want to see new messages scroll into place, but not if the user has scrolled up a ways and it would be disruptive to scroll a bunch. Caveat 1: Reordering elements in the scrollview with this enabled will probably cause jumpiness and jank. It can be fixed, but there are currently no plans to do so. For now, don't re-order the content of any ScrollViews or Lists that use this feature. Caveat 2: This uses contentOffset and frame.origin in native code to compute visibility. Occlusion, transforms, and other complexity won't be taken into account as to whether content is \"visible\" or not."},{"name":"maximumZoomScale","type":"number | undefined","required":false,"description":"The maximum allowed zoom scale. The default value is 1.0."},{"name":"minimumZoomScale","type":"number | undefined","required":false,"description":"The minimum allowed zoom scale. The default value is 1.0."},{"name":"onScrollAnimationEnd","type":"(() => void) | undefined","required":false,"description":"Called when a scrolling animation ends."},{"name":"pinchGestureEnabled","type":"boolean | undefined","required":false,"description":"When true, ScrollView allows use of pinch gestures to zoom in and out. The default value is true."},{"name":"scrollEventThrottle","type":"number | undefined","required":false,"description":"Limits how often scroll events will be fired while scrolling, specified as a time interval in ms. This may be useful when expensive work is performed in response to scrolling. Values <= `16` will disable throttling, regardless of the refresh rate of the device."},{"name":"scrollIndicatorInsets","type":"Insets | undefined","required":false,"description":"The amount by which the scroll view indicators are inset from the edges of the scroll view. This should normally be set to the same value as the contentInset. Defaults to {0, 0, 0, 0}."},{"name":"scrollToOverflowEnabled","type":"boolean | undefined","required":false,"description":"When true, the scroll view can be programmatically scrolled beyond its content size. The default value is false."},{"name":"scrollsToTop","type":"boolean | undefined","required":false,"description":"When true the scroll view scrolls to top when the status bar is tapped. The default value is true."},{"name":"snapToAlignment","type":"\"start\" | \"end\" | \"center\" | undefined","required":false,"description":"When `snapToInterval` is set, `snapToAlignment` will define the relationship of the snapping to the scroll view. - `start` (the default) will align the snap at the left (horizontal) or top (vertical) - `center` will align the snap in the center - `end` will align the snap at the right (horizontal) or bottom (vertical)"},{"name":"onScrollToTop","type":"((event: NativeSyntheticEvent<NativeScrollEvent>) => void) | undefined","required":false,"description":"Fires when the scroll view scrolls to top after the status bar has been tapped"},{"name":"zoomScale","type":"number | undefined","required":false,"description":"The current scale of the scroll view content. The default value is 1.0."},{"name":"endFillColor","type":"ColorValue | undefined","required":false,"description":"Sometimes a scrollview takes up more space than its content fills. When this is the case, this prop will fill the rest of the scrollview with a color to avoid setting a background and creating unnecessary overdraw. This is an advanced optimization that is not needed in the general case."},{"name":"scrollPerfTag","type":"string | undefined","required":false,"description":"Tag used to log scroll performance on this scroll view. Will force momentum events to be turned on (see sendMomentumEvents). This doesn't do anything out of the box and you need to implement a custom native FpsListener for it to be useful."},{"name":"overScrollMode","type":"\"auto\" | \"always\" | \"never\" | undefined","required":false,"description":"Used to override default value of overScroll mode. Possible values: - 'auto' - Default value, allow a user to over-scroll this view only if the content is large enough to meaningfully scroll. - 'always' - Always allow a user to over-scroll this view. - 'never' - Never allow a user to over-scroll this view."},{"name":"nestedScrollEnabled","type":"boolean | undefined","required":false,"description":"Enables nested scrolling for Android API level 21+. Nested scrolling is supported by default on iOS."},{"name":"fadingEdgeLength","type":"number | { start: number; end: number; } | undefined","required":false,"description":"Controls the fading effect at the edges of the scroll content. A value greater than 0 will apply the fading effect, indicating more content is available to scroll. You can specify a single number to apply the same fading length to both edges. Alternatively, use an object with `start` and `end` properties to set different fading lengths for the start and end of the scroll content. The default value is 0."},{"name":"persistentScrollbar","type":"boolean | undefined","required":false,"description":"Causes the scrollbars not to turn transparent when they are not in use. The default value is false."},{"name":"scrollsChildToFocus","type":"boolean | undefined","required":false,"description":"When false, the ScrollView will not automatically scroll to a focused child when the child requests focus. This can be useful when you want to control the scroll position programmatically. The default value is true."},{"name":"ref","type":"Ref<ScrollView> | undefined","required":false,"description":"Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref)."},{"name":"key","type":"Key | null | undefined","required":false,"description":""}]}],"platformNotes":{"web":"A scrollable container for content larger than its bounds: vertical by default, `horizontal` for a row.\n\nUnlike a plain View, a ScrollView lets its children exceed its size and scroll. Style the frame with `style` and the inner content with `contentContainerStyle`. In Chromium and Firefox a scroller with nothing focusable inside it is a keyboard stop of its own, so arrow keys can scroll it; the browser draws its focus ring in the theme's `ring` colour, 2 px off the frame, like every kit control.","ios":"A scrollable container for content larger than its bounds: vertical by default, `horizontal` for a row.\n\nUnlike a plain View, a ScrollView lets its children exceed its size and scroll. Style the frame with `style` and the inner content with `contentContainerStyle`. In Chromium and Firefox a scroller with nothing focusable inside it is a keyboard stop of its own, so arrow keys can scroll it; the browser draws its focus ring in the theme's `ring` colour, 2 px off the frame, like every kit control.","android":"A scrollable container for content larger than its bounds: vertical by default, `horizontal` for a row.\n\nUnlike a plain View, a ScrollView lets its children exceed its size and scroll. Style the frame with `style` and the inner content with `contentContainerStyle`. In Chromium and Firefox a scroller with nothing focusable inside it is a keyboard stop of its own, so arrow keys can scroll it; the browser draws its focus ring in the theme's `ring` colour, 2 px off the frame, like every kit control."}},{"slug":"select","name":"Select","category":"atoms","description":"A single-choice dropdown field: a trigger showing the chosen value that opens a panel of options, styled to match Canvas inputs.","source":"src/atoms/select/select.md","url":"https://canvas.nannier.com/ai/4.2.0/components/select.md","humanUrl":"https://canvas.nannier.com/components/select","exports":["Select","SelectProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"SelectProps","props":[{"name":"value","type":"string | undefined","required":false,"description":"Controlled selection; omit for uncontrolled use. Empty shows the placeholder. With plain string options this is the option itself; with `SelectOption` objects it is the option's `value`, and the trigger shows its `label`."},{"name":"defaultValue","type":"string | undefined","required":false,"description":"Initial selection for uncontrolled use (a bare <Select options/> picks on its own)."},{"name":"options","type":"(string | SelectOption)[] | undefined","required":false,"description":"The selectable options: bare strings, or `{ value, label }` objects when the stored value differs from the text shown for it."},{"name":"label","type":"string | undefined","required":false,"description":"The field's persistent label. Its placement is platform-adaptive: iOS and web render it ABOVE the trigger; Android renders the Material 3 in-container FLOATING label (centered like a placeholder at rest, floating to the top once the menu opens or a value is selected). The label names the field for a11y."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible purpose for the trigger and option list. Overrides the visible label for assistive technology; otherwise the label or placeholder names them."},{"name":"inline","type":"boolean | undefined","required":false,"description":"Places the `label` as a LEADING cluster INSIDE the trigger row (a toolbar-style labeled select) instead of the persistent above/floating placement. Takes effect only alongside `label`. The inline label still names the trigger (accessibilityLabel / aria-labelledby) and shares its tap target, since it lives inside the trigger Pressable. Pairs with `fit` for a content-hugging toolbar cluster.","default":"false"},{"name":"required","type":"boolean | undefined","required":false,"description":"Marks the field as required and announces \"required\" with the trigger name. A visible label also gets a decorative destructive \"*\".","default":"false"},{"name":"icon","type":"boolean | undefined","required":false,"description":"Renders a leading globe glyph inside the trigger, indented so the value clears it.","default":"false"},{"name":"placeholder","type":"string | undefined","required":false,"description":"Prompt shown in the trigger when no value is selected.","default":"\"Select an option\""},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state of the option list; omit for uncontrolled use.","default":"false"},{"name":"defaultOpen","type":"boolean | undefined","required":false,"description":"Initial open state for uncontrolled use.","default":"false"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the open state changes (trigger press, select), in both modes."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Dims the control and blocks interaction.","default":"false"},{"name":"onSelect","type":"((option: string) => void) | undefined","required":false,"description":"Called with the chosen option's value when a row is pressed (both modes)."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the trigger pressable."},{"name":"dense","type":"boolean | undefined","required":false,"description":"Use the compact content-sized web field with a drawn disclosure chevron.","default":"false"},{"name":"eyebrow","type":"boolean | undefined","required":false,"description":"Use the compact application eyebrow above a web field.","default":"false"},{"name":"soft","type":"boolean | undefined","required":false,"description":"Use the brand field fill instead of the card fill.","default":"false"},{"name":"plainOptions","type":"boolean | undefined","required":false,"description":"Text-only options: selected ink and a pointer wash, without a check gutter.","default":"false"},{"name":"steadyPress","type":"boolean | undefined","required":false,"description":"Keep the resting fill and opacity during a press.","default":"false"},{"name":"combobox","type":"boolean | undefined","required":false,"description":"Announce a selection field as a combobox rather than a menu button.","default":"false"},{"name":"menuWidth","type":"number | undefined","required":false,"description":"Width of the floating menu, clamped within the overlay outlet."},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium field, matching Input's h-9).","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium field, matching Input's h-9).","default":"false","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0},{"name":"ref","type":"React.Ref<View>","required":false,"description":"Ref to the interactive trigger, preserving overlay measurement. Typed as a React Native View. On web, React Native Web exposes its DOM host; focus() and blur() move browser focus. Native host behavior depends on the platform and React Native version. Calling focus() does not activate the control or call accessibility focus APIs."},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":1},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":1}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default is the medium field, matching Input's h-9)."},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"A single-choice dropdown field: a trigger showing the chosen value that opens a\npanel of options, styled to match Canvas inputs.\n\nPass `label` (and `required`) to name the field:\niOS and web render the label\nabove the trigger, while Android floats the Material 3 in-container label once\nthe menu opens or a value is selected. On Android the trigger grows with the\nuser's text size, and a label longer than the trigger truncates on one line clear\nof the chevron while the trigger's accessible name stays the whole label.\nThe trigger fills the parent it is given;\na step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or\na Container step sets its measure.\n\nIn glass mode the option panel is a dense-layer glass card under the trigger (or\nabove it when it fits there); the trigger stays in place with its value and\nchevron, and the chosen value and expanded state commit immediately. Solid mode\npaints the skin's own panel.\n\nThe label also names the option list. Use `accessibilityLabel` to provide an explicit purpose when the visible label or placeholder is insufficient; it overrides both accessible names. A required field announces \"required\" with the button name and marks the option list as required. The selected value never replaces the field's purpose.\n\nPass `ref` to access the interactive trigger, preserving overlay measurement. Use `useRef<ComponentRef<typeof Select>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn web, the trigger is the Canvas v4 field: 40 pixels tall (32 small, 48 large)\non the sunken fill behind the `field-border` hairline, a 400 14-pixel value (13\nsmall) and a 16-pixel chevron that turns over while the list is open. The pointer\ndarkens the edge to the subtle ink, and keyboard focus or the open list rings it in\nthe accent with a 4-pixel halo. The list is a card 6 pixels under the trigger with\na 4-pixel inset, 34-pixel rows, the chosen row on the `muted` wash with a trailing\ncheck in the accent ink.\niOS keeps the pop-up button (a 44-point field with the\nup-and-down chevrons) and its menu, which marks the chosen row with a leading check;\nAndroid keeps the Material 3 exposed dropdown, whose menu marks the chosen row with\nits state layer alone.\n\nUse `dense eyebrow soft` for the compact application field on web: a 32-pixel\ntrigger with a 600 13-pixel value under a tracked uppercase eyebrow label at the\nkit’s 10-pixel reading floor, and 30-pixel rows. `plainOptions` removes the check\nand marks the chosen row with its wash alone; pointer hover uses the brand wash. `steadyPress` keeps the resting fill and\nopacity while pressed. `menuWidth` bounds the floating menu independently of the\nfield. `combobox` exposes the selection-field role. Native skins keep their\nplatform field anatomy and minimum touch targets.","ios":"A single-choice dropdown field: a trigger showing the chosen value that opens a\npanel of options, styled to match Canvas inputs.\n\nPass `label` (and `required`) to name the field:\niOS renders the label above the trigger.\nThe trigger fills the parent it is given;\na step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or\na Container step sets its measure.\n\nIn glass mode the option panel is a dense-layer glass card under the trigger (or\nabove it when it fits there); the trigger stays in place with its value and\nchevron, and the chosen value and expanded state commit immediately. Solid mode\npaints the skin's own panel.\n\nThe label also names the option list. Use `accessibilityLabel` to provide an explicit purpose when the visible label or placeholder is insufficient; it overrides both accessible names. A required field announces \"required\" with the button name and marks the option list as required. The selected value never replaces the field's purpose.\n\nPass `ref` to access the interactive trigger, preserving overlay measurement. Use `useRef<ComponentRef<typeof Select>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn web, the trigger is the Canvas v4 field: 40 pixels tall (32 small, 48 large)\non the sunken fill behind the `field-border` hairline, a 400 14-pixel value (13\nsmall) and a 16-pixel chevron that turns over while the list is open. The pointer\ndarkens the edge to the subtle ink, and keyboard focus or the open list rings it in\nthe accent with a 4-pixel halo. The list is a card 6 pixels under the trigger with\na 4-pixel inset, 34-pixel rows, the chosen row on the `muted` wash with a trailing\ncheck in the accent ink.\niOS keeps the pop-up button (a 44-point field with the up-and-down chevrons) and its menu, which marks the chosen row with a leading check.\n\nUse `dense eyebrow soft` for the compact application field on web: a 32-pixel\ntrigger with a 600 13-pixel value under a tracked uppercase eyebrow label at the\nkit’s 10-pixel reading floor, and 30-pixel rows. `plainOptions` removes the check\nand marks the chosen row with its wash alone; pointer hover uses the brand wash. `steadyPress` keeps the resting fill and\nopacity while pressed. `menuWidth` bounds the floating menu independently of the\nfield. `combobox` exposes the selection-field role. Native skins keep their\nplatform field anatomy and minimum touch targets.","android":"A single-choice dropdown field: a trigger showing the chosen value that opens a\npanel of options, styled to match Canvas inputs.\n\nPass `label` (and `required`) to name the field:\nAndroid floats the Material 3 in-container label once the menu opens or a value is selected. The trigger grows with the user's text size, and a label longer than the trigger truncates on one line clear of the chevron while the trigger's accessible name stays the whole label.\nThe trigger fills the parent it is given;\na step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or\na Container step sets its measure.\n\nIn glass mode the option panel is a dense-layer glass card under the trigger (or\nabove it when it fits there); the trigger stays in place with its value and\nchevron, and the chosen value and expanded state commit immediately. Solid mode\npaints the skin's own panel.\n\nThe label also names the option list. Use `accessibilityLabel` to provide an explicit purpose when the visible label or placeholder is insufficient; it overrides both accessible names. A required field announces \"required\" with the button name and marks the option list as required. The selected value never replaces the field's purpose.\n\nPass `ref` to access the interactive trigger, preserving overlay measurement. Use `useRef<ComponentRef<typeof Select>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn web, the trigger is the Canvas v4 field: 40 pixels tall (32 small, 48 large)\non the sunken fill behind the `field-border` hairline, a 400 14-pixel value (13\nsmall) and a 16-pixel chevron that turns over while the list is open. The pointer\ndarkens the edge to the subtle ink, and keyboard focus or the open list rings it in\nthe accent with a 4-pixel halo. The list is a card 6 pixels under the trigger with\na 4-pixel inset, 34-pixel rows, the chosen row on the `muted` wash with a trailing\ncheck in the accent ink.\nAndroid keeps the Material 3 exposed dropdown, whose menu marks the chosen row with its state layer alone.\n\nUse `dense eyebrow soft` for the compact application field on web: a 32-pixel\ntrigger with a 600 13-pixel value under a tracked uppercase eyebrow label at the\nkit’s 10-pixel reading floor, and 30-pixel rows. `plainOptions` removes the check\nand marks the chosen row with its wash alone; pointer hover uses the brand wash. `steadyPress` keeps the resting fill and\nopacity while pressed. `menuWidth` bounds the floating menu independently of the\nfield. `combobox` exposes the selection-field role. Native skins keep their\nplatform field anatomy and minimum touch targets."}},{"slug":"service-health-list","name":"ServiceHealthList","category":"charts","description":"Per-service status rows: a status dot (down > degraded > operational), the service name, an optional right-aligned `detail` such as an uptime percentage, and, when the item carries `periods`, an inline strip of its latest 14 periods beside the detail.","source":"src/charts/service-health-list/service-health-list.md","url":"https://canvas.nannier.com/ai/4.2.0/components/service-health-list.md","humanUrl":"https://canvas.nannier.com/components/service-health-list","exports":["ServiceHealthItem","ServiceHealthList","ServiceHealthListProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ServiceHealthListProps","props":[{"name":"items","type":"ServiceHealthItem[]","required":true,"description":"The services to render, in order."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the rows."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default row insets).","default":"false","group":0},{"name":"detailed","type":"boolean | undefined","required":false,"description":"Bordered status panel with full-width history strips and explicit status labels.","default":"false","group":0},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":0},{"name":"onPressItem","type":"((index: number) => void) | undefined","required":false,"description":"Rows become tappable drill-in targets (open the service) when set.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Density","pickOne":false,"note":"Density (omit for the default row insets)."}],"inherits":[]}],"platformNotes":{"web":"Per-service status rows: a status dot (down > degraded > operational), the service name, an optional right-aligned `detail` such as an uptime percentage, and, when the item carries `periods`, an inline strip of its latest 14 periods beside the detail.\n\nIt shares its strip renderer with UptimeBar, so the two never drift. `onPressItem` turns rows into drill-in buttons; `compact` tightens the rows; `plain` strips the card surface for nesting.\n\n`detailed` places the services in one bordered panel, spells out each status and shows its complete history in a separate full-width strip.","ios":"Per-service status rows: a status dot (down > degraded > operational), the service name, an optional right-aligned `detail` such as an uptime percentage, and, when the item carries `periods`, an inline strip of its latest 14 periods beside the detail.\n\nIt shares its strip renderer with UptimeBar, so the two never drift. `onPressItem` turns rows into drill-in buttons; `compact` tightens the rows; `plain` strips the card surface for nesting.\n\n`detailed` places the services in one bordered panel, spells out each status and shows its complete history in a separate full-width strip.","android":"Per-service status rows: a status dot (down > degraded > operational), the service name, an optional right-aligned `detail` such as an uptime percentage, and, when the item carries `periods`, an inline strip of its latest 14 periods beside the detail.\n\nIt shares its strip renderer with UptimeBar, so the two never drift. `onPressItem` turns rows into drill-in buttons; `compact` tightens the rows; `plain` strips the card surface for nesting.\n\n`detailed` places the services in one bordered panel, spells out each status and shows its complete history in a separate full-width strip."}},{"slug":"sidebar","name":"Sidebar","category":"organisms","description":"App navigation rail with collapsible sections and active highlighting. The sidebar on the left of this page is a thin adapter over this very `Sidebar` component: it feeds the docs' nav tree in and gets the same collapse, accordion, and active-highlight behavior back.","source":"src/organisms/sidebar/sidebar.md","url":"https://canvas.nannier.com/ai/4.2.0/components/sidebar.md","humanUrl":"https://canvas.nannier.com/components/sidebar","exports":["Sidebar","SidebarAccount","SidebarItem","SidebarProps","SidebarSection"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"SidebarProps","props":[{"name":"sections","type":"SidebarSection[] | undefined","required":false,"description":"Titled sections of nav rows. Use this or the flat `items` array."},{"name":"items","type":"SidebarItem[] | undefined","required":false,"description":"Flat list of nav rows, wrapped into a single untitled section."},{"name":"active","type":"string | number | undefined","required":false,"description":"The active row (CONTROLLED), by id, by label, or by flat index across all rows. Omit for uncontrolled use."},{"name":"defaultActive","type":"string | number | undefined","required":false,"description":"Initial active row for uncontrolled use (a bare sidebar moves the highlight on press)."},{"name":"onSelect","type":"((item: SidebarItem, index: number, event: GestureResponderEvent) => void) | undefined","required":false,"description":"Fired with the selected row and its flat index across all sections."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (pick one; default is the comfortable row).","default":"false","group":0},{"name":"bordered","type":"boolean | undefined","required":false,"description":"A rounded card inside the field hairline.","default":"false","group":1},{"name":"floating","type":"boolean | undefined","required":false,"description":"A rounded card lifted on the medium shadow (the bordered card natively).","default":"false","group":1},{"name":"embedded","type":"boolean | undefined","required":false,"description":"Navigation groups embedded in an app-owned rail: no frame, fill or width of its own and no scroll body (the host rail scrolls); the `header` and `footer` slots stack above and below the groups as plain blocks.","default":"false","group":1},{"name":"markers","type":"boolean | undefined","required":false,"description":"Trailing marker dots: the accent on the active row, the field hairline on a row of the current place (an item's `marked`, or every row of a `current` section).","default":"false","group":1},{"name":"collapsed","type":"boolean | undefined","required":false,"description":"Collapsed to the mini icon-rail (CONTROLLED). Omit for uncontrolled use.","default":"false","group":2},{"name":"defaultCollapsed","type":"boolean | undefined","required":false,"description":"Initial collapsed state for uncontrolled use (default expanded).","default":"false","group":2},{"name":"collapsible","type":"boolean | undefined","required":false,"description":"Show the collapse/expand toggle in the header slot.","default":"false","group":2},{"name":"onToggleCollapse","type":"(() => void) | undefined","required":false,"description":"Fired when the user taps the collapse/expand toggle.","group":2},{"name":"openSections","type":"string | string[] | undefined","required":false,"description":"Open collapsible sections (CONTROLLED), by section id/title. A single key by default, an array when `independentSections`. Pair with `onOpenSectionsChange`.","group":3},{"name":"defaultOpenSections","type":"string | string[] | undefined","required":false,"description":"Initial open sections for uncontrolled use.","group":3},{"name":"onOpenSectionsChange","type":"((value: string | string[]) => void) | undefined","required":false,"description":"Fired with the next open sections whenever a section header toggles.","group":3},{"name":"independentSections","type":"boolean | undefined","required":false,"description":"Allow more than one collapsible section open at once (default: one-open-at-a-time).","default":"false","group":3},{"name":"responsive","type":"boolean | undefined","required":false,"description":"Opt in to the responsive rail->drawer behavior. Off by default: a bare sidebar is the inline rail at every width, byte-identical to before.","default":"false","group":4},{"name":"drawer","type":"boolean | undefined","required":false,"description":"Always the drill-down drawer, at every width, never the inline rail: for an app shell whose only entry to the site tree is its own hamburger (a top app bar). Takes the same `open` / `onOpenChange` wiring as `responsive`, and wins over it.","default":"false","group":4},{"name":"open","type":"boolean | undefined","required":false,"description":"The narrow drawer's open state (CONTROLLED). The consumer wires its hamburger to this.","default":"false","group":4},{"name":"defaultOpen","type":"boolean | undefined","required":false,"description":"Initial open state for the uncontrolled narrow drawer (default closed).","default":"false","group":4},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the narrow drawer opens or closes (scrim tap, back, or a leaf selection).","group":4},{"name":"drawerBreakpoint","type":"BreakpointKey | undefined","required":false,"description":"The width at and below which `responsive` switches to the drawer (default `lg` = 1024).","group":4},{"name":"drawerWidth","type":"number | undefined","required":false,"description":"The narrow drawer panel width in px (default 288).","group":4},{"name":"drawerContentInsetBottom","type":"number | undefined","required":false,"description":"Extra bottom padding for the drawer's scrolling content, so its last rows clear persistent chrome painting over the drawer (e.g. a native bottom tab bar on Android).","group":4},{"name":"drawerRight","type":"boolean | undefined","required":false,"description":"Slide the drawer in from the end (right) edge instead of the start (left).","default":"false","group":5},{"name":"drawerTop","type":"boolean | undefined","required":false,"description":"Drop the drawer down from the top edge (a top sheet).","default":"false","group":5},{"name":"drawerBottom","type":"boolean | undefined","required":false,"description":"Raise the drawer up from the bottom edge (a bottom sheet).","default":"false","group":5},{"name":"header","type":"ReactNode | ((collapsed: boolean) => ReactNode)","required":false,"description":"Optional top slot (a brand lockup / logo). A render function receives the collapsed state so it can show a compact mark in the rail. When `header` or `footer` is set, the panel becomes a pinned header + scrolling body (+ footer).","group":5},{"name":"footer","type":"ReactNode | ((collapsed: boolean) => ReactNode)","required":false,"description":"Optional bottom slot (pinned below the scrolling sections). A render function receives the collapsed state so it can show a compact (icon-only) footer in the rail.","group":5},{"name":"account","type":"SidebarAccount | undefined","required":false,"description":"The signed-in account, drawn as a filled card pinned to the foot of the column: a small avatar beside the name and a detail line in the third ink. The collapsed rail keeps the avatar alone. It sits under the groups (above a `footer` slot), and in the drawer under the drill-down.","group":5},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"The name of the sidebar's navigation landmark, a short statement of what it navigates (\"Workspace\", \"Controls components\"). A sidebar is a navigation landmark on every platform, and a page holding two navigation landmarks needs a distinct name on each, so a landmark list can tell them apart. In the narrow `responsive` drawer it names the drawer. Omit it and the landmark stays unnamed, as before.","group":5},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":5},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook.","group":5}],"groups":[{"title":"Density","pickOne":true,"note":"Density (pick one; default is the comfortable row)."},{"title":"Frame","pickOne":true,"note":"Frame (pick one; default is the flush right-bordered column). `bordered` wins over `floating`."},{"title":"Collapse axis","pickOne":false,"note":"Collapse axis (the mini icon-rail)."},{"title":"Accordion open-state","pickOne":false,"note":"Accordion open-state (for `collapsible` sections; mirrors Accordion's value API)."},{"title":"Responsive drawer axis","pickOne":false,"note":"Responsive drawer axis: at and below `drawerBreakpoint` the sidebar renders as a start-edge (left, RTL-aware) DRILL-DOWN Drawer instead of the inline rail, opened by a consumer-owned hamburger. The rail is unchanged above the breakpoint."},{"title":"Responsive drawer EDGE axis","pickOne":false,"note":"Responsive drawer EDGE axis: which side the drawer slides from (default = the start/left edge). First match wins; pass none for the default left. Only applies in drawer mode."}],"inherits":[]}],"platformNotes":{"web":"App navigation rail with collapsible sections and active highlighting. The sidebar on the left of this page is a thin adapter over this very `Sidebar` component: it feeds the docs' nav tree in and gets the same collapse, accordion, and active-highlight behavior back.\n\nIn glass mode the active row paints a control-layer pane behind its icon, label\nand badge; the drill-down drawer keeps its own row treatment. Solid mode keeps\nthe skin's own row fill.\n\nOn the web a hovered row's wash (the palette's translucent `hover`) fades in over\n150 ms and back out when the pointer leaves, in the rail and the drill-down alike;\nthe pressed and active fills still switch at once, and Reduce Motion makes the wash\ninstant.\n\nAdd `responsive` to make it adapt across breakpoints: it stays the accordion rail on desktop, and at and below the `lg` breakpoint (1024px) it becomes a start-edge (left, RTL-aware) **navigation drawer** that drills through the same `sections` one level at a time (tap a group to slide in to its rows, back to return). Drive the drawer's open state with `open` / `onOpenChange` from your own hamburger button; the `header` and `footer` slots pin above and below the drill-down, just as in the rail. The drawer slides from the start (left) edge by default; `drawerRight`, `drawerTop`, and `drawerBottom` change which edge it slides in from. (This page's own left nav does exactly this: an accordion rail here, a drill-down drawer on a phone.)\n\nPass `drawer` instead when the shell's hamburger is the only way into the tree at every width (a top app bar on a phone and a tablet alike): the sidebar is then the drill-down drawer at every width and never the inline rail, with the same `open` / `onOpenChange` wiring. `drawer` wins over `responsive`.\n\nOn the web the sidebar takes the Canvas v4 rail: a 232px column on the sunken page\ntone, rows 36px tall at a 9px corner (30px at 8 with `compact`, the docs rail's\ndensity), 500 13px labels in the secondary ink, the active row on the accent's soft\nwash in the accent's text ink, and a mono uppercase eyebrow over each titled group.\niOS and Android keep their platform rows (the HIG capsule, the Material 3 pill) in the\nv4 colors.\n\n`markers` gives each row a trailing dot: the accent on the active row, and the field\nhairline on a row of the reader's current place, either one item with `marked: true`\nor every row of a section with `current: true`. A `current` section also sets its\neyebrow in the accent's text ink and its resting rows in the foreground ink, and a\nsection's `count` sits at the far end of its heading.\n\n`embedded` renders the navigation groups inside an app-owned rail: it inherits the\nrail's frame, fill, width and scroll, stacks its groups 16px apart, and renders the\n`header` and `footer` slots as plain blocks above and below them, so a filter field or\na heading row fits there. A framed sidebar's header grows past its 56px floor when its\ncontent is taller.\n\nA sidebar is a navigation landmark on every platform. Name it with `accessibilityLabel`,\na short statement of what it navigates such as \"Workspace\", so a screen reader's\nlandmark list can tell it apart; a page that holds more than one navigation landmark (a\nsidebar beside the app's top navigation, or two sidebars) needs a distinct name on each.\nIn the narrow `responsive` drawer the same name labels the drawer.","ios":"App navigation rail with collapsible sections and active highlighting. The sidebar on the left of this page is a thin adapter over this very `Sidebar` component: it feeds the docs' nav tree in and gets the same collapse, accordion, and active-highlight behavior back.\n\nIn glass mode the active row paints a control-layer pane behind its icon, label\nand badge; the drill-down drawer keeps its own row treatment. Solid mode keeps\nthe skin's own row fill.\n\nOn the web a hovered row's wash (the palette's translucent `hover`) fades in over\n150 ms and back out when the pointer leaves, in the rail and the drill-down alike;\nthe pressed and active fills still switch at once, and Reduce Motion makes the wash\ninstant.\n\nAdd `responsive` to make it adapt across breakpoints: it stays the accordion rail on desktop, and at and below the `lg` breakpoint (1024px) it becomes a start-edge (left, RTL-aware) **navigation drawer** that drills through the same `sections` one level at a time (tap a group to slide in to its rows, back to return). Drive the drawer's open state with `open` / `onOpenChange` from your own hamburger button; the `header` and `footer` slots pin above and below the drill-down, just as in the rail. The drawer slides from the start (left) edge by default; `drawerRight`, `drawerTop`, and `drawerBottom` change which edge it slides in from. (This page's own left nav does exactly this: an accordion rail here, a drill-down drawer on a phone.)\n\nPass `drawer` instead when the shell's hamburger is the only way into the tree at every width (a top app bar on a phone and a tablet alike): the sidebar is then the drill-down drawer at every width and never the inline rail, with the same `open` / `onOpenChange` wiring. `drawer` wins over `responsive`.\n\nOn the web the sidebar takes the Canvas v4 rail: a 232px column on the sunken page\ntone, rows 36px tall at a 9px corner (30px at 8 with `compact`, the docs rail's\ndensity), 500 13px labels in the secondary ink, the active row on the accent's soft\nwash in the accent's text ink, and a mono uppercase eyebrow over each titled group.\niOS keeps its platform rows (the HIG capsule) in the v4 colors.\n\n`markers` gives each row a trailing dot: the accent on the active row, and the field\nhairline on a row of the reader's current place, either one item with `marked: true`\nor every row of a section with `current: true`. A `current` section also sets its\neyebrow in the accent's text ink and its resting rows in the foreground ink, and a\nsection's `count` sits at the far end of its heading.\n\n`embedded` renders the navigation groups inside an app-owned rail: it inherits the\nrail's frame, fill, width and scroll, stacks its groups 16px apart, and renders the\n`header` and `footer` slots as plain blocks above and below them, so a filter field or\na heading row fits there. A framed sidebar's header grows past its 56px floor when its\ncontent is taller.\n\nA sidebar is a navigation landmark on every platform. Name it with `accessibilityLabel`,\na short statement of what it navigates such as \"Workspace\", so a screen reader's\nlandmark list can tell it apart; a page that holds more than one navigation landmark (a\nsidebar beside the app's top navigation, or two sidebars) needs a distinct name on each.\nIn the narrow `responsive` drawer the same name labels the drawer.","android":"App navigation rail with collapsible sections and active highlighting. The sidebar on the left of this page is a thin adapter over this very `Sidebar` component: it feeds the docs' nav tree in and gets the same collapse, accordion, and active-highlight behavior back.\n\nIn glass mode the active row paints a control-layer pane behind its icon, label\nand badge; the drill-down drawer keeps its own row treatment. Solid mode keeps\nthe skin's own row fill.\n\nOn the web a hovered row's wash (the palette's translucent `hover`) fades in over\n150 ms and back out when the pointer leaves, in the rail and the drill-down alike;\nthe pressed and active fills still switch at once, and Reduce Motion makes the wash\ninstant.\n\nAdd `responsive` to make it adapt across breakpoints: it stays the accordion rail on desktop, and at and below the `lg` breakpoint (1024px) it becomes a start-edge (left, RTL-aware) **navigation drawer** that drills through the same `sections` one level at a time (tap a group to slide in to its rows, back to return). Drive the drawer's open state with `open` / `onOpenChange` from your own hamburger button; the `header` and `footer` slots pin above and below the drill-down, just as in the rail. The drawer slides from the start (left) edge by default; `drawerRight`, `drawerTop`, and `drawerBottom` change which edge it slides in from. (This page's own left nav does exactly this: an accordion rail here, a drill-down drawer on a phone.)\n\nPass `drawer` instead when the shell's hamburger is the only way into the tree at every width (a top app bar on a phone and a tablet alike): the sidebar is then the drill-down drawer at every width and never the inline rail, with the same `open` / `onOpenChange` wiring. `drawer` wins over `responsive`.\n\nOn the web the sidebar takes the Canvas v4 rail: a 232px column on the sunken page\ntone, rows 36px tall at a 9px corner (30px at 8 with `compact`, the docs rail's\ndensity), 500 13px labels in the secondary ink, the active row on the accent's soft\nwash in the accent's text ink, and a mono uppercase eyebrow over each titled group.\nAndroid keeps its platform rows (the Material 3 pill) in the v4 colors.\n\n`markers` gives each row a trailing dot: the accent on the active row, and the field\nhairline on a row of the reader's current place, either one item with `marked: true`\nor every row of a section with `current: true`. A `current` section also sets its\neyebrow in the accent's text ink and its resting rows in the foreground ink, and a\nsection's `count` sits at the far end of its heading.\n\n`embedded` renders the navigation groups inside an app-owned rail: it inherits the\nrail's frame, fill, width and scroll, stacks its groups 16px apart, and renders the\n`header` and `footer` slots as plain blocks above and below them, so a filter field or\na heading row fits there. A framed sidebar's header grows past its 56px floor when its\ncontent is taller.\n\nA sidebar is a navigation landmark on every platform. Name it with `accessibilityLabel`,\na short statement of what it navigates such as \"Workspace\", so a screen reader's\nlandmark list can tell it apart; a page that holds more than one navigation landmark (a\nsidebar beside the app's top navigation, or two sidebars) needs a distinct name on each.\nIn the narrow `responsive` drawer the same name labels the drawer."}},{"slug":"skeleton","name":"Skeleton","category":"atoms","description":"Placeholders for loading content.","source":"src/atoms/skeleton/skeleton.md","url":"https://canvas.nannier.com/ai/4.2.0/components/skeleton.md","humanUrl":"https://canvas.nannier.com/components/skeleton","exports":["Skeleton","SkeletonProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"SkeletonProps","props":[{"name":"text","type":"boolean | undefined","required":false,"description":"Shape (pick one; default is a single text line).","default":"false","group":0},{"name":"avatar","type":"boolean | undefined","required":false,"description":"Shape (pick one; default is a single text line).","default":"false","group":0},{"name":"button","type":"boolean | undefined","required":false,"description":"Shape (pick one; default is a single text line).","default":"false","group":0},{"name":"card","type":"boolean | undefined","required":false,"description":"Shape (pick one; default is a single text line).","default":"false","group":0},{"name":"list","type":"boolean | undefined","required":false,"description":"Shape (pick one; default is a single text line).","default":"false","group":0},{"name":"table","type":"boolean | undefined","required":false,"description":"Shape (pick one; default is a single text line).","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one). Scales the line height and the avatar/button footprint.","default":"false","group":1},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one). Scales the line height and the avatar/button footprint.","default":"false","group":1},{"name":"long","type":"boolean | undefined","required":false,"description":"A line that runs most of the way across (80%), a mid-paragraph line.","default":"false","group":2},{"name":"short","type":"boolean | undefined","required":false,"description":"A short trailing line (60%), the last line of a paragraph.","default":"false","group":2},{"name":"animate","type":"boolean | undefined","required":false,"description":"Subtle opacity pulse while content loads.","default":"false","group":2},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Screen-reader label announced for the loading placeholder. Defaults to \"Loading\". The placeholder carries a `progressbar` role + busy state so assistive tech announces the pending content (matching Spinner / Progress).","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":2}],"groups":[{"title":"Shape","pickOne":true,"note":"Shape (pick one; default is a single text line)."},{"title":"Size","pickOne":true,"note":"Size (pick one). Scales the line height and the avatar/button footprint."},{"title":"Line length","pickOne":true,"note":"Line length (text shape only; pick one; default spans the parent). A paragraph of placeholder lines varies them so the block reads like wrapped prose."}],"inherits":[]}],"platformNotes":{"web":"Placeholders for loading content.","ios":"Placeholders for loading content.","android":"Placeholders for loading content."}},{"slug":"slider","name":"Slider","category":"atoms","description":"Drag (or tap) along a track to pick a value in a range; the keyboard and screen readers step it too. Controlled by `value`, bounded by `min` / `max`, and snapped to `step`.","source":"src/atoms/slider/slider.md","url":"https://canvas.nannier.com/ai/4.2.0/components/slider.md","humanUrl":"https://canvas.nannier.com/components/slider","exports":["Slider","SliderProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"SliderProps","props":[{"name":"value","type":"number | undefined","required":false,"description":"Controlled value; omit for uncontrolled use. The thumb sits at this value (clamped to [min, max])."},{"name":"defaultValue","type":"number | undefined","required":false,"description":"Initial value for uncontrolled use (a bare <Slider/> drags out of the box). Default `min`."},{"name":"min","type":"number | undefined","required":false,"description":"Lower bound of the range. Default 0.","default":"0"},{"name":"max","type":"number | undefined","required":false,"description":"Upper bound of the range. Default 100.","default":"100"},{"name":"step","type":"number | undefined","required":false,"description":"Snap increment. Default 1. Set to a fraction for finer control.","default":"1"},{"name":"onChange","type":"((value: number) => void) | undefined","required":false,"description":"Fired with the next (clamped, snapped) value as the thumb is dragged or the track tapped (both modes)."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the slider container."},{"name":"children","type":"ReactNode","required":false,"description":"The title line, rendered ABOVE the track (a slider's label sits above the rail, not beside it). Supplying it builds the component-owned header so the caller never hand-composes a Column + Typography above a bare slider, and the visible title also names the control for assistive tech (see `accessibilityLabel`)."},{"name":"description","type":"ReactNode","required":false,"description":"Optional muted secondary line rendered under the title, for a hint or unit note."},{"name":"showValue","type":"boolean | undefined","required":false,"description":"Render the live current value (the same value the thumb sits at) as a trailing readout on the title line, right-aligned. With no title it still renders the value as a standalone trailing readout above the track. The number tracks the drag in real time and uses tabular figures so it does not jitter.","default":"false"},{"name":"percent","type":"boolean | undefined","required":false,"description":"The value is a percentage: the `showValue` readout prints it with a percent sign (\"62%\") and assistive tech hears it so. Pair with the default 0 to 100 range.","default":"false"},{"name":"scale","type":"boolean | undefined","required":false,"description":"A scale under the track: the minimum, the middle and the maximum, spread across the track's width in the small mono meta type, 8 px below the rail.","default":"false"},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the standard track + thumb).","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the standard track + thumb).","default":"false","group":0},{"name":"disabled","type":"boolean | undefined","required":false,"description":"State.","default":"false","group":1},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the slider (e.g. \"Volume\").","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Extra style on the slider container, applied last.","group":1},{"name":"ref","type":"React.Ref<View>","required":false,"description":"Ref to the interactive adjustable track, including when a header is shown. Typed as a React Native View. On web, React Native Web exposes its DOM host; focus() and blur() move browser focus. Native host behavior depends on the platform and React Native version. Calling focus() does not activate the control or call accessibility focus APIs."},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":2}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default is the standard track + thumb)."},{"title":"State","pickOne":false},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"Drag (or tap) along a track to pick a value in a range; the keyboard and screen readers step it too. Controlled by `value`, bounded by `min` / `max`, and snapped to `step`.\n\nLike the other input-like controls, a slider fills the parent it is given; a step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container step sets its measure.\n\nPass `ref` to access the interactive adjustable track, including when a header is shown. Use `useRef<ComponentRef<typeof Slider>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nName the setting with string `children`, or pass `accessibilityLabel` when the visible title is omitted or contains rich content.","ios":"Drag (or tap) along a track to pick a value in a range; the keyboard and screen readers step it too. Controlled by `value`, bounded by `min` / `max`, and snapped to `step`.\n\nLike the other input-like controls, a slider fills the parent it is given; a step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container step sets its measure.\n\nPass `ref` to access the interactive adjustable track, including when a header is shown. Use `useRef<ComponentRef<typeof Slider>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nName the setting with string `children`, or pass `accessibilityLabel` when the visible title is omitted or contains rich content.","android":"Drag (or tap) along a track to pick a value in a range; the keyboard and screen readers step it too. Controlled by `value`, bounded by `min` / `max`, and snapped to `step`.\n\nLike the other input-like controls, a slider fills the parent it is given; a step of its own (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container step sets its measure.\n\nPass `ref` to access the interactive adjustable track, including when a header is shown. Use `useRef<ComponentRef<typeof Slider>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nName the setting with string `children`, or pass `accessibilityLabel` when the visible title is omitted or contains rich content."}},{"slug":"sparkline","name":"Sparkline","category":"charts","description":"A compact trend strip: a row of thin bars whose heights track a series of values, with the series in a soft wash of the tone and the latest bar in the full accent. Pass `values` and it sizes each bar against the series max and paints the tone, so no call site hand-composes a row of `flexGrow` + `height` + `backgroundColor` Views to draw an inline trend on a stat card or dashboard.","source":"src/charts/sparkline/sparkline.md","url":"https://canvas.nannier.com/ai/4.2.0/components/sparkline.md","humanUrl":"https://canvas.nannier.com/components/sparkline","exports":["Sparkline","SparklineProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"SparklineProps","props":[{"name":"values","type":"number[]","required":true,"description":"The series to plot; each value becomes one bar, sized against the max."},{"name":"primary","type":"boolean | undefined","required":false,"description":"Tone (pick one; default `primary`). Colors the marks.","default":"false","group":0},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (pick one; default `primary`). Colors the marks.","default":"false","group":0},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (pick one; default `primary`). Colors the marks.","default":"false","group":0},{"name":"muted","type":"boolean | undefined","required":false,"description":"Tone (pick one; default `primary`). Colors the marks.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Height (pick one; default medium).","default":"false","group":1},{"name":"tall","type":"boolean | undefined","required":false,"description":"Height (pick one; default medium).","default":"false","group":1},{"name":"line","type":"boolean | undefined","required":false,"description":"A continuous 2px trend line with an area wash and end marker, instead of the bar strip.","default":"false","group":1},{"name":"track","type":"boolean | undefined","required":false,"description":"Paint the plot area with the muted track, giving the strip a visible frame. Two things it buys: a flat or all-zero series reads as a chart sitting at zero rather than as one that failed to load, and a row of strips scans evenly because every one of them holds the same band whatever its data. Use it wherever strips sit side by side (a Stats row); a lone sparkline inside running text is usually better without.","default":"false","group":1},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible summary (e.g. \"requests, last 11 days\").","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"For sizing/composition only (e.g. maxWidth); not a styling escape hatch.","group":1}],"groups":[{"title":"Tone","pickOne":true,"note":"Tone (pick one; default `primary`). Colors the marks."},{"title":"Height","pickOne":true,"note":"Height (pick one; default medium)."}],"inherits":[]}],"platformNotes":{"web":"A compact trend strip: a row of thin bars whose heights track a series of values,\nwith the series in a soft wash of the tone and the latest bar in the full accent.\nPass `values` and it sizes each bar against the series max and paints the tone, so\nno call site hand-composes a row of `flexGrow` + `height` + `backgroundColor`\nViews to draw an inline trend on a stat card or dashboard.","ios":"A compact trend strip: a row of thin bars whose heights track a series of values,\nwith the series in a soft wash of the tone and the latest bar in the full accent.\nPass `values` and it sizes each bar against the series max and paints the tone, so\nno call site hand-composes a row of `flexGrow` + `height` + `backgroundColor`\nViews to draw an inline trend on a stat card or dashboard.","android":"A compact trend strip: a row of thin bars whose heights track a series of values,\nwith the series in a soft wash of the tone and the latest bar in the full accent.\nPass `values` and it sizes each bar against the series max and paints the tone, so\nno call site hand-composes a row of `flexGrow` + `height` + `backgroundColor`\nViews to draw an inline trend on a stat card or dashboard."}},{"slug":"spinner","name":"Spinner","category":"atoms","description":"Animated loading spinner in three sizes.","source":"src/atoms/spinner/spinner.md","url":"https://canvas.nannier.com/ai/4.2.0/components/spinner.md","humanUrl":"https://canvas.nannier.com/components/spinner","exports":["Spinner","SpinnerProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"SpinnerProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"Optional label rendered beside (or below) the indicator in the spinner's 500 14 foreground type. Supplying it turns the bare indicator into a component-owned loading pairing, so the caller never hand-composes a Row/Column + Typography beside a <Spinner />. A bare <Spinner /> (no children) is unchanged."},{"name":"description","type":"ReactNode","required":false,"description":"Optional muted secondary line rendered under the label (a progress hint, an ETA). Stacks under the label inside the control."},{"name":"stacked","type":"boolean | undefined","required":false,"description":"Layout axis for the label. Omitted/false: the label sits BESIDE the indicator in a snug row (the inline pairing). `stacked`: the indicator sits over a centered label column (the panel / section-loader form).","default":"false"},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default sits between small and large).","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default sits between small and large).","default":"false","group":0},{"name":"primary","type":"boolean | undefined","required":false,"description":"Tone (pick one; default is the accent).","default":"false","group":1},{"name":"muted","type":"boolean | undefined","required":false,"description":"Tone (pick one; default is the accent).","default":"false","group":1},{"name":"foreground","type":"boolean | undefined","required":false,"description":"Tone (pick one; default is the accent).","default":"false","group":1},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible description of what is loading. When absent, a string label (children) becomes the accessible name; when neither is present it defaults to \"Loading\".","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default sits between small and large)."},{"title":"Tone","pickOne":true,"note":"Tone (pick one; default is the accent)."}],"inherits":[]}],"platformNotes":{"web":"Animated loading spinner in three sizes.","ios":"Animated loading spinner in three sizes.","android":"Animated loading spinner in three sizes."}},{"slug":"stacked-bar","name":"StackedBar","category":"charts","description":"One proportional horizontal bar split into colored segments (the `chart-1`..`chart-8` tokens in fixed order), with a legend carrying each segment's label and share.","source":"src/charts/stacked-bar/stacked-bar.md","url":"https://canvas.nannier.com/ai/4.2.0/components/stacked-bar.md","humanUrl":"https://canvas.nannier.com/components/stacked-bar","exports":["StackedBar","StackedBarProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"StackedBarProps","props":[{"name":"segments","type":"StackedSegment[]","required":true,"description":""},{"name":"label","type":"string | undefined","required":false,"description":"What the bar measures (e.g. \"Traffic sources\"); leads the accessible name."},{"name":"hideLegend","type":"boolean | undefined","required":false,"description":"Hide the legend (the labelled dots below the bar).","default":"false"},{"name":"detailed","type":"boolean | undefined","required":false,"description":"A two-column legend with separate right-aligned share readouts.","default":"false"},{"name":"legendSegments","type":"StackedSegment[] | undefined","required":false,"description":"The series to identify in a shared comparison legend. Defaults to this strip."},{"name":"track","type":"boolean | undefined","required":false,"description":"Paint the unfilled remainder as a muted rail, so a bar whose segments sum to zero still reads as a bar rather than as blank space. A composition of nothing (an empty queue, a metric at zero) is a real state to draw, and without the rail it draws as an absence.","default":"false"},{"name":"tall","type":"boolean | undefined","required":false,"description":"A 24 px strip instead of the default 8 px pill; capacity strips use 14 px bands.","default":"false"},{"name":"subtle","type":"boolean | undefined","required":false,"description":"Draw the segments as washes of their ramp colours rather than at full strength. For a bar that supports a headline rather than being one (the strip under a metric's value), where a solid bar outweighs everything around it.","default":"false"},{"name":"max","type":"number | undefined","required":false,"description":"The capacity the segments are shares of (100 GB of storage): each segment is its value over `max`, and the room left is drawn as one remainder segment on the raised surface fill, left out of the legend. Omit to split the strip by the segments' own total. A `max` under the segments' total is ignored."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"LayoutStyle","required":false,"description":"For sizing/composition only."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"One proportional horizontal bar split into colored segments (the `chart-1`..`chart-8` tokens in fixed order), with a legend carrying each segment's label and share.","ios":"One proportional horizontal bar split into colored segments (the `chart-1`..`chart-8` tokens in fixed order), with a legend carrying each segment's label and share.","android":"One proportional horizontal bar split into colored segments (the `chart-1`..`chart-8` tokens in fixed order), with a legend carrying each segment's label and share."}},{"slug":"stacked-lists","name":"StackedList","category":"molecules","description":"Vertical lists with avatar, two-line items, and trailing metadata. Used for contacts, activity feeds, and data previews.","source":"src/molecules/stacked-lists/stacked-lists.md","url":"https://canvas.nannier.com/ai/4.2.0/components/stacked-lists.md","humanUrl":"https://canvas.nannier.com/components/stacked-lists","exports":["StackedList","StackedListItem","StackedListMove","StackedListProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"StackedListProps","props":[{"name":"items","type":"StackedListItem[] | undefined","required":false,"description":"Rows to render."},{"name":"title","type":"ReactNode","required":false,"description":"Optional header title; shown above the rows, separated by a rule. It also names the list for assistive tech (\"Team, list, 12 items\")."},{"name":"label","type":"string | undefined","required":false,"description":"The list's accessible name when it has no `title` (a `title` names the list, and wins when both are set). A screen reader announces it with the list. A `title` that is not a string names the list on the web only, and `label` then names it on iOS and Android. A `virtualized` list needs a name: on the web its scroller is a keyboard stop while the rows overflow, and Chromium names an unnamed stop from the text of every row it has rendered."},{"name":"action","type":"ReactNode","required":false,"description":"Trailing header content (e.g. an action button); only shown with a title. Takes precedence over `addAction` when both are supplied."},{"name":"addAction","type":"string | undefined","required":false,"description":"Convenience header action: renders a small outlined button with a leading plus icon and this label (e.g. \"Add\"). Only shown with a title and when `action` is not set. Serializable, so the playground can drive it."},{"name":"rowMenu","type":"boolean | undefined","required":false,"description":"Appends a trailing ghost overflow (\"...\") action-menu button to every row. Press is reported through `onPressItemMenu`.","default":"false"},{"name":"onPressItem","type":"((index: number, event: GestureResponderEvent) => void) | undefined","required":false,"description":"Press handler for a row, by index. Only used in the `clickable` variant."},{"name":"onPressItemMenu","type":"((index: number, event: GestureResponderEvent) => void) | undefined","required":false,"description":"Press handler for a row's overflow menu, by index. Used with `rowMenu`."},{"name":"clickable","type":"boolean | undefined","required":false,"description":"Variant (pick one; default is the plain two-line list).","default":"false","group":0},{"name":"card","type":"boolean | undefined","required":false,"description":"Variant (pick one; default is the plain two-line list).","default":"false","group":0},{"name":"flush","type":"boolean | undefined","required":false,"description":"Divider modifier: rows are ruled by default; `flush` removes the hairlines.","default":"false","group":1},{"name":"virtualized","type":"boolean | undefined","required":false,"description":"Render the rows through a windowed `FlatList` instead of mounting every row up front, for large lists. Give the list a bounded height (via `style`, e.g. `{ maxHeight: 400 }`) so it can scroll; without one it warns and renders eagerly anyway. Default (omitted) mounts all rows, unchanged. Ignored (with a dev warning) when `reorderable` is set: windowing unmounts off-screen rows, which would leave them undraggable and unmeasurable mid-drag. On the web, while the rows overflow, the windowed list is a keyboard tab stop the keyboard can scroll, and the list's frame draws the focus ring while it has keyboard focus.","default":"false","group":1},{"name":"reorderable","type":"boolean | undefined","required":false,"description":"Make the rows reorderable: each row gains a leading drag grip (keyboard- and screen-reader-operable: Space grabs, the arrow keys move, Space drops, Escape cancels) and the list becomes one drop zone. The order stays CONTROLLED by the consumer's `items` array: a drop only reports the move through `onReorder`, never reorders internally.","default":"false","group":1},{"name":"onReorder","type":"((move: StackedListMove) => void) | undefined","required":false,"description":"Fired on drop with the computed move (row id, from/to index, new neighbors).","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Variant","pickOne":true,"note":"Variant (pick one; default is the plain two-line list)."},{"title":"Divider modifier","pickOne":false,"note":"Divider modifier: rows are ruled by default; `flush` removes the hairlines."}],"inherits":[]}],"platformNotes":{"web":"Vertical lists with avatar, two-line items, and trailing metadata. Used for\ncontacts, activity feeds, and data previews.\n\nRows can carry a per-item `trailing` slot for an inline control, and\n`reorderable` adds a leading drag grip per row (keyboard- and\nscreen-reader-operable) that reports each drop through `onReorder` while the\norder stays controlled by your `items` array.\n\nThe rows are a list, as in Tailwind UI, and each row is one of its items: a\nscreen reader announces the list with its number of rows and moves through it\nrow by row. A clickable row's button sits inside its item. The header `title`\nnames the list; a list without a title takes its name from `label`.\n\nA `virtualized` list with a bounded height scrolls its rows in a list of its\nown. On the web, while those rows overflow, that list is a keyboard tab stop\n(after the header's action, and before the rows' own buttons when they have\nany), the keyboard can scroll it, and while it has keyboard focus the list's\ncard, or a plain list's frame, draws the theme's focus ring. Only the rows near\nits viewport are mounted, and each says where it sits in the whole list, so a\nscreen reader still counts every row. Give a windowed list a `title` or a\n`label`: focused, a list with no name is named in Chromium from the text of\nevery row it has rendered, so the kit warns in development when it has neither.","ios":"Vertical lists with avatar, two-line items, and trailing metadata. Used for\ncontacts, activity feeds, and data previews.\n\nRows can carry a per-item `trailing` slot for an inline control, and\n`reorderable` adds a leading drag grip per row (keyboard- and\nscreen-reader-operable) that reports each drop through `onReorder` while the\norder stays controlled by your `items` array.\n\nThe rows are a list, as in Tailwind UI, and each row is one of its items: a\nscreen reader announces the list with its number of rows and moves through it\nrow by row. A clickable row's button sits inside its item. The header `title`\nnames the list; a list without a title takes its name from `label`.\n\nA `virtualized` list with a bounded height scrolls its rows in a list of its\nown. On the web, while those rows overflow, that list is a keyboard tab stop\n(after the header's action, and before the rows' own buttons when they have\nany), the keyboard can scroll it, and while it has keyboard focus the list's\ncard, or a plain list's frame, draws the theme's focus ring. Only the rows near\nits viewport are mounted, and each says where it sits in the whole list, so a\nscreen reader still counts every row. Give a windowed list a `title` or a\n`label`: focused, a list with no name is named in Chromium from the text of\nevery row it has rendered, so the kit warns in development when it has neither.","android":"Vertical lists with avatar, two-line items, and trailing metadata. Used for\ncontacts, activity feeds, and data previews.\n\nRows can carry a per-item `trailing` slot for an inline control, and\n`reorderable` adds a leading drag grip per row (keyboard- and\nscreen-reader-operable) that reports each drop through `onReorder` while the\norder stays controlled by your `items` array.\n\nThe rows are a list, as in Tailwind UI, and each row is one of its items: a\nscreen reader announces the list with its number of rows and moves through it\nrow by row. A clickable row's button sits inside its item. The header `title`\nnames the list; a list without a title takes its name from `label`.\n\nA `virtualized` list with a bounded height scrolls its rows in a list of its\nown. On the web, while those rows overflow, that list is a keyboard tab stop\n(after the header's action, and before the rows' own buttons when they have\nany), the keyboard can scroll it, and while it has keyboard focus the list's\ncard, or a plain list's frame, draws the theme's focus ring. Only the rows near\nits viewport are mounted, and each says where it sits in the whole list, so a\nscreen reader still counts every row. Give a windowed list a `title` or a\n`label`: focused, a list with no name is named in Chromium from the text of\nevery row it has rendered, so the kit warns in development when it has neither."}},{"slug":"stats","name":"Stats","category":"molecules","description":"Single value, grouped row, with sparkline, with comparison. Used for dashboards and overview pages.","source":"src/molecules/stats/stats.md","url":"https://canvas.nannier.com/ai/4.2.0/components/stats.md","humanUrl":"https://canvas.nannier.com/components/stats","exports":["StatItem","Stats","StatsProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"StatsProps","props":[{"name":"items","type":"StatItem[]","required":true,"description":"The metrics to render, in order."},{"name":"plain","type":"boolean | undefined","required":false,"description":"Borderless metric stacks on a shared surface, for nesting inside a card.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"Dense value-first tile for a navigation rail: a 12px inset and a 20px headline.","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Value-first dashboard tile with a 36px headline.","default":"false","group":0},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the metrics (mainly for the plain surface).","group":0},{"name":"framed","type":"boolean | undefined","required":false,"description":"Draw every metric's strip on a muted track, in one bounded band. For a ROW of metrics, where the strips are read against each other. Without it each strip draws only its marks, so a metric with a quiet series shows a near-empty band beside one with a full bar and the row's densities range from blank to solid with nothing tying them together; the eye lands on the fullest tile rather than scanning the row. The track gives every strip the same frame whatever its data, so a flat series reads as a chart sitting at zero and the fill is the only thing that varies.","default":"false","group":0},{"name":"onPressItem","type":"((index: number) => void) | undefined","required":false,"description":"Make each metric a tappable target (drill into the underlying detail). When set, every metric renders as a Pressable with a button role and a pressed affordance, so a tappable stat needs no hand-rolled Pressable.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Surface","pickOne":true,"note":"Surface (pick one; default is bordered cards)."}],"inherits":[]}],"platformNotes":{"web":"Single value, grouped row, with sparkline, with comparison. Used for dashboards and overview pages.\n\nUnder the value each tile can draw one strip: its trend (`spark`) or its composition (`share`). Both reserve the same height, so a row that mixes them keeps one card height and no tile is left half empty. `framed` puts every strip on a muted track, which is what makes a ROW of them scan evenly.\n\nThe metrics sit edge to edge inside one bordered surface, a hairline between each: a 16px\ninset, a 13px label, a 28px figure and a 12px delta led by its direction arrow. `framed`\nseparates them into tiles 12px apart. A trend draws as a small line beside the figure and\na composition as a thin bar over its legend. `compact` renders value-first rail tiles with\na 12px inset and 20px figures; `large` renders 36px dashboard headlines; compact wins if\nboth are set. Each item may include a muted `description`.","ios":"Single value, grouped row, with sparkline, with comparison. Used for dashboards and overview pages.\n\nUnder the value each tile can draw one strip: its trend (`spark`) or its composition (`share`). Both reserve the same height, so a row that mixes them keeps one card height and no tile is left half empty. `framed` puts every strip on a muted track, which is what makes a ROW of them scan evenly.\n\nThe metrics sit edge to edge inside one bordered surface, a hairline between each: a 16px\ninset, a 13px label, a 28px figure and a 12px delta led by its direction arrow. `framed`\nseparates them into tiles 12px apart. A trend draws as a small line beside the figure and\na composition as a thin bar over its legend. `compact` renders value-first rail tiles with\na 12px inset and 20px figures; `large` renders 36px dashboard headlines; compact wins if\nboth are set. Each item may include a muted `description`.","android":"Single value, grouped row, with sparkline, with comparison. Used for dashboards and overview pages.\n\nUnder the value each tile can draw one strip: its trend (`spark`) or its composition (`share`). Both reserve the same height, so a row that mixes them keeps one card height and no tile is left half empty. `framed` puts every strip on a muted track, which is what makes a ROW of them scan evenly.\n\nThe metrics sit edge to edge inside one bordered surface, a hairline between each: a 16px\ninset, a 13px label, a 28px figure and a 12px delta led by its direction arrow. `framed`\nseparates them into tiles 12px apart. A trend draws as a small line beside the figure and\na composition as a thin bar over its legend. `compact` renders value-first rail tiles with\na 12px inset and 20px figures; `large` renders 36px dashboard headlines; compact wins if\nboth are set. Each item may include a muted `description`."}},{"slug":"stepper","name":"Stepper","category":"atoms","description":"Increment, decrement, or type a number in a bounded range. A − button, an editable numeric center field, and a + button, controlled by `value` and clamped to `min` / `max` by `step`. This is the ± numeric control (the iOS UIStepper idiom); for a multi-step progress indicator see Steps.","source":"src/atoms/stepper/stepper.md","url":"https://canvas.nannier.com/ai/4.2.0/components/stepper.md","humanUrl":"https://canvas.nannier.com/components/stepper","exports":["Stepper","StepperProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"StepperProps","props":[{"name":"value","type":"number | undefined","required":false,"description":"Controlled numeric value (clamped to [min, max] for display); omit for uncontrolled use."},{"name":"defaultValue","type":"number | undefined","required":false,"description":"Initial value for uncontrolled use (a bare <Stepper /> steps out of the box). Default `min`."},{"name":"onChange","type":"((next: number) => void) | undefined","required":false,"description":"Fired with the next clamped value when buttons, adjustment keys, or direct entry change it (both modes)."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the group container."},{"name":"min","type":"number | undefined","required":false,"description":"Lower bound. Default 0. The − button disables when value <= min.","default":"0"},{"name":"max","type":"number | undefined","required":false,"description":"Upper bound. Default Number.MAX_SAFE_INTEGER. The + button disables when value >= max."},{"name":"step","type":"number | undefined","required":false,"description":"Increment/decrement amount for the ± buttons and adjustment keys. Default 1.","default":"1"},{"name":"label","type":"string | undefined","required":false,"description":"The control's persistent, component-owned label. When set it renders as a VISIBLE title ABOVE the ± control (mirroring Input's above-field placement, per-OS type from the skin) and becomes the group's programmatic name (wired via accessibilityLabel + aria-labelledby). When omitted, the control keeps the invisible \"Number\" accessible-name fallback and renders no visible label, so a bare `<Stepper />` looks exactly as before."},{"name":"description","type":"ReactNode","required":false,"description":"Optional muted secondary line rendered under the label (parity with Input). Takes effect only alongside `label`."},{"name":"required","type":"boolean | undefined","required":false,"description":"Marks the control required: appends a destructive \"*\" to the label (decorative, never in the accessible name) and announces the control as required, through aria-required on the web's numeric field and with the word in its name (\"Quantity, required\") on iOS and Android. The star takes effect only alongside `label`.","default":"false"},{"name":"suffix","type":"ReactNode","required":false,"description":"A unit or note beside the control, 16 px after it on the same line (\"× 4px\", \"items\"): a string is set in the 400 13 px subtle ink, a node as it is. Unlike `description`, it reads as part of the value's line."},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium control). Precedence: large > small.","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the medium control). Precedence: large > small.","default":"false","group":0},{"name":"disabled","type":"boolean | undefined","required":false,"description":"State.","default":"false","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1},{"name":"ref","type":"React.Ref<RNTextInput>","required":false,"description":"Ref to the underlying React Native host. Supports object refs and callback refs; native methods follow the platform's behavior."}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default is the medium control). Precedence: large > small."},{"title":"State","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"Increment, decrement, or type a number in a bounded range. A − button, an editable numeric center field, and a + button, controlled by `value` and clamped to `min` / `max` by `step`.\nThis is the ± numeric control (the iOS UIStepper idiom); for a multi-step progress indicator see Steps.\n\nOn the web the control is one 40 px box (32 `small`, 48 `large`) at the control corner with square ± cells and the value in the mono face; on iOS the capsule [ − | + ] pill with the value to its left; on Android Material 3's outlined circular icon buttons around the value.\n\nPass `label` to title the control from above, `description` for a secondary line under it, and `required` to mark it: the label takes a decorative destructive star, and a screen reader hears the control as required,\nfrom `aria-required` on the web's numeric field and from its name (\"Quantity, required\") on iOS and Android.","ios":"Increment, decrement, or type a number in a bounded range. A − button, an editable numeric center field, and a + button, controlled by `value` and clamped to `min` / `max` by `step`.\nThis is the ± numeric control (the iOS UIStepper idiom); for a multi-step progress indicator see Steps.\n\nOn iOS the control is the capsule [ − | + ] pill with the value to its left.\n\nPass `label` to title the control from above, `description` for a secondary line under it, and `required` to mark it: the label takes a decorative destructive star, and a screen reader hears the control as required,\nfrom its name (\"Quantity, required\").","android":"Increment, decrement, or type a number in a bounded range. A − button, an editable numeric center field, and a + button, controlled by `value` and clamped to `min` / `max` by `step`.\nThis is the ± numeric control; for a multi-step progress indicator see Steps.\n\nOn Android the control is Material 3's outlined circular icon buttons around the value.\n\nPass `label` to title the control from above, `description` for a secondary line under it, and `required` to mark it: the label takes a decorative destructive star, and a screen reader hears the control as required,\nfrom its name (\"Quantity, required\")."}},{"slug":"steps","name":"Steps","category":"organisms","description":"Multi-step progress indicators: horizontal, vertical, with progress.","source":"src/organisms/steps/steps.md","url":"https://canvas.nannier.com/ai/4.2.0/components/steps.md","humanUrl":"https://canvas.nannier.com/components/steps","exports":["Step","Steps","StepsProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"StepsProps","props":[{"name":"steps","type":"Step[]","required":true,"description":"Ordered steps to render. Each is a label with an optional one-line note."},{"name":"current","type":"number | undefined","required":false,"description":"Index of the active step (CONTROLLED). Earlier steps read completed, later ones muted. Omit for uncontrolled use."},{"name":"defaultCurrent","type":"number | undefined","required":false,"description":"Initial active step for uncontrolled use (pressing a step, with `onStepPress`, moves it)."},{"name":"vertical","type":"boolean | undefined","required":false,"description":"Layout (pick one; default is horizontal). Precedence: progress, segmented, vertical.","default":"false","group":0},{"name":"compact","type":"boolean | undefined","required":false,"description":"A short vertical list with 22px markers and no connector lines, for a workflow sidebar.","default":"false","group":0},{"name":"segmented","type":"boolean | undefined","required":false,"description":"Equal segments in a row: each step a 4 px bar (the accent once reached, glowing on the current step) over its label and, from its `description`, a status line inked by the step's state (the success ink once done, the accent's text ink on the current step).","default":"false","group":0},{"name":"progress","type":"boolean | undefined","required":false,"description":"Render a labeled percentage progress bar instead of discrete steps.","default":"false","group":0},{"name":"stacks","type":"boolean | undefined","required":false,"description":"Responsive (horizontal layout only): render the EXISTING vertical layout when the component's own CONTAINER is at or below `stackBreakpoint` (default `sm` = 640). Container-measured with a viewport seed, mirroring Row `stacks`. `vertical` and `progress` are unaffected (a progress bar is already fluid).","default":"false","group":0},{"name":"stackBreakpoint","type":"BreakpointKey | undefined","required":false,"description":"The breakpoint at and below which `stacks` goes vertical (default `\"sm\"`). Only meaningful with `stacks`.","group":0},{"name":"value","type":"number | undefined","required":false,"description":"Progress mode only: filled fraction, 0-100 (clamped). Defaults to 0.","group":0},{"name":"label","type":"string | undefined","required":false,"description":"Progress mode only: caption shown left of the percentage.","group":0},{"name":"onStepPress","type":"((index: number) => void) | undefined","required":false,"description":"When set, each step circle is pressable, reporting the step index.","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Layout","pickOne":true,"note":"Layout (pick one; default is horizontal). Precedence: progress, segmented, vertical."}],"inherits":[]}],"platformNotes":{"web":"Multi-step progress indicators: horizontal, vertical, with progress.","ios":"Multi-step progress indicators: horizontal, vertical, with progress.","android":"Multi-step progress indicators: horizontal, vertical, with progress."}},{"slug":"swatch","name":"Swatch","category":"atoms","description":"A color sample: a filled rounded block with the token's name and value beneath it, the anatomy a design-system color sheet repeats down a page. Swatch owns the whole lockup, so a sheet never sets a bare block next to a hand-built text column and drifts row to row.","source":"src/atoms/swatch/swatch.md","url":"https://canvas.nannier.com/ai/4.2.0/components/swatch.md","humanUrl":"https://canvas.nannier.com/components/swatch","exports":["Swatch","SwatchProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"SwatchProps","props":[{"name":"color","type":"string | undefined","required":false,"description":"The fill: any React Native color string. Pass a theme token, not a literal."},{"name":"violet","type":"boolean | undefined","required":false,"description":"Palette picker (pick one): the sample becomes the 16 px hue disc of that accent palette, a radio named for it (a size boolean sizes the disc to that sample edge: `small` is 32 px). Precedence is ThemeProvider's: cyan, mint, rose, amber, violet.","default":"false","group":0},{"name":"cyan","type":"boolean | undefined","required":false,"description":"Palette picker (pick one): the sample becomes the 16 px hue disc of that accent palette, a radio named for it (a size boolean sizes the disc to that sample edge: `small` is 32 px). Precedence is ThemeProvider's: cyan, mint, rose, amber, violet.","default":"false","group":0},{"name":"mint","type":"boolean | undefined","required":false,"description":"Palette picker (pick one): the sample becomes the 16 px hue disc of that accent palette, a radio named for it (a size boolean sizes the disc to that sample edge: `small` is 32 px). Precedence is ThemeProvider's: cyan, mint, rose, amber, violet.","default":"false","group":0},{"name":"rose","type":"boolean | undefined","required":false,"description":"Palette picker (pick one): the sample becomes the 16 px hue disc of that accent palette, a radio named for it (a size boolean sizes the disc to that sample edge: `small` is 32 px). Precedence is ThemeProvider's: cyan, mint, rose, amber, violet.","default":"false","group":0},{"name":"amber","type":"boolean | undefined","required":false,"description":"Palette picker (pick one): the sample becomes the 16 px hue disc of that accent palette, a radio named for it (a size boolean sizes the disc to that sample edge: `small` is 32 px). Precedence is ThemeProvider's: cyan, mint, rose, amber, violet.","default":"false","group":0},{"name":"selected","type":"boolean | undefined","required":false,"description":"The sample is the chosen one: draws the selection ring (a 2 px gap in the page color, then a 2 px band). On a plain sample the band is the accent and the name says \"selected\"; on a palette picker it is the one in force and the radio is checked.","default":"false","group":0},{"name":"onPress","type":"(() => void) | undefined","required":false,"description":"Palette picker: pick this palette.","group":0},{"name":"children","type":"ReactNode","required":false,"description":"The sample's name (the token name). Swatch owns this label column.","group":0},{"name":"value","type":"string | undefined","required":false,"description":"Primary mono line under the name: what the name resolves to (a hex, a custom-property name, a ramp step).","group":0},{"name":"detail","type":"string | undefined","required":false,"description":"Secondary mono line under the value, for a second notation of the same color (an oklch value, a legacy alias).","group":0},{"name":"tiny","type":"boolean | undefined","required":false,"description":"The 20 px disc of a token chip (`<Chip token icon={<Swatch tiny ring circle />}>`).","default":"false","group":1},{"name":"small","type":"boolean | undefined","required":false,"description":"","default":"false","group":1},{"name":"large","type":"boolean | undefined","required":false,"description":"","default":"false","group":1},{"name":"circle","type":"boolean | undefined","required":false,"description":"Circle instead of the default rounded square. Keeps the 1:1 footprint, so it wins over `block`'s stretch.","default":"false","group":1},{"name":"ring","type":"boolean | undefined","required":false,"description":"Draws the token chip's hairline INSIDE the sample, a 1 px inset ring in the field border, in place of the resting hairline edge; a selected sample keeps its selection ring outside it.","default":"false","group":1},{"name":"inline","type":"boolean | undefined","required":false,"description":"Put the label column beside the block instead of under it.","default":"false","group":1},{"name":"block","type":"boolean | undefined","required":false,"description":"Stretch the block to the parent's width; the size then reads as its height (the full-width ramp bar).","default":"false","group":1},{"name":"tile","type":"boolean | undefined","required":false,"description":"The labelled colour tile: the parent's width, 64 px tall (40 `small`), its name set inside the fill on one line (ellipsized where it outgrows the tile) at an 8 px inset in the 11 px mono face, at the foot (centred `small`). `ink` paints the name; the value lines are read into the accessible name only.","default":"false","group":2},{"name":"bar","type":"boolean | undefined","required":false,"description":"A colour bar: the parent's width, 26 px tall at the swatch bar corner (a neutral role's sample).","default":"false","group":2},{"name":"steps","type":"readonly string[] | undefined","required":false,"description":"One bar of colour steps in place of `color`, flush and clipped at the ramp corner at the size's height (`block small` is the 32 px accent ramp); `segmented` stands them apart.","group":2},{"name":"segmented","type":"boolean | undefined","required":false,"description":"`steps` as separate segments: a 28 px bar, 4 apart, the step corner inside and the bar corner at its ends.","default":"false","group":2},{"name":"fluid","type":"boolean | undefined","required":false,"description":"The chip's edge is the parent's width, held 1:1 (a spectrum's discs filling their cells).","default":"false","group":2},{"name":"glow","type":"boolean | undefined","required":false,"description":"The fill's own ambient light under the chip (`0 12px 30px -8px`, the fill at .6).","default":"false","group":2},{"name":"centered","type":"boolean | undefined","required":false,"description":"The label column centred under the chip, 10 px below it.","default":"false","group":2},{"name":"bare","type":"boolean | undefined","required":false,"description":"No resting edge: the sample sits on its fill alone (a saturated fill that needs no hairline).","default":"false","group":2},{"name":"compact","type":"boolean | undefined","required":false,"description":"The mono lockup: the name 500 12 px and the value 400 10 px in the code face, each on one line (ellipsized where it outgrows a narrow column), 6 px apart and 6 px under the chip; a `block` chip is 56 px tall.","default":"false","group":2},{"name":"ink","type":"string | undefined","required":false,"description":"The `tile` name's ink, a theme token like `color` (default the foreground).","group":2},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name override. By default the sample names itself from its own name, value, and detail (falling back to the color string), so pass this only when the name is a node rather than text and there is nothing to read.","group":2},{"name":"decorative","type":"boolean | undefined","required":false,"description":"The sample is decoration beside text that already names it (a theme choice's disc before its label): hidden from assistive tech, so the text carries the name once. Pass it in place of `accessibilityLabel`.","default":"false","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"For layout composition only (not styling): the fill, radius, and size come from props.","group":2}],"groups":[{"title":"Palette picker","pickOne":true,"note":"Palette picker (pick one): the sample becomes the 16 px hue disc of that accent palette, a radio named for it (a size boolean sizes the disc to that sample edge: `small` is 32 px). Precedence is ThemeProvider's: cyan, mint, rose, amber, violet."},{"title":"Size","pickOne":true,"note":"Size (pick one; default 48). Sets the block's edge, or its height when `block`. Precedence: `tiny` > `small` > `large`."},{"title":"Form","pickOne":true,"note":"Form (pick one; default the rounded square). Precedence: `tile` > `bar` > `circle`; a `steps` list wins over all three."}],"inherits":[]}],"platformNotes":{"web":"A color sample: a filled rounded block with the token's name and value beneath\nit, the anatomy a design-system color sheet repeats down a page. Swatch owns the\nwhole lockup, so a sheet never sets a bare block next to a hand-built text\ncolumn and drifts row to row.\n\nPass a live theme token as `color` and the sample follows the active scheme; a\nhairline edge keeps a white or near-black sample visible on the surface behind\nit. The chip is 48px at a 12px corner (32 `small`, 72 `large`, and 20 `tiny`,\nthe disc of a token Chip), the name a 13px line and the value lines 11px mono\nin the subtle ink; the lockup also comes as a `circle`, `inline` (the label\nbeside the block), or as a `block` (a full-width ramp bar). `ring` draws the\nedge as a 1px inset ring in the field border instead of the hairline, the token\nchip's swatch. `selected` marks the chosen sample with the selection ring, a\n2px gap in the page color and then a 2px accent band, and adds \"selected\" to\nits accessible name. `decorative` hides a sample from assistive tech when text\nbeside it already names it (a theme choice's disc before its label), so the\nname is read once.\n\nA palette picker takes one of the kit's five accent palettes, `violet`, `cyan`,\n`mint`, `rose` or `amber` (ThemeProvider's precedence: cyan, mint, rose, amber,\nviolet), with `selected` and `onPress`. It is a 16px disc of the palette's hue,\nthe same in both schemes, and a radio named for its palette (\"Violet\"). The\npalette in force wears the selection ring, a 2px gap in the card color and then\na 2px muted-foreground band; the others draw none. On the web a hovered disc\ngrows to 1.25 times its size. A size boolean sizes the disc to that sample edge\n(`small` is a 32px disc, the size a form's hue choice takes). Put the pickers in\na `radiogroup` so the set reads as one choice. A plain sample still uses `color`.\n\nThe section page's samples come as forms and lockups of the same component. `tile` is\nthe labelled colour tile, the parent's width and 64 px tall (40 `small`), its name set\ninside the fill on one line (ellipsized where it outgrows the tile, its accessible name\nwhole) in the 11 px code face at an 8 px inset, at the foot (centred `small`),\nin the `ink` it is given. `bar` is a colour bar, the parent's width at 26 px and a 7 px\ncorner. `steps` takes a list of colours in place of `color` and draws one bar of them,\nflush and clipped at a 10 px corner at the size's height; `segmented` stands them 4 px\napart in a 28 px bar, each at a 3 px corner but for the bar's two outer ends at 7. The\nform precedence is `tile` > `bar` > `circle`, and a `steps` list wins over all three.\n`fluid` makes the chip's edge the parent's width, held 1:1; `glow` lays the fill's own\nlight under the chip; `centered` centres the label column 10 px under the chip; `bare`\ndrops the resting edge from a fill that needs none; and `compact` is the mono lockup, the\nname 500 12 px and the value 400 10 px in the code face, each on one line (ellipsized in a\nnarrow column), 6 px apart and 6 px under a 56 px `block`.","ios":"A color sample: a filled rounded block with the token's name and value beneath\nit, the anatomy a design-system color sheet repeats down a page. Swatch owns the\nwhole lockup, so a sheet never sets a bare block next to a hand-built text\ncolumn and drifts row to row.\n\nPass a live theme token as `color` and the sample follows the active scheme; a\nhairline edge keeps a white or near-black sample visible on the surface behind\nit. The chip is 48px at a 12px corner (32 `small`, 72 `large`, and 20 `tiny`,\nthe disc of a token Chip), the name a 13px line and the value lines 11px mono\nin the subtle ink; the lockup also comes as a `circle`, `inline` (the label\nbeside the block), or as a `block` (a full-width ramp bar). `ring` draws the\nedge as a 1px inset ring in the field border instead of the hairline, the token\nchip's swatch. `selected` marks the chosen sample with the selection ring, a\n2px gap in the page color and then a 2px accent band, and adds \"selected\" to\nits accessible name. `decorative` hides a sample from assistive tech when text\nbeside it already names it (a theme choice's disc before its label), so the\nname is read once.\n\nA palette picker takes one of the kit's five accent palettes, `violet`, `cyan`,\n`mint`, `rose` or `amber` (ThemeProvider's precedence: cyan, mint, rose, amber,\nviolet), with `selected` and `onPress`. It is a 16px disc of the palette's hue,\nthe same in both schemes, and a radio named for its palette (\"Violet\"). The\npalette in force wears the selection ring, a 2px gap in the card color and then\na 2px muted-foreground band; the others draw none. On the web a hovered disc\ngrows to 1.25 times its size. A size boolean sizes the disc to that sample edge\n(`small` is a 32px disc, the size a form's hue choice takes). Put the pickers in\na `radiogroup` so the set reads as one choice. A plain sample still uses `color`.\n\nThe section page's samples come as forms and lockups of the same component. `tile` is\nthe labelled colour tile, the parent's width and 64 px tall (40 `small`), its name set\ninside the fill on one line (ellipsized where it outgrows the tile, its accessible name\nwhole) in the 11 px code face at an 8 px inset, at the foot (centred `small`),\nin the `ink` it is given. `bar` is a colour bar, the parent's width at 26 px and a 7 px\ncorner. `steps` takes a list of colours in place of `color` and draws one bar of them,\nflush and clipped at a 10 px corner at the size's height; `segmented` stands them 4 px\napart in a 28 px bar, each at a 3 px corner but for the bar's two outer ends at 7. The\nform precedence is `tile` > `bar` > `circle`, and a `steps` list wins over all three.\n`fluid` makes the chip's edge the parent's width, held 1:1; `glow` lays the fill's own\nlight under the chip; `centered` centres the label column 10 px under the chip; `bare`\ndrops the resting edge from a fill that needs none; and `compact` is the mono lockup, the\nname 500 12 px and the value 400 10 px in the code face, each on one line (ellipsized in a\nnarrow column), 6 px apart and 6 px under a 56 px `block`.","android":"A color sample: a filled rounded block with the token's name and value beneath\nit, the anatomy a design-system color sheet repeats down a page. Swatch owns the\nwhole lockup, so a sheet never sets a bare block next to a hand-built text\ncolumn and drifts row to row.\n\nPass a live theme token as `color` and the sample follows the active scheme; a\nhairline edge keeps a white or near-black sample visible on the surface behind\nit. The chip is 48px at a 12px corner (32 `small`, 72 `large`, and 20 `tiny`,\nthe disc of a token Chip), the name a 13px line and the value lines 11px mono\nin the subtle ink; the lockup also comes as a `circle`, `inline` (the label\nbeside the block), or as a `block` (a full-width ramp bar). `ring` draws the\nedge as a 1px inset ring in the field border instead of the hairline, the token\nchip's swatch. `selected` marks the chosen sample with the selection ring, a\n2px gap in the page color and then a 2px accent band, and adds \"selected\" to\nits accessible name. `decorative` hides a sample from assistive tech when text\nbeside it already names it (a theme choice's disc before its label), so the\nname is read once.\n\nA palette picker takes one of the kit's five accent palettes, `violet`, `cyan`,\n`mint`, `rose` or `amber` (ThemeProvider's precedence: cyan, mint, rose, amber,\nviolet), with `selected` and `onPress`. It is a 16px disc of the palette's hue,\nthe same in both schemes, and a radio named for its palette (\"Violet\"). The\npalette in force wears the selection ring, a 2px gap in the card color and then\na 2px muted-foreground band; the others draw none. On the web a hovered disc\ngrows to 1.25 times its size. A size boolean sizes the disc to that sample edge\n(`small` is a 32px disc, the size a form's hue choice takes). Put the pickers in\na `radiogroup` so the set reads as one choice. A plain sample still uses `color`.\n\nThe section page's samples come as forms and lockups of the same component. `tile` is\nthe labelled colour tile, the parent's width and 64 px tall (40 `small`), its name set\ninside the fill on one line (ellipsized where it outgrows the tile, its accessible name\nwhole) in the 11 px code face at an 8 px inset, at the foot (centred `small`),\nin the `ink` it is given. `bar` is a colour bar, the parent's width at 26 px and a 7 px\ncorner. `steps` takes a list of colours in place of `color` and draws one bar of them,\nflush and clipped at a 10 px corner at the size's height; `segmented` stands them 4 px\napart in a 28 px bar, each at a 3 px corner but for the bar's two outer ends at 7. The\nform precedence is `tile` > `bar` > `circle`, and a `steps` list wins over all three.\n`fluid` makes the chip's edge the parent's width, held 1:1; `glow` lays the fill's own\nlight under the chip; `centered` centres the label column 10 px under the chip; `bare`\ndrops the resting edge from a fill that needs none; and `compact` is the mono lockup, the\nname 500 12 px and the value 400 10 px in the code face, each on one line (ellipsized in a\nnarrow column), 6 px apart and 6 px under a 56 px `block`."}},{"slug":"switch","name":"Switch","category":"atoms","description":"On / off switch, isolated or grouped in a settings list.","source":"src/atoms/switch/switch.md","url":"https://canvas.nannier.com/ai/4.2.0/components/switch.md","humanUrl":"https://canvas.nannier.com/components/switch","exports":["Switch","SwitchProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"SwitchProps","props":[{"name":"checked","type":"boolean | undefined","required":false,"description":"Controlled on/off state; omit for uncontrolled use.","default":"false"},{"name":"defaultChecked","type":"boolean | undefined","required":false,"description":"Initial state for uncontrolled use (a bare <Switch /> is interactive).","default":"false"},{"name":"onChange","type":"((next: boolean) => void) | undefined","required":false,"description":"Fired with the next checked value when the switch is toggled (both modes). Web keyboard activation supports Space on release and Enter."},{"name":"onValueChange","type":"((next: boolean) => void) | undefined","required":false,"description":"Alias of onChange, for parity with RN's value-style callbacks."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the pressable row."},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the standard track). The web track scales; iOS and Android draw their platform switch, which comes in one size.","default":"false","group":0},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the standard track). The web track scales; iOS and Android draw their platform switch, which comes in one size.","default":"false","group":0},{"name":"chip","type":"boolean | undefined","required":false,"description":"A compact bordered capsule with its label after the switch, for a toolbar setting.","default":"false","group":0},{"name":"listed","type":"boolean | undefined","required":false,"description":"A row of a settings list: 10 px above and below the row, so a stack of switches reads as a list rather than a form (stack them in a `Column tight`). Pair with `divided` on every row after the first.","default":"false","group":0},{"name":"divided","type":"boolean | undefined","required":false,"description":"A hairline above the row in the `border` ink: a settings list's separator from the row before.","default":"false","group":0},{"name":"disabled","type":"boolean | undefined","required":false,"description":"State.","default":"false","group":1},{"name":"children","type":"ReactNode","required":false,"description":"Optional label, rendered to the left of the track.","group":1},{"name":"description","type":"ReactNode","required":false,"description":"Optional muted description line, rendered under the label.","group":1},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Accessible name for the switch when no visible `children` label is rendered (e.g. a switch embedded in an Action Panel whose label sits in sibling Text). Without it, a label-less switch announces only \"switch, on/off\".","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1},{"name":"ref","type":"React.Ref<View>","required":false,"description":"Ref to the interactive switch row, including its label. Typed as a React Native View. On web, React Native Web exposes its DOM host; focus() and blur() move browser focus. Native host behavior depends on the platform and React Native version. Calling focus() does not activate the control or call accessibility focus APIs."}],"groups":[{"title":"Size","pickOne":true,"note":"Size (pick one; default is the standard track). The web track scales; iOS and Android draw their platform switch, which comes in one size."},{"title":"State","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"On / off switch, isolated or grouped in a settings list.\n\nIn glass mode a switch keeps its solid look on every platform: it is a small\nmark inside content, not a surface, so its track and knob draw as in solid mode,\nwith no pane and no rim, a checked track in its solid brand fill. The track, the\nlabel, the description and the hit target never move, and the checked state flips\nat once. A disabled switch is inert.\n\n`small` and `large` scale the track on the web.\nPass `chip` for a compact toolbar setting: a 32 px bordered capsule with a 26×16 track, a 10 px knob and the label after the switch. The web thumb follows the reference spring and Reduce Motion; native skins keep their own switch.\nOn iOS and Android the switch is the\nplatform's own control, which comes in one size (51x31 on iOS, 52x32 on Android), so\nthe size props leave it unchanged there.\n\nPass `ref` to access the interactive switch row, including its label. Use `useRef<ComponentRef<typeof Switch>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn the web, Space activates the focused control on key release, and Enter also activates it. Holding Space does not repeat the change. Moving focus away, disabling the control, or composing text cancels a pending Space press.","ios":"On / off switch, isolated or grouped in a settings list.\n\nIn glass mode a switch keeps its solid look on every platform: it is a small\nmark inside content, not a surface, so its track and knob draw as in solid mode,\nwith no pane and no rim, a checked track in its solid brand fill. The track, the\nlabel, the description and the hit target never move, and the checked state flips\nat once. A disabled switch is inert.\n\n`small` and `large` scale the track on the web.\nPass `chip` for a compact toolbar setting: a 32 px bordered capsule with a 26×16 track, a 10 px knob and the label after the switch. The web thumb follows the reference spring and Reduce Motion; native skins keep their own switch.\nOn iOS the switch is the platform's own control, which comes in one size (51x31), so the size props leave it unchanged there.\n\nPass `ref` to access the interactive switch row, including its label. Use `useRef<ComponentRef<typeof Switch>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn the web, Space activates the focused control on key release, and Enter also activates it. Holding Space does not repeat the change. Moving focus away, disabling the control, or composing text cancels a pending Space press.","android":"On / off switch, isolated or grouped in a settings list.\n\nIn glass mode a switch keeps its solid look on every platform: it is a small\nmark inside content, not a surface, so its track and knob draw as in solid mode,\nwith no pane and no rim, a checked track in its solid brand fill. The track, the\nlabel, the description and the hit target never move, and the checked state flips\nat once. A disabled switch is inert.\n\n`small` and `large` scale the track on the web.\nPass `chip` for a compact toolbar setting: a 32 px bordered capsule with a 26×16 track, a 10 px knob and the label after the switch. The web thumb follows the reference spring and Reduce Motion; native skins keep their own switch.\nOn Android the switch is the platform's own control, which comes in one size (52x32), so the size props leave it unchanged there.\n\nPass `ref` to access the interactive switch row, including its label. Use `useRef<ComponentRef<typeof Switch>>(null)` from React, or `useRef<View>(null)` with React Native's `View` type. Object and callback refs are supported and detach on unmount. Calling `ref.current?.focus()` or `.blur()` delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.\n\nOn the web, Space activates the focused control on key release, and Enter also activates it. Holding Space does not repeat the change. Moving focus away, disabling the control, or composing text cancels a pending Space press."}},{"slug":"tab-bar","name":"TabBar","category":"organisms","description":"Bottom app navigation: a row of equal-width destinations, each an icon over a short label, with exactly one active. The mobile idiom (the iOS 26 floating tab bar / Material 3 navigation bar), rendered through the glass functional layer.","source":"src/organisms/tab-bar/tab-bar.md","url":"https://canvas.nannier.com/ai/4.2.0/components/tab-bar.md","humanUrl":"https://canvas.nannier.com/components/tab-bar","exports":["TabBar","TabBarItem","TabBarProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"TabBarProps","props":[{"name":"items","type":"TabBarItem[]","required":true,"description":""},{"name":"active","type":"string | undefined","required":false,"description":"The active item's key; omit for uncontrolled use."},{"name":"defaultActive","type":"string | undefined","required":false,"description":"Initial active key for uncontrolled use (defaults to the first item's key)."},{"name":"onSelect","type":"((key: string) => void) | undefined","required":false,"description":"Called with the pressed destination's key (both modes)."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the tablist row."},{"name":"bottomInset","type":"number | undefined","required":false,"description":"Safe-area bottom inset, e.g. `insets.bottom`. It is added BELOW the bar's own symmetric vertical padding (not in place of it), so the bar clears the home indicator without making the bottom margin heavier than the top. Defaults to 0 (web desktop / no inset).","default":"0"},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only. Use bottomInset for the safe area."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"Bottom app navigation: a row of equal-width destinations, each an icon over a short label, with exactly one active.\nThe mobile idiom (the iOS 26 floating tab bar / Material 3 navigation bar), rendered through the glass functional layer.\n\niOS and web share the iOS 26 anatomy: a 62 px capsule that floats above the\ncontent (which scrolls beneath it), inset from the sides, with the safe-area\ninset kept under the capsule, and the selected destination washed in the accent\nas a capsule covering its whole cell. Android docks the Material 3 bar\nfull-bleed, 80 tall under a hairline, with its 64 by 32 icon pill. In glass mode\nthe selection is a control-layer pane on the active destination: the cell\ncapsule on iOS and web, the icon pill on Android. Solid mode retains the\nordinary platform surface.","ios":"Bottom app navigation: a row of equal-width destinations, each an icon over a short label, with exactly one active.\nThe mobile idiom (the iOS 26 floating tab bar), rendered through the glass functional layer.\n\niOS and web share the iOS 26 anatomy: a 62 px capsule that floats above the content (which scrolls beneath it), inset from the sides, with the safe-area inset kept under the capsule, and the selected destination washed in the accent as a capsule covering its whole cell. In glass mode the selection is a control-layer pane on the active destination's cell capsule. Solid mode retains the ordinary platform surface.","android":"Bottom app navigation: a row of equal-width destinations, each an icon over a short label, with exactly one active.\nThe mobile idiom (the Material 3 navigation bar), rendered through the glass functional layer.\n\nAndroid docks the Material 3 bar full-bleed, 80 tall under a hairline, with its 64 by 32 icon pill. In glass mode the selection is a control-layer pane on the active destination's icon pill. Solid mode retains the ordinary platform surface."}},{"slug":"tabs","name":"Tabs","category":"organisms","description":"Underline, pill, vertical, with badges.","source":"src/organisms/tabs/tabs.md","url":"https://canvas.nannier.com/ai/4.2.0/components/tabs.md","humanUrl":"https://canvas.nannier.com/components/tabs","exports":["TabItem","Tabs","TabsProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"TabsProps","props":[{"name":"tabs","type":"TabItem[] | undefined","required":false,"description":"Triggers, left to right. Strings, or `{ label, badge }` for a count."},{"name":"active","type":"number | undefined","required":false,"description":"Index of the active trigger; omit for uncontrolled use."},{"name":"defaultActive","type":"number | undefined","required":false,"description":"Initial active index for uncontrolled use (a bare <Tabs /> switches out of the box)."},{"name":"onSelect","type":"((index: number) => void) | undefined","required":false,"description":"Called with the pressed trigger's index (both modes). Matches TabBar and ButtonGroup, which also fire `onSelect` for the active-index change."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the tablist row."},{"name":"pills","type":"boolean | undefined","required":false,"description":"Look (pick one; default is the underline look). Precedence when more than one is passed: pills, then vertical, then underline.","default":"false","group":0},{"name":"vertical","type":"boolean | undefined","required":false,"description":"Look (pick one; default is the underline look). Precedence when more than one is passed: pills, then vertical, then underline.","default":"false","group":0},{"name":"underline","type":"boolean | undefined","required":false,"description":"Look (pick one; default is the underline look). Precedence when more than one is passed: pills, then vertical, then underline.","default":"false","group":0},{"name":"block","type":"boolean | undefined","required":false,"description":"Layout: equal full-width triggers vs. leading-aligned hugging triggers.","default":"false","group":1},{"name":"wrap","type":"boolean | undefined","required":false,"description":"Layout (the underline and pills rows): a row longer than its container wraps onto further lines inside one track instead of panning in the overflow scroller, so every tab stays on screen at once. The track fills its container and grows taller, its corners concentric with the pills. `block` never overflows and wins; a `responsive` vertical rail honors it once it flattens.","default":"false","group":1},{"name":"responsive","type":"boolean | undefined","required":false,"description":"Responsive (vertical look only): render the EXISTING horizontal underline look when the component's own CONTAINER is at or below `sm` (640), where a side rail would starve the panel beside it. Container-measured with a viewport seed. `pills` and `underline` are unaffected.","default":"false","group":1},{"name":"disabled","type":"boolean | undefined","required":false,"description":"","default":"false","group":1},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook.","group":1}],"groups":[{"title":"Look","pickOne":true,"note":"Look (pick one; default is the underline look). Precedence when more than one is passed: pills, then vertical, then underline."},{"title":"Layout","pickOne":false,"note":"Layout: equal full-width triggers vs. leading-aligned hugging triggers."}],"inherits":[]}],"platformNotes":{"web":"Underline, pill, vertical, with badges.\n\nOn the web the underline look marks the active tab with a glowing accent bar on\nthe row's hairline, pills sit on a rounded track with a raised thumb, and the\nvertical rail washes its active row in the accent.\niOS draws its segmented\ncontrol (UISegmentedControl): underline and pills are a capsule track with a\nraised thumb, and vertical is a grouped rail. Android draws Material 3's tabs.\nIn glass mode a filled selection is a\ncontrol-layer pane behind the selected label, in the platform skin's selected\ntint with readable foreground ink. Solid mode keeps the complete platform\ntreatment.","ios":"Underline, pill, vertical, with badges.\n\nOn the web the underline look marks the active tab with a glowing accent bar on\nthe row's hairline, pills sit on a rounded track with a raised thumb, and the\nvertical rail washes its active row in the accent.\niOS draws its segmented control (UISegmentedControl): underline and pills are a capsule track with a raised thumb, and vertical is a grouped rail.\nIn glass mode a filled selection is a\ncontrol-layer pane behind the selected label, in the platform skin's selected\ntint with readable foreground ink. Solid mode keeps the complete platform\ntreatment.","android":"Underline, pill, vertical, with badges.\n\nOn the web the underline look marks the active tab with a glowing accent bar on\nthe row's hairline, pills sit on a rounded track with a raised thumb, and the\nvertical rail washes its active row in the accent.\nAndroid draws Material 3's tabs.\nIn glass mode a filled selection is a\ncontrol-layer pane behind the selected label, in the platform skin's selected\ntint with readable foreground ink. Solid mode keeps the complete platform\ntreatment."}},{"slug":"text","name":"Text","category":"atoms","description":"Renders text. In React Native every string must live inside a Text element, so you cannot put a bare string in a View. For type scale and tone in app code, reach for `<Typography>` (e.g. `<Typography h3>`, `<Typography body>`, `<Typography tiny muted>`), which owns the kit's roles and colors; use the raw Text primitive for the primitive-level cases it does not cover: `numberOfLines` truncation and nested inline runs.","source":"src/atoms/text/text.md","url":"https://canvas.nannier.com/ai/4.2.0/components/text.md","humanUrl":"https://canvas.nannier.com/components/text","exports":["Text"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"Text host props","groups":[],"inherits":[],"props":[{"name":"allowFontScaling","type":"boolean | undefined","required":false,"description":"Specifies whether fonts should scale to respect Text Size accessibility settings. The default is `true`."},{"name":"children","type":"React.ReactNode","required":false,"description":""},{"name":"ellipsizeMode","type":"\"middle\" | \"head\" | \"tail\" | \"clip\" | undefined","required":false,"description":"This can be one of the following values: - `head` - The line is displayed so that the end fits in the container and the missing text at the beginning of the line is indicated by an ellipsis glyph. e.g., \"...wxyz\" - `middle` - The line is displayed so that the beginning and end fit in the container and the missing text in the middle is indicated by an ellipsis glyph. \"ab...yz\" - `tail` - The line is displayed so that the beginning fits in the container and the missing text at the end of the line is indicated by an ellipsis glyph. e.g., \"abcd...\" - `clip` - Lines are not drawn past the edge of the text container. The default is `tail`. `numberOfLines` must be set in conjunction with this prop. > `clip` is working only for iOS"},{"name":"id","type":"string | undefined","required":false,"description":"Used to reference react managed views from native code."},{"name":"lineBreakMode","type":"\"middle\" | \"head\" | \"tail\" | \"clip\" | undefined","required":false,"description":"Line Break mode. Works only with numberOfLines. clip is working only for iOS"},{"name":"numberOfLines","type":"number | undefined","required":false,"description":"Used to truncate the text with an ellipsis after computing the text layout, including line wrapping, such that the total number of lines does not exceed this number. This prop is commonly used with `ellipsizeMode`."},{"name":"onLayout","type":"((event: LayoutChangeEvent) => void) | undefined","required":false,"description":"Invoked on mount and layout changes with {nativeEvent: { layout: {x, y, width, height}}}."},{"name":"onTextLayout","type":"((event: TextLayoutEvent) => void) | undefined","required":false,"description":"Invoked on Text layout"},{"name":"onPress","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"This function is called on press. Text intrinsically supports press handling with a default highlight state (which can be disabled with suppressHighlighting)."},{"name":"onPressIn","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onPressOut","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onLongPress","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"This function is called on long press. e.g., `onLongPress={this.increaseSize}>`"},{"name":"style","type":"StyleProp<TextStyle>","required":false,"description":""},{"name":"testID","type":"string | undefined","required":false,"description":"Used to locate this view in end-to-end tests."},{"name":"nativeID","type":"string | undefined","required":false,"description":"Used to reference react managed views from native code."},{"name":"maxFontSizeMultiplier","type":"number | null | undefined","required":false,"description":"Specifies largest possible scale a font can reach when allowFontScaling is enabled. Possible values: - null/undefined (default): inherit from the parent node or the global default (0) - 0: no max, ignore parent/global default - >= 1: sets the maxFontSizeMultiplier of this node to this value"},{"name":"minimumFontScale","type":"number | undefined","required":false,"description":"Specifies smallest possible scale a font can reach when adjustsFontSizeToFit is enabled. (values 0.01-1.0)."},{"name":"pointerEvents","type":"\"box-none\" | \"none\" | \"box-only\" | \"auto\" | undefined","required":false,"description":"Controls how touch events are handled. Similar to `View`'s `pointerEvents`."},{"name":"pressRetentionOffset","type":"{ top: number; left: number; bottom: number; right: number; } | undefined","required":false,"description":"Defines how far your touch may move off of the button, before deactivating the button."},{"name":"adjustsFontSizeToFit","type":"boolean | undefined","required":false,"description":"Specifies whether font should be scaled down automatically to fit given style constraints."},{"name":"dynamicTypeRamp","type":"\"callout\" | \"body\" | \"caption2\" | \"caption1\" | \"footnote\" | \"subheadline\" | \"headline\" | \"title3\" | \"title2\" | \"title1\" | \"largeTitle\" | undefined","required":false,"description":"The Dynamic Type scale ramp to apply to this element on iOS."},{"name":"suppressHighlighting","type":"boolean | undefined","required":false,"description":"When `true`, no visual change is made when text is pressed down. By default, a gray oval highlights the text on press down."},{"name":"lineBreakStrategyIOS","type":"\"none\" | \"standard\" | \"hangul-word\" | \"push-out\" | undefined","required":false,"description":"Set line break strategy on iOS."},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Specifies the disabled state of the text view for testing purposes."},{"name":"selectable","type":"boolean | undefined","required":false,"description":"Lets the user select text, to use the native copy and paste functionality."},{"name":"selectionColor","type":"ColorValue | undefined","required":false,"description":"The highlight color of the text."},{"name":"textBreakStrategy","type":"\"simple\" | \"highQuality\" | \"balanced\" | undefined","required":false,"description":"Set text break strategy on Android API Level 23+ default is `highQuality`."},{"name":"dataDetectorType","type":"\"link\" | \"none\" | \"all\" | \"email\" | \"phoneNumber\" | null | undefined","required":false,"description":"Determines the types of data converted to clickable URLs in the text element. By default no data types are detected."},{"name":"android_hyphenationFrequency","type":"\"none\" | \"normal\" | \"full\" | undefined","required":false,"description":"Hyphenation strategy"},{"name":"accessible","type":"boolean | undefined","required":false,"description":"When true, indicates that the view is an accessibility element. By default, all the touchable elements are accessible."},{"name":"accessibilityActions","type":"readonly Readonly<{ name: AccessibilityActionName | string; label?: string | undefined; }>[] | undefined","required":false,"description":"Provides an array of custom actions available for accessibility."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Overrides the text that's read by the screen reader when the user interacts with the element. By default, the label is constructed by traversing all the children and accumulating all the Text nodes separated by space."},{"name":"aria-label","type":"string | undefined","required":false,"description":"Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel https://github.com/facebook/react-native/issues/34424"},{"name":"accessibilityRole","type":"AccessibilityRole | undefined","required":false,"description":"Accessibility Role tells a person using either VoiceOver on iOS or TalkBack on Android the type of element that is focused on."},{"name":"accessibilityState","type":"AccessibilityState | undefined","required":false,"description":"Accessibility State tells a person using either VoiceOver on iOS or TalkBack on Android the state of the element currently focused on."},{"name":"aria-busy","type":"boolean | undefined","required":false,"description":"alias for accessibilityState see https://reactnative.dev/docs/accessibility#accessibilitystate"},{"name":"aria-checked","type":"boolean | \"mixed\" | undefined","required":false,"description":""},{"name":"aria-disabled","type":"boolean | undefined","required":false,"description":""},{"name":"aria-expanded","type":"boolean | undefined","required":false,"description":""},{"name":"aria-selected","type":"boolean | undefined","required":false,"description":""},{"name":"accessibilityHint","type":"string | undefined","required":false,"description":"An accessibility hint helps users understand what will happen when they perform an action on the accessibility element when that result is not obvious from the accessibility label."},{"name":"accessibilityValue","type":"AccessibilityValue | undefined","required":false,"description":"Represents the current value of a component. It can be a textual description of a component's value, or for range-based components, such as sliders and progress bars, it contains range information (minimum, current, and maximum)."},{"name":"aria-valuemax","type":"number | undefined","required":false,"description":""},{"name":"aria-valuemin","type":"number | undefined","required":false,"description":""},{"name":"aria-valuenow","type":"number | undefined","required":false,"description":""},{"name":"aria-valuetext","type":"string | undefined","required":false,"description":""},{"name":"onAccessibilityAction","type":"((event: AccessibilityActionEvent) => void) | undefined","required":false,"description":"When `accessible` is true, the system will try to invoke this function when the user performs an accessibility custom action."},{"name":"importantForAccessibility","type":"\"auto\" | \"yes\" | \"no\" | \"no-hide-descendants\" | undefined","required":false,"description":"[Android] Controlling if a view fires accessibility events and if it is reported to accessibility services."},{"name":"aria-hidden","type":"boolean | undefined","required":false,"description":"A value indicating whether the accessibility elements contained within this accessibility element are hidden."},{"name":"aria-modal","type":"boolean | undefined","required":false,"description":""},{"name":"role","type":"Role | undefined","required":false,"description":"Indicates to accessibility services to treat UI component like a specific role."},{"name":"accessibilityLabelledBy","type":"string | string[] | undefined","required":false,"description":"Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props, the text is read aloud. The value should should match the nativeID of the related element."},{"name":"aria-labelledby","type":"string | undefined","required":false,"description":"Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props, the text is read aloud. The value should should match the nativeID of the related element."},{"name":"accessibilityLiveRegion","type":"\"none\" | \"polite\" | \"assertive\" | undefined","required":false,"description":"Indicates to accessibility services whether the user should be notified when this view changes. Works for Android API >= 19 only."},{"name":"aria-live","type":"\"polite\" | \"assertive\" | \"off\" | undefined","required":false,"description":"Indicates to accessibility services whether the user should be notified when this view changes. Works for Android API >= 19 only."},{"name":"screenReaderFocusable","type":"boolean | undefined","required":false,"description":"Enables the view to be screen reader focusable, not keyboard focusable."},{"name":"accessibilityElementsHidden","type":"boolean | undefined","required":false,"description":"A Boolean value indicating whether the accessibility elements contained within this accessibility element are hidden to the screen reader."},{"name":"accessibilityViewIsModal","type":"boolean | undefined","required":false,"description":"A Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver."},{"name":"onAccessibilityEscape","type":"(() => void) | undefined","required":false,"description":"When accessible is true, the system will invoke this function when the user performs the escape gesture (scrub with two fingers)."},{"name":"onAccessibilityTap","type":"(() => void) | undefined","required":false,"description":"When `accessible` is true, the system will try to invoke this function when the user performs accessibility tap gesture."},{"name":"onMagicTap","type":"(() => void) | undefined","required":false,"description":"When accessible is true, the system will invoke this function when the user performs the magic tap gesture."},{"name":"accessibilityIgnoresInvertColors","type":"boolean | undefined","required":false,"description":"https://reactnative.dev/docs/accessibility#accessibilityignoresinvertcolorsios"},{"name":"accessibilityLanguage","type":"string | undefined","required":false,"description":"By using the accessibilityLanguage property, the screen reader will understand which language to use while reading the element's label, value and hint. The provided string value must follow the BCP 47 specification (https://www.rfc-editor.org/info/bcp47). https://reactnative.dev/docs/accessibility#accessibilitylanguage-ios"},{"name":"accessibilityShowsLargeContentViewer","type":"boolean | undefined","required":false,"description":"A Boolean value that indicates whether or not to show the item in the large content viewer. Available on iOS 13.0+ https://reactnative.dev/docs/accessibility#accessibilityshowslargecontentviewer"},{"name":"accessibilityLargeContentTitle","type":"string | undefined","required":false,"description":"When `accessibilityShowsLargeContentViewer` is set, this string will be used as title for the large content viewer. https://reactnative.dev/docs/accessibility#accessibilitylargecontenttitle"},{"name":"accessibilityRespondsToUserInteraction","type":"boolean | undefined","required":false,"description":"Blocks the user from interacting with the component through keyboard while still allowing screen reader to interact with it if this View is still accessible."},{"name":"ref","type":"Ref<Text> | undefined","required":false,"description":"Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref)."},{"name":"key","type":"Key | null | undefined","required":false,"description":""}]}],"platformNotes":{"web":"Renders text. In React Native every string must live inside a Text element, so you cannot put a bare string in a View. For type scale and tone in app code, reach for `<Typography>` (e.g. `<Typography h3>`, `<Typography body>`, `<Typography tiny muted>`), which owns the kit's roles and colors; use the raw Text primitive for the primitive-level cases it does not cover: `numberOfLines` truncation and nested inline runs.","ios":"Renders text. In React Native every string must live inside a Text element, so you cannot put a bare string in a View. For type scale and tone in app code, reach for `<Typography>` (e.g. `<Typography h3>`, `<Typography body>`, `<Typography tiny muted>`), which owns the kit's roles and colors; use the raw Text primitive for the primitive-level cases it does not cover: `numberOfLines` truncation and nested inline runs.","android":"Renders text. In React Native every string must live inside a Text element, so you cannot put a bare string in a View. For type scale and tone in app code, reach for `<Typography>` (e.g. `<Typography h3>`, `<Typography body>`, `<Typography tiny muted>`), which owns the kit's roles and colors; use the raw Text primitive for the primitive-level cases it does not cover: `numberOfLines` truncation and nested inline runs."}},{"slug":"text-input","name":"TextInput","category":"atoms","description":"Single-line (or multiline) text entry. Control it with `value` + `onChangeText`, and style the box with the usual View style props. Common props: `placeholder`, `secureTextEntry` (passwords), `keyboardType`, and `multiline`.","source":"src/atoms/text-input/text-input.md","url":"https://canvas.nannier.com/ai/4.2.0/components/text-input.md","humanUrl":"https://canvas.nannier.com/components/text-input","exports":["TextInput"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"TextInput host props","groups":[],"inherits":[],"props":[{"name":"systemFocus","type":"boolean | undefined","required":false,"description":"Keep the platform’s system focus appearance instead of the themed ring."},{"name":"allowFontScaling","type":"boolean | undefined","required":false,"description":"Specifies whether fonts should scale to respect Text Size accessibility settings. The default is `true`."},{"name":"autoCapitalize","type":"\"none\" | \"sentences\" | \"words\" | \"characters\" | undefined","required":false,"description":"Can tell TextInput to automatically capitalize certain characters. characters: all characters, words: first letter of each word sentences: first letter of each sentence (default) none: don't auto capitalize anything https://reactnative.dev/docs/textinput#autocapitalize"},{"name":"autoComplete","type":"\"country\" | \"name\" | \"off\" | \"nickname\" | \"username\" | \"password\" | \"2fa-app-otp\" | \"additional-name\" | \"address-line1\" | \"address-line2\" | \"birthdate-day\" | \"birthdate-full\" | \"birthdate-month\" | \"birthdate-year\" | \"cc-csc\" | \"cc-exp\" | \"cc-exp-day\" | \"cc-exp-month\" | \"cc-exp-year\" | \"cc-number\" | \"cc-name\" | \"cc-given-name\" | \"cc-middle-name\" | \"cc-family-name\" | \"cc-type\" | \"current-password\" | \"email\" | \"email-otp\" | \"flight-confirmation-code\" | \"flight-number\" | \"family-name\" | \"gender\" | \"gift-card-number\" | \"gift-card-pin\" | \"given-name\" | \"honorific-prefix\" | \"honorific-suffix\" | \"loyalty-account-number\" | \"name-family\" | \"name-given\" | \"name-middle\" | \"name-middle-initial\" | \"name-prefix\" | \"name-suffix\" | \"new-password\" | \"one-time-code\" | \"organization\" | \"organization-title\" | \"password-new\" | \"postal-address\" | \"postal-address-country\" | \"postal-address-dependent-locality\" | \"postal-address-extended\" | \"postal-address-extended-postal-code\" | \"postal-address-locality\" | \"postal-address-region\" | \"postal-address-unit\" | \"postal-code\" | \"promo-code\" | \"street-address\" | \"sms-otp\" | \"tel\" | \"tel-country-code\" | \"tel-national\" | \"tel-device\" | \"upi-vpa\" | \"url\" | \"wifi-password\" | \"username-new\" | undefined","required":false,"description":"Specifies autocomplete hints for the system, so it can provide autofill. On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content. To disable autocomplete, set autoComplete to off. The following values work across platforms: - `additional-name` - `address-line1` - `address-line2` - `cc-number` - `country` - `current-password` - `email` - `family-name` - `given-name` - `honorific-prefix` - `honorific-suffix` - `name` - `new-password` - `off` - `one-time-code` - `postal-code` - `street-address` - `tel` - `username` The following values work on iOS only: - `nickname` - `organization` - `organization-title` - `url` The following values work on Android only: - `birthdate-day` - `birthdate-full` - `birthdate-month` - `birthdate-year` - `cc-csc` - `cc-exp` - `cc-exp-day` - `cc-exp-month` - `cc-exp-year` - `2fa-app-otp` - `email-otp` - `flight-confirmation-code` - `flight-number` - `gender` - `gift-card-number` - `gift-card-pin` - `loyalty-account-number` - `name-family` - `name-given` - `name-middle` - `name-middle-initial` - `name-prefix` - `name-suffix` - `password` - `password-new` - `postal-address` - `postal-address-country` - `postal-address-dependent-locality` - `postal-address-extended` - `postal-address-extended-postal-code` - `postal-address-locality` - `postal-address-region` - `postal-address-unit` - `promo-code` - `sms-otp` - `tel-country-code` - `tel-national` - `tel-device` - `upi-vpa` - `wifi-password` - `username-new`"},{"name":"autoCorrect","type":"boolean | undefined","required":false,"description":"If false, disables auto-correct. The default value is true."},{"name":"autoFocus","type":"boolean | undefined","required":false,"description":"If true, focuses the input on componentDidMount. The default value is false."},{"name":"blurOnSubmit","type":"boolean | undefined","required":false,"description":"If `true`, the text field will blur when submitted. The default value is true for single-line fields and false for multiline fields. Note that for multiline fields, setting `blurOnSubmit` to `true` means that pressing return will blur the field and trigger the `onSubmitEditing` event instead of inserting a newline into the field."},{"name":"submitBehavior","type":"SubmitBehavior | undefined","required":false,"description":"When the return key is pressed, For single line inputs: - `'newline`' defaults to `'blurAndSubmit'` - `undefined` defaults to `'blurAndSubmit'` For multiline inputs: - `'newline'` adds a newline - `undefined` defaults to `'newline'` For both single line and multiline inputs: - `'submit'` will only send a submit event and not blur the input - `'blurAndSubmit`' will both blur the input and send a submit event"},{"name":"caretHidden","type":"boolean | undefined","required":false,"description":"If true, caret is hidden. The default value is false."},{"name":"contextMenuHidden","type":"boolean | undefined","required":false,"description":"If true, context menu is hidden. The default value is false."},{"name":"defaultValue","type":"string | undefined","required":false,"description":"Provides an initial value that will change when the user starts typing. Useful for simple use-cases where you don't want to deal with listening to events and updating the value prop to keep the controlled state in sync."},{"name":"editable","type":"boolean | undefined","required":false,"description":"If false, text is not editable. The default value is true."},{"name":"keyboardType","type":"KeyboardTypeOptions | undefined","required":false,"description":"enum(\"default\", 'numeric', 'email-address', \"ascii-capable\", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search', 'visible-password') Determines which keyboard to open, e.g.numeric. The following values work across platforms: - default - numeric - email-address - phone-pad The following values work on iOS: - ascii-capable - numbers-and-punctuation - url - number-pad - name-phone-pad - decimal-pad - twitter - web-search The following values work on Android: - visible-password"},{"name":"inputMode","type":"InputModeOptions | undefined","required":false,"description":"Works like the inputmode attribute in HTML, it determines which keyboard to open, e.g. numeric and has precedence over keyboardType."},{"name":"maxLength","type":"number | undefined","required":false,"description":"Limits the maximum number of characters that can be entered. Use this instead of implementing the logic in JS to avoid flicker."},{"name":"multiline","type":"boolean | undefined","required":false,"description":"If true, the text input can be multiple lines. The default value is false."},{"name":"onBlur","type":"((e: BlurEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input is blurred Note: If you are trying to find the last value of TextInput, you can use the `onEndEditing` event, which is fired upon completion of editing."},{"name":"onChange","type":"((e: TextInputChangeEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input's text changes."},{"name":"onChangeText","type":"((text: string) => void) | undefined","required":false,"description":"Callback that is called when the text input's text changes. Changed text is passed as an argument to the callback handler."},{"name":"onContentSizeChange","type":"((e: TextInputContentSizeChangeEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input's content size changes. This will be called with `{ nativeEvent: { contentSize: { width, height } } }`. Only called for multiline text inputs."},{"name":"onEndEditing","type":"((e: TextInputEndEditingEvent) => void) | undefined","required":false,"description":"Callback that is called when text input ends."},{"name":"onPress","type":"((e: NativeSyntheticEvent<NativeTouchEvent>) => void) | undefined","required":false,"description":"Called when a single tap gesture is detected."},{"name":"onPressIn","type":"((e: NativeSyntheticEvent<NativeTouchEvent>) => void) | undefined","required":false,"description":"Callback that is called when a touch is engaged."},{"name":"onPressOut","type":"((e: NativeSyntheticEvent<NativeTouchEvent>) => void) | undefined","required":false,"description":"Callback that is called when a touch is released."},{"name":"onFocus","type":"((e: FocusEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input is focused"},{"name":"onSelectionChange","type":"((e: TextInputSelectionChangeEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input selection is changed."},{"name":"onSubmitEditing","type":"((e: TextInputSubmitEditingEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input's submit button is pressed."},{"name":"onScroll","type":"((e: TextInputScrollEvent) => void) | undefined","required":false,"description":"Invoked on content scroll with `{ nativeEvent: { contentOffset: { x, y } } }`. May also contain other properties from ScrollEvent but on Android contentSize is not provided for performance reasons."},{"name":"onKeyPress","type":"((e: TextInputKeyPressEvent) => void) | undefined","required":false,"description":"Callback that is called when a key is pressed. This will be called with `{ nativeEvent: { key: keyValue } }` where keyValue is 'Enter' or 'Backspace' for respective keys and the typed-in character otherwise including ' ' for space. Fires before onChange callbacks. Note: on Android only the inputs from soft keyboard are handled, not the hardware keyboard inputs."},{"name":"placeholder","type":"string | undefined","required":false,"description":"The string that will be rendered before text input has been entered"},{"name":"placeholderTextColor","type":"ColorValue | undefined","required":false,"description":"The text color of the placeholder string"},{"name":"readOnly","type":"boolean | undefined","required":false,"description":"If `true`, text is not editable. The default value is `false`."},{"name":"returnKeyType","type":"ReturnKeyTypeOptions | undefined","required":false,"description":"enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call') Determines how the return key should look."},{"name":"enterKeyHint","type":"EnterKeyHintTypeOptions | undefined","required":false,"description":"Determines what text should be shown to the return key on virtual keyboards. Has precedence over the returnKeyType prop."},{"name":"secureTextEntry","type":"boolean | undefined","required":false,"description":"If true, the text input obscures the text entered so that sensitive text like passwords stay secure. The default value is false."},{"name":"selectTextOnFocus","type":"boolean | undefined","required":false,"description":"If true, all text will automatically be selected on focus"},{"name":"selection","type":"{ start: number; end?: number | undefined; } | undefined","required":false,"description":"The start and end of the text input's selection. Set start and end to the same value to position the cursor."},{"name":"selectionColor","type":"ColorValue | undefined","required":false,"description":"The highlight (and cursor on ios) color of the text input"},{"name":"style","type":"StyleProp<TextStyle>","required":false,"description":"Styles"},{"name":"textAlign","type":"\"left\" | \"right\" | \"center\" | undefined","required":false,"description":"Align the input text to the left, center, or right sides of the input field."},{"name":"testID","type":"string | undefined","required":false,"description":"Used to locate this view in end-to-end tests"},{"name":"inputAccessoryViewID","type":"string | undefined","required":false,"description":"Used to connect to an InputAccessoryView. Not part of react-natives documentation, but present in examples and code. See https://reactnative.dev/docs/inputaccessoryview for more information."},{"name":"inputAccessoryViewButtonLabel","type":"string | undefined","required":false,"description":"An optional label that overrides the default input accessory view button label."},{"name":"value","type":"string | undefined","required":false,"description":"The value to show for the text input. TextInput is a controlled component, which means the native value will be forced to match this value prop if provided. For most uses this works great, but in some cases this may cause flickering - one common cause is preventing edits by keeping value the same. In addition to simply setting the same value, either set editable={false}, or set/update maxLength to prevent unwanted edits without flicker."},{"name":"maxFontSizeMultiplier","type":"number | null | undefined","required":false,"description":"Specifies largest possible scale a font can reach when allowFontScaling is enabled. Possible values: - null/undefined (default): inherit from the parent node or the global default (0) - 0: no max, ignore parent/global default - >= 1: sets the maxFontSizeMultiplier of this node to this value"},{"name":"children","type":"React.ReactNode","required":false,"description":""},{"name":"hitSlop","type":"number | Insets | null | undefined","required":false,"description":"This defines how far a touch event can start away from the view. Typical interface guidelines recommend touch targets that are at least 30 - 40 points/density-independent pixels. If a Touchable view has a height of 20 the touchable height can be extended to 40 with hitSlop={{top: 10, bottom: 10, left: 0, right: 0}} NOTE The touch area never extends past the parent view bounds and the Z-index of sibling views always takes precedence if a touch hits two overlapping views."},{"name":"id","type":"string | undefined","required":false,"description":"Used to reference react managed views from native code."},{"name":"needsOffscreenAlphaCompositing","type":"boolean | undefined","required":false,"description":"Whether this view needs to rendered offscreen and composited with an alpha in order to preserve 100% correct colors and blending behavior. The default (false) falls back to drawing the component and its children with an alpha applied to the paint used to draw each element instead of rendering the full component offscreen and compositing it back with an alpha value. This default may be noticeable and undesired in the case where the View you are setting an opacity on has multiple overlapping elements (e.g. multiple overlapping Views, or text and a background). Rendering offscreen to preserve correct alpha behavior is extremely expensive and hard to debug for non-native developers, which is why it is not turned on by default. If you do need to enable this property for an animation, consider combining it with renderToHardwareTextureAndroid if the view contents are static (i.e. it doesn't need to be redrawn each frame). If that property is enabled, this View will be rendered off-screen once, saved in a hardware texture, and then composited onto the screen with an alpha each frame without having to switch rendering targets on the GPU."},{"name":"onLayout","type":"((event: LayoutChangeEvent) => void) | undefined","required":false,"description":"Invoked on mount and layout changes with {nativeEvent: { layout: {x, y, width, height}}}."},{"name":"pointerEvents","type":"\"box-none\" | \"none\" | \"box-only\" | \"auto\" | undefined","required":false,"description":" In the absence of auto property, none is much like CSS's none value. box-none is as if you had applied the CSS class: .box-none { pointer-events: none; } .box-none * { pointer-events: all; } box-only is the equivalent of .box-only { pointer-events: all; } .box-only * { pointer-events: none; } But since pointerEvents does not affect layout/appearance, and we are already deviating from the spec by adding additional modes, we opt to not include pointerEvents on style. On some platforms, we would need to implement it as a className anyways. Using style or not is an implementation detail of the platform."},{"name":"removeClippedSubviews","type":"boolean | undefined","required":false,"description":" This is a special performance property exposed by RCTView and is useful for scrolling content when there are many subviews, most of which are offscreen. For this property to be effective, it must be applied to a view that contains many subviews that extend outside its bound. The subviews must also have overflow: hidden, as should the containing view (or one of its superviews)."},{"name":"nativeID","type":"string | undefined","required":false,"description":"Used to reference react managed views from native code."},{"name":"collapsable","type":"boolean | undefined","required":false,"description":"Views that are only used to layout their children or otherwise don't draw anything may be automatically removed from the native hierarchy as an optimization. Set this property to false to disable this optimization and ensure that this View exists in the native view hierarchy."},{"name":"collapsableChildren","type":"boolean | undefined","required":false,"description":"Setting to false prevents direct children of the view from being removed from the native view hierarchy, similar to the effect of setting `collapsable={false}` on each child."},{"name":"renderToHardwareTextureAndroid","type":"boolean | undefined","required":false,"description":"Whether this view should render itself (and all of its children) into a single hardware texture on the GPU. On Android, this is useful for animations and interactions that only modify opacity, rotation, translation, and/or scale: in those cases, the view doesn't have to be redrawn and display lists don't need to be re-executed. The texture can just be re-used and re-composited with different parameters. The downside is that this can use up limited video memory, so this prop should be set back to false at the end of the interaction/animation."},{"name":"focusable","type":"boolean | undefined","required":false,"description":"Whether this `View` should be focusable with a non-touch input device, eg. receive focus with a hardware keyboard."},{"name":"tabIndex","type":"0 | -1 | undefined","required":false,"description":"Indicates whether this `View` should be focusable with a non-touch input device, eg. receive focus with a hardware keyboard. See https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex for more details. Supports the following values: - 0 (View is focusable) - -1 (View is not focusable)"},{"name":"shouldRasterizeIOS","type":"boolean | undefined","required":false,"description":"Whether this view should be rendered as a bitmap before compositing. On iOS, this is useful for animations and interactions that do not modify this component's dimensions nor its children; for example, when translating the position of a static view, rasterization allows the renderer to reuse a cached bitmap of a static view and quickly composite it during each frame. Rasterization incurs an off-screen drawing pass and the bitmap consumes memory. Test and measure when using this property."},{"name":"isTVSelectable","type":"boolean | undefined","required":false,"description":"*(Apple TV only)* When set to true, this view will be focusable and navigable using the Apple TV remote."},{"name":"hasTVPreferredFocus","type":"boolean | undefined","required":false,"description":"*(Apple TV only)* May be set to true to force the Apple TV focus engine to move focus to this view."},{"name":"tvParallaxShiftDistanceX","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0."},{"name":"tvParallaxShiftDistanceY","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0."},{"name":"tvParallaxTiltAngle","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 0.05."},{"name":"tvParallaxMagnification","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 1.0."},{"name":"onStartShouldSetResponder","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"Does this view want to become responder on the start of a touch?"},{"name":"onMoveShouldSetResponder","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"Called for every touch move on the View when it is not the responder: does this view want to \"claim\" touch responsiveness?"},{"name":"onResponderEnd","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"If the View returns true and attempts to become the responder, one of the following will happen:"},{"name":"onResponderGrant","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"The View is now responding for touch events. This is the time to highlight and show the user what is happening"},{"name":"onResponderReject","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Something else is the responder right now and will not release it"},{"name":"onResponderMove","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"The user is moving their finger"},{"name":"onResponderRelease","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Fired at the end of the touch, ie \"touchUp\""},{"name":"onResponderStart","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onResponderTerminationRequest","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"Something else wants to become responder. Should this view release the responder? Returning true allows release"},{"name":"onResponderTerminate","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"The responder has been taken from the View. Might be taken by other views after a call to onResponderTerminationRequest, or might be taken by the OS without asking (happens with control center/ notification center on iOS)"},{"name":"onStartShouldSetResponderCapture","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern, where the deepest node is called first. That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers. This is desirable in most cases, because it makes sure all controls and buttons are usable. However, sometimes a parent will want to make sure that it becomes responder. This can be handled by using the capture phase. Before the responder system bubbles up from the deepest component, it will do a capture phase, firing on*ShouldSetResponderCapture. So if a parent View wants to prevent the child from becoming responder on a touch start, it should have a onStartShouldSetResponderCapture handler which returns true."},{"name":"onMoveShouldSetResponderCapture","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern, where the deepest node is called first. That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers. This is desirable in most cases, because it makes sure all controls and buttons are usable. However, sometimes a parent will want to make sure that it becomes responder. This can be handled by using the capture phase. Before the responder system bubbles up from the deepest component, it will do a capture phase, firing on*ShouldSetResponderCapture. So if a parent View wants to prevent the child from becoming responder on a touch start, it should have a onStartShouldSetResponderCapture handler which returns true."},{"name":"onTouchStart","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchMove","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchEnd","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchCancel","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchEndCapture","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerEnter","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerEnterCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerLeave","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerLeaveCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerMove","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerMoveCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerCancel","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerCancelCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerDown","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerDownCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerUp","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerUpCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"accessible","type":"boolean | undefined","required":false,"description":"When true, indicates that the view is an accessibility element. By default, all the touchable elements are accessible."},{"name":"accessibilityActions","type":"readonly Readonly<{ name: AccessibilityActionName | string; label?: string | undefined; }>[] | undefined","required":false,"description":"Provides an array of custom actions available for accessibility."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Overrides the text that's read by the screen reader when the user interacts with the element. By default, the label is constructed by traversing all the children and accumulating all the Text nodes separated by space."},{"name":"aria-label","type":"string | undefined","required":false,"description":"Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel https://github.com/facebook/react-native/issues/34424"},{"name":"accessibilityRole","type":"AccessibilityRole | undefined","required":false,"description":"Accessibility Role tells a person using either VoiceOver on iOS or TalkBack on Android the type of element that is focused on."},{"name":"accessibilityState","type":"AccessibilityState | undefined","required":false,"description":"Accessibility State tells a person using either VoiceOver on iOS or TalkBack on Android the state of the element currently focused on."},{"name":"aria-busy","type":"boolean | undefined","required":false,"description":"alias for accessibilityState see https://reactnative.dev/docs/accessibility#accessibilitystate"},{"name":"aria-checked","type":"boolean | \"mixed\" | undefined","required":false,"description":""},{"name":"aria-disabled","type":"boolean | undefined","required":false,"description":""},{"name":"aria-expanded","type":"boolean | undefined","required":false,"description":""},{"name":"aria-selected","type":"boolean | undefined","required":false,"description":""},{"name":"accessibilityHint","type":"string | undefined","required":false,"description":"An accessibility hint helps users understand what will happen when they perform an action on the accessibility element when that result is not obvious from the accessibility label."},{"name":"accessibilityValue","type":"AccessibilityValue | undefined","required":false,"description":"Represents the current value of a component. It can be a textual description of a component's value, or for range-based components, such as sliders and progress bars, it contains range information (minimum, current, and maximum)."},{"name":"aria-valuemax","type":"number | undefined","required":false,"description":""},{"name":"aria-valuemin","type":"number | undefined","required":false,"description":""},{"name":"aria-valuenow","type":"number | undefined","required":false,"description":""},{"name":"aria-valuetext","type":"string | undefined","required":false,"description":""},{"name":"onAccessibilityAction","type":"((event: AccessibilityActionEvent) => void) | undefined","required":false,"description":"When `accessible` is true, the system will try to invoke this function when the user performs an accessibility custom action."},{"name":"importantForAccessibility","type":"\"auto\" | \"yes\" | \"no\" | \"no-hide-descendants\" | undefined","required":false,"description":"[Android] Controlling if a view fires accessibility events and if it is reported to accessibility services."},{"name":"aria-hidden","type":"boolean | undefined","required":false,"description":"A value indicating whether the accessibility elements contained within this accessibility element are hidden."},{"name":"aria-modal","type":"boolean | undefined","required":false,"description":""},{"name":"role","type":"Role | undefined","required":false,"description":"Indicates to accessibility services to treat UI component like a specific role."},{"name":"accessibilityLabelledBy","type":"string | string[] | undefined","required":false,"description":"Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props, the text is read aloud. The value should should match the nativeID of the related element."},{"name":"aria-labelledby","type":"string | undefined","required":false,"description":"Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props, the text is read aloud. The value should should match the nativeID of the related element."},{"name":"accessibilityLiveRegion","type":"\"none\" | \"polite\" | \"assertive\" | undefined","required":false,"description":"Indicates to accessibility services whether the user should be notified when this view changes. Works for Android API >= 19 only."},{"name":"aria-live","type":"\"polite\" | \"assertive\" | \"off\" | undefined","required":false,"description":"Indicates to accessibility services whether the user should be notified when this view changes. Works for Android API >= 19 only."},{"name":"screenReaderFocusable","type":"boolean | undefined","required":false,"description":"Enables the view to be screen reader focusable, not keyboard focusable."},{"name":"accessibilityElementsHidden","type":"boolean | undefined","required":false,"description":"A Boolean value indicating whether the accessibility elements contained within this accessibility element are hidden to the screen reader."},{"name":"accessibilityViewIsModal","type":"boolean | undefined","required":false,"description":"A Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver."},{"name":"onAccessibilityEscape","type":"(() => void) | undefined","required":false,"description":"When accessible is true, the system will invoke this function when the user performs the escape gesture (scrub with two fingers)."},{"name":"onAccessibilityTap","type":"(() => void) | undefined","required":false,"description":"When `accessible` is true, the system will try to invoke this function when the user performs accessibility tap gesture."},{"name":"onMagicTap","type":"(() => void) | undefined","required":false,"description":"When accessible is true, the system will invoke this function when the user performs the magic tap gesture."},{"name":"accessibilityIgnoresInvertColors","type":"boolean | undefined","required":false,"description":"https://reactnative.dev/docs/accessibility#accessibilityignoresinvertcolorsios"},{"name":"accessibilityLanguage","type":"string | undefined","required":false,"description":"By using the accessibilityLanguage property, the screen reader will understand which language to use while reading the element's label, value and hint. The provided string value must follow the BCP 47 specification (https://www.rfc-editor.org/info/bcp47). https://reactnative.dev/docs/accessibility#accessibilitylanguage-ios"},{"name":"accessibilityShowsLargeContentViewer","type":"boolean | undefined","required":false,"description":"A Boolean value that indicates whether or not to show the item in the large content viewer. Available on iOS 13.0+ https://reactnative.dev/docs/accessibility#accessibilityshowslargecontentviewer"},{"name":"accessibilityLargeContentTitle","type":"string | undefined","required":false,"description":"When `accessibilityShowsLargeContentViewer` is set, this string will be used as title for the large content viewer. https://reactnative.dev/docs/accessibility#accessibilitylargecontenttitle"},{"name":"accessibilityRespondsToUserInteraction","type":"boolean | undefined","required":false,"description":"Blocks the user from interacting with the component through keyboard while still allowing screen reader to interact with it if this View is still accessible."},{"name":"disableKeyboardShortcuts","type":"boolean | undefined","required":false,"description":"If true, the keyboard shortcuts (undo/redo and copy buttons) are disabled. The default value is false."},{"name":"clearButtonMode","type":"\"always\" | \"never\" | \"while-editing\" | \"unless-editing\" | undefined","required":false,"description":"enum('never', 'while-editing', 'unless-editing', 'always') When the clear button should appear on the right side of the text view"},{"name":"clearTextOnFocus","type":"boolean | undefined","required":false,"description":"If true, clears the text field automatically when editing begins"},{"name":"dataDetectorTypes","type":"DataDetectorTypes | DataDetectorTypes[] | undefined","required":false,"description":"Determines the types of data converted to clickable URLs in the text input. Only valid if `multiline={true}` and `editable={false}`. By default no data types are detected. You can provide one type or an array of many types. Possible values for `dataDetectorTypes` are: - `'phoneNumber'` - `'link'` - `'address'` - `'calendarEvent'` - `'none'` - `'all'`"},{"name":"enablesReturnKeyAutomatically","type":"boolean | undefined","required":false,"description":"If true, the keyboard disables the return key when there is no text and automatically enables it when there is text. The default value is false."},{"name":"keyboardAppearance","type":"\"light\" | \"dark\" | \"default\" | undefined","required":false,"description":"Determines the color of the keyboard."},{"name":"passwordRules","type":"string | null | undefined","required":false,"description":"Provide rules for your password. For example, say you want to require a password with at least eight characters consisting of a mix of uppercase and lowercase letters, at least one number, and at most two consecutive characters. \"required: upper; required: lower; required: digit; max-consecutive: 2; minlength: 8;\""},{"name":"rejectResponderTermination","type":"boolean | null | undefined","required":false,"description":"If `true`, allows TextInput to pass touch events to the parent component. This allows components to be swipeable from the TextInput on iOS, as is the case on Android by default. If `false`, TextInput always asks to handle the input (except when disabled)."},{"name":"selectionState","type":"DocumentSelectionState | undefined","required":false,"description":"See DocumentSelectionState.js, some state that is responsible for maintaining selection information for a document"},{"name":"spellCheck","type":"boolean | undefined","required":false,"description":"If false, disables spell-check style (i.e. red underlines). The default value is inherited from autoCorrect"},{"name":"textContentType","type":"\"none\" | \"name\" | \"URL\" | \"addressCity\" | \"addressCityAndState\" | \"addressState\" | \"countryName\" | \"creditCardNumber\" | \"creditCardExpiration\" | \"creditCardExpirationMonth\" | \"creditCardExpirationYear\" | \"creditCardSecurityCode\" | \"creditCardType\" | \"creditCardName\" | \"creditCardGivenName\" | \"creditCardMiddleName\" | \"creditCardFamilyName\" | \"emailAddress\" | \"familyName\" | \"fullStreetAddress\" | \"givenName\" | \"jobTitle\" | \"location\" | \"middleName\" | \"namePrefix\" | \"nameSuffix\" | \"nickname\" | \"organizationName\" | \"postalCode\" | \"streetAddressLine1\" | \"streetAddressLine2\" | \"sublocality\" | \"telephoneNumber\" | \"username\" | \"password\" | \"newPassword\" | \"oneTimeCode\" | \"birthdate\" | \"birthdateDay\" | \"birthdateMonth\" | \"birthdateYear\" | \"cellularEID\" | \"cellularIMEI\" | \"dateTime\" | \"flightNumber\" | \"shipmentTrackingNumber\" | undefined","required":false,"description":"Give the keyboard and the system information about the expected semantic meaning for the content that users enter. To disable autofill, set textContentType to `none`. Possible values for `textContentType` are: - `'none'` - `'URL'` - `'addressCity'` - `'addressCityAndState'` - `'addressState'` - `'countryName'` - `'creditCardNumber'` - `'creditCardExpiration'` (iOS 17+) - `'creditCardExpirationMonth'` (iOS 17+) - `'creditCardExpirationYear'` (iOS 17+) - `'creditCardSecurityCode'` (iOS 17+) - `'creditCardType'` (iOS 17+) - `'creditCardName'` (iOS 17+) - `'creditCardGivenName'` (iOS 17+) - `'creditCardMiddleName'` (iOS 17+) - `'creditCardFamilyName'` (iOS 17+) - `'emailAddress'` - `'familyName'` - `'fullStreetAddress'` - `'givenName'` - `'jobTitle'` - `'location'` - `'middleName'` - `'name'` - `'namePrefix'` - `'nameSuffix'` - `'nickname'` - `'organizationName'` - `'postalCode'` - `'streetAddressLine1'` - `'streetAddressLine2'` - `'sublocality'` - `'telephoneNumber'` - `'username'` - `'password'` - `'newPassword'` - `'oneTimeCode'` - `'birthdate'` (iOS 17+) - `'birthdateDay'` (iOS 17+) - `'birthdateMonth'` (iOS 17+) - `'birthdateYear'` (iOS 17+) - `'cellularEID'` (iOS 17.4+) - `'cellularIMEI'` (iOS 17.4+) - `'dateTime'` (iOS 15+) - `'flightNumber'` (iOS 15+) - `'shipmentTrackingNumber'` (iOS 15+)"},{"name":"scrollEnabled","type":"boolean | undefined","required":false,"description":"If false, scrolling of the text view will be disabled. The default value is true. Only works with multiline={true}"},{"name":"lineBreakStrategyIOS","type":"\"none\" | \"standard\" | \"hangul-word\" | \"push-out\" | undefined","required":false,"description":"Set line break strategy on iOS."},{"name":"lineBreakModeIOS","type":"\"middle\" | \"head\" | \"tail\" | \"clip\" | \"wordWrapping\" | \"char\" | undefined","required":false,"description":"Set line break mode on iOS."},{"name":"smartInsertDelete","type":"boolean | undefined","required":false,"description":"If `false`, the iOS system will not insert an extra space after a paste operation neither delete one or two spaces after a cut or delete operation. The default value is `true`."},{"name":"cursorColor","type":"ColorValue | null | undefined","required":false,"description":"When provided it will set the color of the cursor (or \"caret\") in the component. Unlike the behavior of `selectionColor` the cursor color will be set independently from the color of the text selection box."},{"name":"selectionHandleColor","type":"ColorValue | null | undefined","required":false,"description":"When provided it will set the color of the selection handles when highlighting text. Unlike the behavior of `selectionColor` the handle color will be set independently from the color of the text selection box."},{"name":"importantForAutofill","type":"\"auto\" | \"yes\" | \"no\" | \"noExcludeDescendants\" | \"yesExcludeDescendants\" | undefined","required":false,"description":"Determines whether the individual fields in your app should be included in a view structure for autofill purposes on Android API Level 26+. Defaults to auto. To disable auto complete, use `off`. *Android Only* The following values work on Android only: - `auto` - let Android decide - `no` - not important for autofill - `noExcludeDescendants` - this view and its children aren't important for autofill - `yes` - is important for autofill - `yesExcludeDescendants` - this view is important for autofill but its children aren't"},{"name":"disableFullscreenUI","type":"boolean | undefined","required":false,"description":"When false, if there is a small amount of space available around a text input (e.g. landscape orientation on a phone), the OS may choose to have the user edit the text inside of a full screen text input mode. When true, this feature is disabled and users will always edit the text directly inside of the text input. Defaults to false."},{"name":"inlineImageLeft","type":"string | undefined","required":false,"description":"If defined, the provided image resource will be rendered on the left."},{"name":"inlineImagePadding","type":"number | undefined","required":false,"description":"Padding between the inline image, if any, and the text input itself."},{"name":"numberOfLines","type":"number | undefined","required":false,"description":"Sets the number of lines for a TextInput. Use it with multiline set to true to be able to fill the lines."},{"name":"returnKeyLabel","type":"string | undefined","required":false,"description":"Sets the return key to the label. Use it instead of `returnKeyType`."},{"name":"textBreakStrategy","type":"\"simple\" | \"highQuality\" | \"balanced\" | undefined","required":false,"description":"Set text break strategy on Android API Level 23+, possible values are simple, highQuality, balanced The default value is simple."},{"name":"underlineColorAndroid","type":"ColorValue | undefined","required":false,"description":"The color of the textInput underline."},{"name":"textAlignVertical","type":"\"bottom\" | \"top\" | \"auto\" | \"center\" | undefined","required":false,"description":"Vertically align text when `multiline` is set to true"},{"name":"showSoftInputOnFocus","type":"boolean | undefined","required":false,"description":"When false, it will prevent the soft keyboard from showing when the field is focused. The default value is true"},{"name":"verticalAlign","type":"\"bottom\" | \"top\" | \"auto\" | \"middle\" | undefined","required":false,"description":"Vertically align text when `multiline` is set to true"},{"name":"ref","type":"Ref<TextInput> | undefined","required":false,"description":"Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref)."},{"name":"key","type":"Key | null | undefined","required":false,"description":""}]}],"platformNotes":{"web":"Single-line (or multiline) text entry. Control it with `value` + `onChangeText`, and style the box with the usual View style props. Common props: `placeholder`, `secureTextEntry` (passwords), `keyboardType`, and `multiline`.","ios":"Single-line (or multiline) text entry. Control it with `value` + `onChangeText`, and style the box with the usual View style props. Common props: `placeholder`, `secureTextEntry` (passwords), `keyboardType`, and `multiline`.","android":"Single-line (or multiline) text entry. Control it with `value` + `onChangeText`, and style the box with the usual View style props. Common props: `placeholder`, `secureTextEntry` (passwords), `keyboardType`, and `multiline`."}},{"slug":"textarea","name":"Textarea","category":"atoms","description":"Multi-line input, with character count, with toolbar.","source":"src/atoms/textarea/textarea.md","url":"https://canvas.nannier.com/ai/4.2.0/components/textarea.md","humanUrl":"https://canvas.nannier.com/components/textarea","exports":["Textarea","TextareaProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"TextareaProps","props":[{"name":"value","type":"string | undefined","required":false,"description":"Controlled text value. Omit and use `defaultValue` for uncontrolled use."},{"name":"onChangeText","type":"((next: string) => void) | undefined","required":false,"description":"Fired with the next text value on each edit."},{"name":"placeholder","type":"string | undefined","required":false,"description":"Placeholder shown while the field is empty."},{"name":"label","type":"string | undefined","required":false,"description":"The field's persistent label. Its placement is platform-adaptive: iOS and web render it ABOVE the field; Android renders the Material 3 in-container FLOATING label — a MULTILINE float pinned to the first text line at rest, floating to the top once the field is focused or filled. The label names the field for a11y."},{"name":"eyebrow","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"systemFocus","type":"boolean | undefined","required":false,"description":"Preserve the platform system focus outline.","default":"false"},{"name":"dense","type":"boolean | undefined","required":false,"description":"Dense paragraph-entry metrics matching the application field family.","default":"false"},{"name":"terminal","type":"boolean | undefined","required":false,"description":"Bare monospace prompt metrics for a terminal transcript composer. Implies embedded.","default":"false"},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":""},{"name":"readOnly","type":"boolean | undefined","required":false,"description":"Prevent edits while retaining focus and the resting appearance.","default":"false"},{"name":"required","type":"boolean | undefined","required":false,"description":"Marks the field as required: appends a destructive \"*\" to the label (decorative, never in the accessible name) and announces the field as required, through aria-required on the web and with the word in its name (\"Bio, required\") on iOS and Android. The star and the spoken word take effect only alongside `label`.","default":"false"},{"name":"rows","type":"number | undefined","required":false,"description":"Visible rows the field sizes to (4 when omitted). Sets the min height (rows times the skin's line plus the field's padding); the field still grows with content past this floor."},{"name":"showCount","type":"boolean | undefined","required":false,"description":"Show a live character-count line inside the field's own anatomy: an end-aligned muted caption under the control reading \"N / max\" (just \"N\" when no `maxLength` is set), where N is the current text length. When on, `maxLength` becomes a SOFT cap rather than a hard one: it is NOT forwarded to the native TextInput (a hard cap silently drops the extra keystroke, so the overage could never be seen), the user can type past it, and once N exceeds `maxLength` the count turns destructive AND the field enters its error state automatically (red border/underline). Leave `showCount` off to keep `maxLength` as a hard input cap.","default":"false"},{"name":"error","type":"boolean | undefined","required":false,"description":"Error/validation state: a destructive cue. `invalid` is an alias.","default":"false","group":0},{"name":"invalid","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the base text-sm field).","default":"false","group":1},{"name":"large","type":"boolean | undefined","required":false,"description":"Size (pick one; default is the base text-sm field).","default":"false","group":1},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Blocks editing and focus, and dims the field.","default":"false","group":1},{"name":"flush","type":"boolean | undefined","required":false,"description":"Borderless: drop the field's own border and radius so it sits flush inside a framed container (e.g. a Card with a formatting toolbar above it).","default":"false","group":1},{"name":"embedded","type":"boolean | undefined","required":false,"description":"Bare editor inside a parent-owned field surface and focus frame. Implies flush.","default":"false","group":1},{"name":"style","type":"StyleProp<Omit<TextStyle, SizingKey>>","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1},{"name":"textContentType","type":"\"none\" | \"name\" | \"URL\" | \"addressCity\" | \"addressCityAndState\" | \"addressState\" | \"countryName\" | \"creditCardNumber\" | \"creditCardExpiration\" | \"creditCardExpirationMonth\" | \"creditCardExpirationYear\" | \"creditCardSecurityCode\" | \"creditCardType\" | \"creditCardName\" | \"creditCardGivenName\" | \"creditCardMiddleName\" | \"creditCardFamilyName\" | \"emailAddress\" | \"familyName\" | \"fullStreetAddress\" | \"givenName\" | \"jobTitle\" | \"location\" | \"middleName\" | \"namePrefix\" | \"nameSuffix\" | \"nickname\" | \"organizationName\" | \"postalCode\" | \"streetAddressLine1\" | \"streetAddressLine2\" | \"sublocality\" | \"telephoneNumber\" | \"username\" | \"password\" | \"newPassword\" | \"oneTimeCode\" | \"birthdate\" | \"birthdateDay\" | \"birthdateMonth\" | \"birthdateYear\" | \"cellularEID\" | \"cellularIMEI\" | \"dateTime\" | \"flightNumber\" | \"shipmentTrackingNumber\" | undefined","required":false,"description":"Give the keyboard and the system information about the expected semantic meaning for the content that users enter. To disable autofill, set textContentType to `none`. Possible values for `textContentType` are: - `'none'` - `'URL'` - `'addressCity'` - `'addressCityAndState'` - `'addressState'` - `'countryName'` - `'creditCardNumber'` - `'creditCardExpiration'` (iOS 17+) - `'creditCardExpirationMonth'` (iOS 17+) - `'creditCardExpirationYear'` (iOS 17+) - `'creditCardSecurityCode'` (iOS 17+) - `'creditCardType'` (iOS 17+) - `'creditCardName'` (iOS 17+) - `'creditCardGivenName'` (iOS 17+) - `'creditCardMiddleName'` (iOS 17+) - `'creditCardFamilyName'` (iOS 17+) - `'emailAddress'` - `'familyName'` - `'fullStreetAddress'` - `'givenName'` - `'jobTitle'` - `'location'` - `'middleName'` - `'name'` - `'namePrefix'` - `'nameSuffix'` - `'nickname'` - `'organizationName'` - `'postalCode'` - `'streetAddressLine1'` - `'streetAddressLine2'` - `'sublocality'` - `'telephoneNumber'` - `'username'` - `'password'` - `'newPassword'` - `'oneTimeCode'` - `'birthdate'` (iOS 17+) - `'birthdateDay'` (iOS 17+) - `'birthdateMonth'` (iOS 17+) - `'birthdateYear'` (iOS 17+) - `'cellularEID'` (iOS 17.4+) - `'cellularIMEI'` (iOS 17.4+) - `'dateTime'` (iOS 15+) - `'flightNumber'` (iOS 15+) - `'shipmentTrackingNumber'` (iOS 15+)"},{"name":"autoCapitalize","type":"\"none\" | \"sentences\" | \"words\" | \"characters\" | undefined","required":false,"description":"Can tell TextInput to automatically capitalize certain characters. characters: all characters, words: first letter of each word sentences: first letter of each sentence (default) none: don't auto capitalize anything https://reactnative.dev/docs/textinput#autocapitalize"},{"name":"autoComplete","type":"\"country\" | \"name\" | \"off\" | \"nickname\" | \"username\" | \"password\" | \"2fa-app-otp\" | \"additional-name\" | \"address-line1\" | \"address-line2\" | \"birthdate-day\" | \"birthdate-full\" | \"birthdate-month\" | \"birthdate-year\" | \"cc-csc\" | \"cc-exp\" | \"cc-exp-day\" | \"cc-exp-month\" | \"cc-exp-year\" | \"cc-number\" | \"cc-name\" | \"cc-given-name\" | \"cc-middle-name\" | \"cc-family-name\" | \"cc-type\" | \"current-password\" | \"email\" | \"email-otp\" | \"flight-confirmation-code\" | \"flight-number\" | \"family-name\" | \"gender\" | \"gift-card-number\" | \"gift-card-pin\" | \"given-name\" | \"honorific-prefix\" | \"honorific-suffix\" | \"loyalty-account-number\" | \"name-family\" | \"name-given\" | \"name-middle\" | \"name-middle-initial\" | \"name-prefix\" | \"name-suffix\" | \"new-password\" | \"one-time-code\" | \"organization\" | \"organization-title\" | \"password-new\" | \"postal-address\" | \"postal-address-country\" | \"postal-address-dependent-locality\" | \"postal-address-extended\" | \"postal-address-extended-postal-code\" | \"postal-address-locality\" | \"postal-address-region\" | \"postal-address-unit\" | \"postal-code\" | \"promo-code\" | \"street-address\" | \"sms-otp\" | \"tel\" | \"tel-country-code\" | \"tel-national\" | \"tel-device\" | \"upi-vpa\" | \"url\" | \"wifi-password\" | \"username-new\" | undefined","required":false,"description":"Specifies autocomplete hints for the system, so it can provide autofill. On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content. To disable autocomplete, set autoComplete to off. The following values work across platforms: - `additional-name` - `address-line1` - `address-line2` - `cc-number` - `country` - `current-password` - `email` - `family-name` - `given-name` - `honorific-prefix` - `honorific-suffix` - `name` - `new-password` - `off` - `one-time-code` - `postal-code` - `street-address` - `tel` - `username` The following values work on iOS only: - `nickname` - `organization` - `organization-title` - `url` The following values work on Android only: - `birthdate-day` - `birthdate-full` - `birthdate-month` - `birthdate-year` - `cc-csc` - `cc-exp` - `cc-exp-day` - `cc-exp-month` - `cc-exp-year` - `2fa-app-otp` - `email-otp` - `flight-confirmation-code` - `flight-number` - `gender` - `gift-card-number` - `gift-card-pin` - `loyalty-account-number` - `name-family` - `name-given` - `name-middle` - `name-middle-initial` - `name-prefix` - `name-suffix` - `password` - `password-new` - `postal-address` - `postal-address-country` - `postal-address-dependent-locality` - `postal-address-extended` - `postal-address-extended-postal-code` - `postal-address-locality` - `postal-address-region` - `postal-address-unit` - `promo-code` - `sms-otp` - `tel-country-code` - `tel-national` - `tel-device` - `upi-vpa` - `wifi-password` - `username-new`"},{"name":"autoCorrect","type":"boolean | undefined","required":false,"description":"If false, disables auto-correct. The default value is true.","default":"false"},{"name":"autoFocus","type":"boolean | undefined","required":false,"description":"If true, focuses the input on componentDidMount. The default value is false.","default":"false"},{"name":"defaultValue","type":"string | undefined","required":false,"description":"Provides an initial value that will change when the user starts typing. Useful for simple use-cases where you don't want to deal with listening to events and updating the value prop to keep the controlled state in sync."},{"name":"keyboardType","type":"KeyboardTypeOptions | undefined","required":false,"description":"enum(\"default\", 'numeric', 'email-address', \"ascii-capable\", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search', 'visible-password') Determines which keyboard to open, e.g.numeric. The following values work across platforms: - default - numeric - email-address - phone-pad The following values work on iOS: - ascii-capable - numbers-and-punctuation - url - number-pad - name-phone-pad - decimal-pad - twitter - web-search The following values work on Android: - visible-password"},{"name":"inputMode","type":"InputModeOptions | undefined","required":false,"description":"Works like the inputmode attribute in HTML, it determines which keyboard to open, e.g. numeric and has precedence over keyboardType."},{"name":"maxLength","type":"number | undefined","required":false,"description":"Limits the maximum number of characters that can be entered. Use this instead of implementing the logic in JS to avoid flicker."},{"name":"onBlur","type":"((e: BlurEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input is blurred Note: If you are trying to find the last value of TextInput, you can use the `onEndEditing` event, which is fired upon completion of editing."},{"name":"onFocus","type":"((e: FocusEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input is focused"},{"name":"onSubmitEditing","type":"((e: TextInputSubmitEditingEvent) => void) | undefined","required":false,"description":"Callback that is called when the text input's submit button is pressed."},{"name":"onKeyPress","type":"((e: TextInputKeyPressEvent) => void) | undefined","required":false,"description":"Callback that is called when a key is pressed. This will be called with `{ nativeEvent: { key: keyValue } }` where keyValue is 'Enter' or 'Backspace' for respective keys and the typed-in character otherwise including ' ' for space. Fires before onChange callbacks. Note: on Android only the inputs from soft keyboard are handled, not the hardware keyboard inputs."},{"name":"returnKeyType","type":"ReturnKeyTypeOptions | undefined","required":false,"description":"enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call') Determines how the return key should look."},{"name":"secureTextEntry","type":"boolean | undefined","required":false,"description":"If true, the text input obscures the text entered so that sensitive text like passwords stay secure. The default value is false.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"Used to locate this view in end-to-end tests"},{"name":"ref","type":"React.Ref<RNTextInput>","required":false,"description":"Ref to the underlying React Native host. Supports object refs and callback refs; native methods follow the platform's behavior."},{"name":"xxxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xs","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"sm","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"md","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"lg","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"xxxl","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"wide","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"wider","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"widest","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"page","type":"boolean | undefined","required":false,"description":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge.","default":"false","group":2},{"name":"start","type":"boolean | undefined","required":false,"description":"Pin a capped component to the leading edge instead of centering it in its column.","default":"false","group":2}],"groups":[{"title":"State","pickOne":true,"note":"State (pick one; orthogonal to size)."},{"title":"Size","pickOne":true,"note":"Size (pick one; default is the base text-sm field)."},{"title":"Measure","pickOne":true,"note":"Measure (pick one; omit to take the parent's bounds). Caps the component at a step of the width scale, centered in its column; `start` pins it to the leading edge."}],"inherits":["MeasureProps"]}],"platformNotes":{"web":"Multi-line input, with character count, with toolbar.\n\nPass `label` (and `required`) to name the field:\niOS and web render the label\nabove the control, while Android floats the Material 3 in-container label at the\ntop of the multiline box, making room for itself at the user's text size and\ntruncating on one line when it is longer than the box while the field's\naccessible name stays the whole label.\nThe required star is decorative: a screen\nreader hears the field as required,\nfrom `aria-required` on the web and from its\nname (\"Bio, required\") on iOS and Android.\nThe box fills the parent it is given; a step of its\nown (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container\nstep sets its measure.\n\nThe box is the single-line Input's on each platform. On the web it is the sunken\nwell with a 1 px hairline that steps to the subtle ink on hover, takes the `ring`\nedge and a 4 px accent halo on focus and the `destructive` edge on error, with a\n400 value on a 1.55 line; the count is an 11 px mono caption (\"12 / 280\").\niOS keeps\nits 8 pt `card` box with the error wash and a tabular count (\"12/280\").\nAndroid uses\nthe same opaque muted surface as the other filled fields, and its count sits at the\nend of the supporting-text row.\nIts label uses `primary-text` when focused and\n`destructive-text` on error. The over-limit character count also uses\n`destructive-text` on every platform. Without `rows` the field starts four rows tall.\n\nInside an overlay, Escape follows the overlay's cancellation policy. A supplied\n`onKeyPress` runs first and can call `preventDefault()` to handle Escape locally.\nCancelling an IME candidate keeps the overlay open.\n\n`dense` preserves application paragraph fields with 13/19.5 semibold values,\nthe dense field inset and explicit visible rows. `eyebrow` supplies the matching\nweb label. `accessibilityLabel` overrides the visible label’s accessible name;\n`readOnly` prevents edits without dimming or removing the field from focus.\n`systemFocus` keeps the platform system focus outline.\n\n`embedded` renders a bare editor inside a parent-owned field surface and focus frame, as used by Chat. It implies `flush` and removes the independent backing and focus outline; the parent must provide a visible focus treatment.","ios":"Multi-line input, with character count, with toolbar.\n\nPass `label` (and `required`) to name the field:\niOS renders the label above the control.\nThe required star is decorative: a screen\nreader hears the field as required,\nfrom its name (\"Bio, required\").\nThe box fills the parent it is given; a step of its\nown (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container\nstep sets its measure.\n\nThe box is the single-line Input's on each platform. On the web it is the sunken\nwell with a 1 px hairline that steps to the subtle ink on hover, takes the `ring`\nedge and a 4 px accent halo on focus and the `destructive` edge on error, with a\n400 value on a 1.55 line; the count is an 11 px mono caption (\"12 / 280\").\niOS keeps\nits 8 pt `card` box with the error wash and a tabular count (\"12/280\").\nIts label uses `primary-text` when focused and\n`destructive-text` on error. The over-limit character count also uses\n`destructive-text` on every platform. Without `rows` the field starts four rows tall.\n\nInside an overlay, Escape follows the overlay's cancellation policy. A supplied\n`onKeyPress` runs first and can call `preventDefault()` to handle Escape locally.\nCancelling an IME candidate keeps the overlay open.\n\n`dense` preserves application paragraph fields with 13/19.5 semibold values,\nthe dense field inset and explicit visible rows. `eyebrow` supplies the matching\nweb label. `accessibilityLabel` overrides the visible label’s accessible name;\n`readOnly` prevents edits without dimming or removing the field from focus.\n`systemFocus` keeps the platform system focus outline.\n\n`embedded` renders a bare editor inside a parent-owned field surface and focus frame, as used by Chat. It implies `flush` and removes the independent backing and focus outline; the parent must provide a visible focus treatment.","android":"Multi-line input, with character count, with toolbar.\n\nPass `label` (and `required`) to name the field:\nAndroid floats the Material 3 in-container label at the top of the multiline box, making room for itself at the user's text size and truncating on one line when it is longer than the box while the field's accessible name stays the whole label.\nThe required star is decorative: a screen\nreader hears the field as required,\nfrom its name (\"Bio, required\").\nThe box fills the parent it is given; a step of its\nown (`xs`, `lg`, …, with `start` to pin it to the leading edge) or a Container\nstep sets its measure.\n\nThe box is the single-line Input's on each platform. On the web it is the sunken\nwell with a 1 px hairline that steps to the subtle ink on hover, takes the `ring`\nedge and a 4 px accent halo on focus and the `destructive` edge on error, with a\n400 value on a 1.55 line; the count is an 11 px mono caption (\"12 / 280\").\nAndroid uses\nthe same opaque muted surface as the other filled fields, and its count sits at the\nend of the supporting-text row.\nIts label uses `primary-text` when focused and\n`destructive-text` on error. The over-limit character count also uses\n`destructive-text` on every platform. Without `rows` the field starts four rows tall.\n\nInside an overlay, Escape follows the overlay's cancellation policy. A supplied\n`onKeyPress` runs first and can call `preventDefault()` to handle Escape locally.\nCancelling an IME candidate keeps the overlay open.\n\n`dense` preserves application paragraph fields with 13/19.5 semibold values,\nthe dense field inset and explicit visible rows. `eyebrow` supplies the matching\nweb label. `accessibilityLabel` overrides the visible label’s accessible name;\n`readOnly` prevents edits without dimming or removing the field from focus.\n`systemFocus` keeps the platform system focus outline.\n\n`embedded` renders a bare editor inside a parent-owned field surface and focus frame, as used by Chat. It implies `flush` and removes the independent backing and focus outline; the parent must provide a visible focus treatment."}},{"slug":"toast","name":"Toast","category":"organisms","description":"A transient notification card. Render a `<Toast>` directly, or drive them imperatively: mount a `<ToastProvider>` near your app root and call `toast(...)` from the `useToast()` hook to enqueue auto-dismissing toasts that stack over the app.","source":"src/organisms/toast/toast.md","url":"https://canvas.nannier.com/ai/4.2.0/components/toast.md","humanUrl":"https://canvas.nannier.com/components/toast","exports":["Toast","ToastAction","ToastHandle","ToastOptions","ToastProps","ToastProvider","useToast"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"ToastProps","props":[{"name":"brief","type":"boolean | undefined","required":false,"description":"A single-line notification pill without extra chrome.","default":"false"},{"name":"message","type":"string","required":true,"description":"The headline line (required)."},{"name":"description","type":"string | undefined","required":false,"description":"A secondary line under the message."},{"name":"action","type":"ToastAction | undefined","required":false,"description":"A trailing action button (e.g. Undo)."},{"name":"success","type":"boolean | undefined","required":false,"description":"Green success intent (icon + tint).","default":"false"},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Red danger intent (icon + tint). This is the name the intent axis uses across the kit (Button, AlertDialog, and every chart) and the one the design hand-off uses.","default":"false"},{"name":"warning","type":"boolean | undefined","required":false,"description":"Amber warning intent (icon + tint).","default":"false"},{"name":"info","type":"boolean | undefined","required":false,"description":"Brand-tinted informational intent (icon + tint).","default":"false"},{"name":"icon","type":"ReactNode","required":false,"description":"Override the auto intent icon; pass any node, or omit to use the intent glyph."},{"name":"onDismiss","type":"(() => void) | undefined","required":false,"description":"When provided, render a trailing dismiss (x) that calls this."},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element."},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":"Outer layout composition only (width/flex within a parent), never a restyle hook."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"A transient notification card. Render a `<Toast>` directly, or drive them imperatively: mount a `<ToastProvider>` near your app root and call `toast(...)` from the `useToast()` hook to enqueue auto-dismissing toasts that stack over the app.\n\nOn the web and iOS the toast is a floating card:\nthe overlay panel at the card corner, up to 380px wide, with the intent glyph in its status color (the accent's sparkle on a neutral toast), a medium message over a muted description, and the action in the accent. A `brief` toast hugs its one line.\nAndroid keeps the Material 3 snackbar on the inverse fill.\n\nFor a single brief notification, use `<ToastProvider single brief safeArea duration={2800}\nbottomInset={28} horizontalInset={20}>`. New messages replace the current toast and\nrestart its lifetime. `safeArea` includes the device safe area. `brief` retains a\nsingle line without the dismiss\ncontrol; Android retains its snackbar skin.\n\nTab reaches a toast's action and its dismiss, and Escape dismisses the toast that holds\nfocus, then returns focus to where it came from. A toast the user is not in never takes\nEscape, so the key still reaches the page or the Dialog under it. A provider toast always\nanswers it (a `brief` one too), a directly rendered `<Toast>` when it has `onDismiss`.\nOn\niOS the same dismiss answers the accessibility escape (the VoiceOver two-finger scrub,\nand Escape under Full Keyboard Access).\nAndroid delivers no Escape key to a view, and\nits back gesture is never taken for a toast.","ios":"A transient notification card. Render a `<Toast>` directly, or drive them imperatively: mount a `<ToastProvider>` near your app root and call `toast(...)` from the `useToast()` hook to enqueue auto-dismissing toasts that stack over the app.\n\nOn iOS the toast is a floating card:\nthe overlay panel at the card corner, up to 380px wide, with the intent glyph in its status color (the accent's sparkle on a neutral toast), a medium message over a muted description, and the action in the accent. A `brief` toast hugs its one line.\n\nFor a single brief notification, use `<ToastProvider single brief safeArea duration={2800}\nbottomInset={28} horizontalInset={20}>`. New messages replace the current toast and\nrestart its lifetime. `safeArea` includes the device safe area. `brief` retains a\nsingle line without the dismiss\ncontrol.\n\nTab reaches a toast's action and its dismiss, and Escape dismisses the toast that holds\nfocus, then returns focus to where it came from. A toast the user is not in never takes\nEscape, so the key still reaches the page or the Dialog under it. A provider toast always\nanswers it (a `brief` one too), a directly rendered `<Toast>` when it has `onDismiss`.\nOn\niOS the same dismiss answers the accessibility escape (the VoiceOver two-finger scrub,\nand Escape under Full Keyboard Access).","android":"A transient notification card. Render a `<Toast>` directly, or drive them imperatively: mount a `<ToastProvider>` near your app root and call `toast(...)` from the `useToast()` hook to enqueue auto-dismissing toasts that stack over the app.\n\nAndroid keeps the Material 3 snackbar on the inverse fill.\n\nFor a single brief notification, use `<ToastProvider single brief safeArea duration={2800}\nbottomInset={28} horizontalInset={20}>`. New messages replace the current toast and\nrestart its lifetime. `safeArea` includes the device safe area. `brief` retains a\nsingle line without the dismiss\ncontrol; Android retains its snackbar skin.\n\nTab reaches a toast's action and its dismiss, and Escape dismisses the toast that holds\nfocus, then returns focus to where it came from. A toast the user is not in never takes\nEscape, so the key still reaches the page or the Dialog under it. A provider toast always\nanswers it (a `brief` one too), a directly rendered `<Toast>` when it has `onDismiss`.\nAndroid delivers no Escape key to a view, and\nits back gesture is never taken for a toast."}},{"slug":"tooltip","name":"Tooltip","category":"atoms","description":"Small floating helper text on hover or focus.","source":"src/atoms/tooltip/tooltip.md","url":"https://canvas.nannier.com/ai/4.2.0/components/tooltip.md","humanUrl":"https://canvas.nannier.com/components/tooltip","exports":["Tooltip","TooltipProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"TooltipProps","props":[{"name":"children","type":"ReactNode","required":false,"description":"An arbitrary element for the tip to hang off: an existing Button, Chip, or any other control that already owns its own press and accessible name. The highest-precedence trigger: children win over `iconTrigger`, `textTrigger`, and the default Button. The child renders as-is and stays the single interactive, labelled element; the root view Tooltip wraps it in takes no accessibility role and no tab stop, listens only for hover and focus, and never claims the press, so a Button child keeps its `onPress` and the tip does not toggle on tap."},{"name":"label","type":"string | undefined","required":false,"description":"The tip text shown in the bubble.","group":0},{"name":"trigger","type":"string | undefined","required":false,"description":"The element the tip describes. By default rendered as a text `<Button outline small>`; set `iconTrigger` for a ghost icon button, `textTrigger` to hang the tip off an inline pressable word, or pass `children` to wrap an element you already have. Ignored when `children` is passed.","group":0},{"name":"iconTrigger","type":"boolean | undefined","required":false,"description":"Render the trigger as a ghost icon button (a settings glyph) instead of the text Button. When set, `trigger` (the label string) is ignored. Ignored when `children` is passed, which takes precedence.","default":"false","group":0},{"name":"textTrigger","type":"boolean | undefined","required":false,"description":"Render the `trigger` string as a pressable inline word (an underlined hover-text affordance) rather than the default text Button, so the tip can hang off a run of body copy. Orthogonal to placement (top/left/right/bottom). Ignored when `children` or `iconTrigger` is set, both of which take precedence.","default":"false","group":0},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled visibility. Omit for uncontrolled: the tip shows while the trigger is hovered or focused, and a tap toggles it (the touch analogue of hover) on the built-in triggers. An element trigger (`children`) has no tap toggle (the child keeps its own press), and native platforms never fire hover, so `open` is the native and touch path for that trigger.","default":"false","group":0},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fired when the bubble is shown/hidden.","group":1},{"name":"top","type":"boolean | undefined","required":false,"description":"Placement (pick one; default is top).","default":"false","group":2},{"name":"bottom","type":"boolean | undefined","required":false,"description":"Placement (pick one; default is top).","default":"false","group":2},{"name":"left","type":"boolean | undefined","required":false,"description":"Placement (pick one; default is top).","default":"false","group":2},{"name":"right","type":"boolean | undefined","required":false,"description":"Placement (pick one; default is top).","default":"false","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":2}],"groups":[{"title":"The tip text shown in the bubble","pickOne":false},{"title":"Fired when the bubble is shown/hidden","pickOne":false},{"title":"Placement","pickOne":true,"note":"Placement (pick one; default is top)."}],"inherits":[]}],"platformNotes":{"web":"Small floating helper text on hover or focus.\n\nThe bubble floats over the page: it is drawn in the overlay layer of the nearest\n`OverlayProvider`, placed against its trigger, and changes no layout, so a tip on a\ntable row's action never grows the cell. It centers on the trigger at the side you\npick, flips to the opposite side when the visible area has no room there, and slides\nto stay inside it. Moving the pointer from the trigger onto the bubble keeps it up.\nWith no `OverlayProvider` mounted it still floats, on an absolute anchor beside the\ntrigger, but an ancestor that clips its content can then cut it off.\n\nThe bubble inverts against the page (dark in the light scheme, light in the dark one)\nand sets its text in Dark Factory's label type;\niOS, which has no tooltip, shows the\nsame bubble, and Android keeps the Material 3 plain tooltip.\n\nThe trigger is a boolean axis of its own, resolved first match wins:\n\n- `children`, an element you already have (an icon `Button`, a `Chip`, any\n  control that owns its own press and accessible name). The child renders as-is\n  and the tip hangs off it through a wrapper that only LISTENS: no accessibility\n  role, no tab stop, and no press of its own, so the child stays the single\n  interactive, labelled element, keeps its `onPress`, and the tip never toggles\n  on tap. Hover and focus on the child both raise it.\n- `iconTrigger`, a ghost icon button carrying a settings glyph.\n- `textTrigger`, the `trigger` string as a pressable inline word.\n- Otherwise the default: the `trigger` string as an outline Button.\n\nHover and focus are pointer-and-keyboard affordances. Touch pointers are\nskipped,\nand iOS and Android never fire hover at all.\nOn touch the built-in\ntriggers toggle the tip on tap (tap again to close it; a tip is never modal, so a\ntap elsewhere goes to the page). A long press is not taken: it belongs to the\nplatform and to the control. An element trigger has no tap toggle either, because\nthat press belongs to the child, so on native and on touch the controlled `open`\nprop is the way to show its tip: drive it from whatever the platform does offer (a\nlong press the child handles, a selected row, an inline help toggle). Keyboard\nfocus, including a hardware keyboard on a tablet, raises the tip on every platform.\n\nEscape hides an open tip and leaves focus where it is (WCAG 1.4.13: hover and focus\ncontent is dismissable without moving the pointer or focus). It goes through the kit's\none Escape owner, so a tip inside a Dialog or Popover closes first and the next Escape\nreaches its host; a closed tip takes no Escape at all. A controlled tip reports the\nclose through `onOpenChange(false)`.\nOn iOS the same close answers the accessibility\nescape (the VoiceOver two-finger scrub, and Escape on a hardware keyboard under Full\nKeyboard Access).\nAndroid delivers no Escape key to a view, and its back gesture is\nnever taken for a tip, so there the tip closes with focus or the controlled `open`.","ios":"Small floating helper text on hover or focus.\n\nThe bubble floats over the page: it is drawn in the overlay layer of the nearest\n`OverlayProvider`, placed against its trigger, and changes no layout, so a tip on a\ntable row's action never grows the cell. It centers on the trigger at the side you\npick, flips to the opposite side when the visible area has no room there, and slides\nto stay inside it. Moving the pointer from the trigger onto the bubble keeps it up.\nWith no `OverlayProvider` mounted it still floats, on an absolute anchor beside the\ntrigger, but an ancestor that clips its content can then cut it off.\n\nThe bubble inverts against the page (dark in the light scheme, light in the dark one)\nand sets its text in Dark Factory's label type;\niOS, which has no tooltip, shows the same bubble.\n\nThe trigger is a boolean axis of its own, resolved first match wins:\n\n- `children`, an element you already have (an icon `Button`, a `Chip`, any\n  control that owns its own press and accessible name). The child renders as-is\n  and the tip hangs off it through a wrapper that only LISTENS: no accessibility\n  role, no tab stop, and no press of its own, so the child stays the single\n  interactive, labelled element, keeps its `onPress`, and the tip never toggles\n  on tap. Hover and focus on the child both raise it.\n- `iconTrigger`, a ghost icon button carrying a settings glyph.\n- `textTrigger`, the `trigger` string as a pressable inline word.\n- Otherwise the default: the `trigger` string as an outline Button.\n\nHover and focus are pointer-and-keyboard affordances. Touch pointers are\nskipped,\nand the native apps never fire hover at all.\nOn touch the built-in\ntriggers toggle the tip on tap (tap again to close it; a tip is never modal, so a\ntap elsewhere goes to the page). A long press is not taken: it belongs to the\nplatform and to the control. An element trigger has no tap toggle either, because\nthat press belongs to the child, so on native and on touch the controlled `open`\nprop is the way to show its tip: drive it from whatever the platform does offer (a\nlong press the child handles, a selected row, an inline help toggle). Keyboard\nfocus, including a hardware keyboard on a tablet, raises the tip on every platform.\n\nEscape hides an open tip and leaves focus where it is (WCAG 1.4.13: hover and focus\ncontent is dismissable without moving the pointer or focus). It goes through the kit's\none Escape owner, so a tip inside a Dialog or Popover closes first and the next Escape\nreaches its host; a closed tip takes no Escape at all. A controlled tip reports the\nclose through `onOpenChange(false)`.\nOn iOS the same close answers the accessibility\nescape (the VoiceOver two-finger scrub, and Escape on a hardware keyboard under Full\nKeyboard Access).","android":"Small floating helper text on hover or focus.\n\nThe bubble floats over the page: it is drawn in the overlay layer of the nearest\n`OverlayProvider`, placed against its trigger, and changes no layout, so a tip on a\ntable row's action never grows the cell. It centers on the trigger at the side you\npick, flips to the opposite side when the visible area has no room there, and slides\nto stay inside it. Moving the pointer from the trigger onto the bubble keeps it up.\nWith no `OverlayProvider` mounted it still floats, on an absolute anchor beside the\ntrigger, but an ancestor that clips its content can then cut it off.\n\nThe bubble inverts against the page (dark in the light scheme, light in the dark one)\nand sets its text in Dark Factory's label type;\nAndroid keeps the Material 3 plain tooltip.\n\nThe trigger is a boolean axis of its own, resolved first match wins:\n\n- `children`, an element you already have (an icon `Button`, a `Chip`, any\n  control that owns its own press and accessible name). The child renders as-is\n  and the tip hangs off it through a wrapper that only LISTENS: no accessibility\n  role, no tab stop, and no press of its own, so the child stays the single\n  interactive, labelled element, keeps its `onPress`, and the tip never toggles\n  on tap. Hover and focus on the child both raise it.\n- `iconTrigger`, a ghost icon button carrying a settings glyph.\n- `textTrigger`, the `trigger` string as a pressable inline word.\n- Otherwise the default: the `trigger` string as an outline Button.\n\nHover and focus are pointer-and-keyboard affordances. Touch pointers are\nskipped,\nand the native apps never fire hover at all.\nOn touch the built-in\ntriggers toggle the tip on tap (tap again to close it; a tip is never modal, so a\ntap elsewhere goes to the page). A long press is not taken: it belongs to the\nplatform and to the control. An element trigger has no tap toggle either, because\nthat press belongs to the child, so on native and on touch the controlled `open`\nprop is the way to show its tip: drive it from whatever the platform does offer (a\nlong press the child handles, a selected row, an inline help toggle). Keyboard\nfocus, including a hardware keyboard on a tablet, raises the tip on every platform.\n\nEscape hides an open tip and leaves focus where it is (WCAG 1.4.13: hover and focus\ncontent is dismissable without moving the pointer or focus). It goes through the kit's\none Escape owner, so a tip inside a Dialog or Popover closes first and the next Escape\nreaches its host; a closed tip takes no Escape at all. A controlled tip reports the\nclose through `onOpenChange(false)`.\nAndroid delivers no Escape key to a view, and its back gesture is\nnever taken for a tip, so there the tip closes with focus or the controlled `open`."}},{"slug":"treemap","name":"Treemap","category":"charts","description":"Squarified value tiles: each datum becomes a ramp-colored rectangle whose area is proportional to its value, packed largest-first with near-square aspect ratios, with the label and formatted value rendered inside only when the tile fits them.","source":"src/charts/treemap/treemap.md","url":"https://canvas.nannier.com/ai/4.2.0/components/treemap.md","humanUrl":"https://canvas.nannier.com/components/treemap","exports":["Treemap","TreemapDatum","TreemapProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"TreemapProps","props":[{"name":"data","type":"TreemapDatum[]","required":true,"description":"The tiles, laid out largest first by the squarified algorithm."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the tiles."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default 240 plot height; compact is 160).","default":"false","group":0},{"name":"partitioned","type":"boolean | undefined","required":false,"description":"Slice successive values along alternating axes, keeping the data order.","default":"false","group":0},{"name":"outlined","type":"boolean | undefined","required":false,"description":"Show pale series washes with colored outlines and large readable values.","default":"false","group":0},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":0},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats tile values and the flag (data formatting, not styling).","group":0},{"name":"selected","type":"number | null | undefined","required":false,"description":"Press-to-inspect: the selected tile index (controlled). Pass null for none.","group":0},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Press-to-inspect: the initially selected tile (uncontrolled).","group":0},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press selects a tile (or clears it with null).","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Density","pickOne":false,"note":"Density (omit for the default 240 plot height; compact is 160)."}],"inherits":[]}],"platformNotes":{"web":"Squarified value tiles: each datum becomes a ramp-colored rectangle whose area is proportional to its value, packed largest-first with near-square aspect ratios, with the label and formatted value rendered inside only when the tile fits them.\n\nFlat one-level data; nesting and drill-down are deferred scope. Press a tile to flag its value and share (the others dim); the accessible name carries every tile with its share regardless of which labels fit.","ios":"Squarified value tiles: each datum becomes a ramp-colored rectangle whose area is proportional to its value, packed largest-first with near-square aspect ratios, with the label and formatted value rendered inside only when the tile fits them.\n\nFlat one-level data; nesting and drill-down are deferred scope. Press a tile to flag its value and share (the others dim); the accessible name carries every tile with its share regardless of which labels fit.","android":"Squarified value tiles: each datum becomes a ramp-colored rectangle whose area is proportional to its value, packed largest-first with near-square aspect ratios, with the label and formatted value rendered inside only when the tile fits them.\n\nFlat one-level data; nesting and drill-down are deferred scope. Press a tile to flag its value and share (the others dim); the accessible name carries every tile with its share regardless of which labels fit."}},{"slug":"typography","name":"Typography","category":"atoms","description":"Type scale classes for headings, body text, and helper styles.","source":"src/atoms/typography/typography.md","url":"https://canvas.nannier.com/ai/4.2.0/components/typography.md","humanUrl":"https://canvas.nannier.com/components/typography","exports":["Typography","TypographyProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"TypographyProps","props":[{"name":"terminal","type":"boolean | undefined","required":false,"description":"Use the system terminal face while retaining the selected reading role and size.","default":"false"},{"name":"section","type":"boolean | undefined","required":false,"description":"A section heading owning its count, metadata and trailing actions.","default":"false"},{"name":"count","type":"string | number | undefined","required":false,"description":""},{"name":"description","type":"string | undefined","required":false,"description":""},{"name":"actions","type":"ReactNode","required":false,"description":""},{"name":"subheading","type":"boolean | undefined","required":false,"description":"Exact Argus reading roles; these preserve the original dense web type.","default":"false"},{"name":"label","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"micro","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"tag","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"eyebrow","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"eyebrowLg","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"stageLabel","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"statValue","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"metricValue","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"formValue","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"extraBold","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"uppercase","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"foreground","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"inverse","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"action","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"actionForeground","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"info","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"hue","type":"number | undefined","required":false,"description":"Hue-keyed stage text; deep in light schemes, pastel in dark."},{"name":"inverseHint","type":"boolean | undefined","required":false,"description":"De-emphasized white ink over branded surfaces.","default":"false"},{"name":"inverseSubtle","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"inverseMuted","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"inverseSoft","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"inverseFaint","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"right","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"center","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"numberOfLines","type":"number | undefined","required":false,"description":""},{"name":"onTextLayout","type":"((event: NativeSyntheticEvent<TextLayoutEventData>) => void) | undefined","required":false,"description":"The text's laid-out lines, as React Native reports them (each line's `y`, `height`, `ascender` and `descender`, so its baseline is `y + height - descender`): for drawing something on the text's own lines, such as an illustration over a word. Fired by the native platforms; the web does not report it."},{"name":"accessibilityRole","type":"AccessibilityRole | undefined","required":false,"description":""},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":""},{"name":"level","type":"HeadingLevel | undefined","required":false,"description":"The heading level assistive tech hears, independent of the visual role: a heading role exposes its own level (display and h1 at 1, h2 to h5 at 2 to 5) unless this overrides it, so `<Typography h3 level={2}>` draws the h3 size and is announced as a level-2 heading (a real `<h2>` on the web). On a non-heading role it makes the text a heading at that level. Semantics only: it never changes the look. `href` still wins (a link is not a heading)."},{"name":"displayLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"singleLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"lockupLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"denseLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"compactLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"labelLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"captionLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"smallLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"strongLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"bodyLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"relaxedLeading","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"displayTracking","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"tightTracking","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"referenceTracking","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"labelTracking","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"eyebrowTracking","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"wideTracking","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"expandedTracking","type":"boolean | undefined","required":false,"description":"","default":"false"},{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"hero","type":"boolean | undefined","required":false,"description":"The hand-off's hero headline: the display face sized by the window, `clamp(56px, 7.2vw, 112px)` at a .94 line and -.045em tracking (56 px on a phone, 103.68 at a 1440 window, 112 from 1556 up). One per page, its lead line. A level-1 heading.","default":"false","group":0},{"name":"pageTitle","type":"boolean | undefined","required":false,"description":"The hand-off's page title (a component page's name): the display face sized by the window, `clamp(40px, 5vw, 64px)` at a 1.0 line and -.04em tracking. A level-1 heading.","default":"false","group":0},{"name":"sectionTitle","type":"boolean | undefined","required":false,"description":"A page section's heading (a component page's Playground, Variants...): the display face, 500 28/1.1, -.02em. A level-2 heading.","default":"false","group":0},{"name":"cardTitle","type":"boolean | undefined","required":false,"description":"A feature card's title: the display face, 500 22/1.15, -.02em. A level-3 heading.","default":"false","group":0},{"name":"panelTitle","type":"boolean | undefined","required":false,"description":"A panel's or dialog's title: the display face, 500 20/1.2, -.02em.","default":"false","group":0},{"name":"tagline","type":"boolean | undefined","required":false,"description":"The one-line tagline under a section's title: the display face, 400 22/1.3, -.015em, in the foreground ink.","default":"false","group":0},{"name":"pageLead","type":"boolean | undefined","required":false,"description":"A page's summary under its title: 400 18/1.55 in the secondary ink.","default":"false","group":0},{"name":"sectionLead","type":"boolean | undefined","required":false,"description":"A section's introductory paragraph: 400 17/1.55 in the secondary ink.","default":"false","group":0},{"name":"cardBody","type":"boolean | undefined","required":false,"description":"A feature card's description: 400 14/1.55 in the secondary ink.","default":"false","group":0},{"name":"sectionNote","type":"boolean | undefined","required":false,"description":"The note under a page section's heading: 400 14/1.5 in the secondary ink.","default":"false","group":0},{"name":"pageBody","type":"boolean | undefined","required":false,"description":"A page's body paragraph (a component page's usage line): 400 15/1.6 in the secondary ink, held to an 80ch measure.","default":"false","group":0},{"name":"pageNote","type":"boolean | undefined","required":false,"description":"A page's note paragraph (a component page's overview and docs notes): 400 14/1.6 in the secondary ink, held to an 80ch measure.","default":"false","group":0},{"name":"pageLabel","type":"boolean | undefined","required":false,"description":"A page's label (a panel's \"Props\", a rail's group header, a table's header cell, a previous/next eyebrow): 500 11/1 tracked .08em in caps, in the subtle ink. Pass `mono` for the mono face, as the other page roles do. Not the `eyebrow`, which is the type table's accent-ink label tracked .1em.","default":"false","group":0},{"name":"knobLabel","type":"boolean | undefined","required":false,"description":"A knob panel's label row (a knob's name, and the type hint beside it with `muted`, the third ink): 500 12/1 in the secondary ink. Pass `mono` for the mono face, as the hand-off's page does.","default":"false","group":0},{"name":"guideTitle","type":"boolean | undefined","required":false,"description":"A guidance card's title: 600 16/1.3 in the interface face. A level-3 heading.","default":"false","group":0},{"name":"guideBody","type":"boolean | undefined","required":false,"description":"A guidance card's paragraph: 400 13.5/1.6 in the secondary ink.","default":"false","group":0},{"name":"pagerName","type":"boolean | undefined","required":false,"description":"A pager card's name (the previous or next page under its label): the display face, 500 18 on the face's own 22 line, in the foreground ink.","default":"false","group":0},{"name":"specMeta","type":"boolean | undefined","required":false,"description":"A reference sheet's meta cell (a props table's type or default): 400 12/1.55 in the foreground ink. Pass `mono` for the mono face and `subtle` or `muted` for the ink, as the sheet's cells take them.","default":"false","group":0},{"name":"specText","type":"boolean | undefined","required":false,"description":"A reference sheet's text cell (a props table's description, an inherited-props note): 400 13/1.55 in the secondary ink.","default":"false","group":0},{"name":"pagerLabel","type":"boolean | undefined","required":false,"description":"A pager card's label (Previous, Next): the page label's 500 11 tracked .08em in caps and subtle ink on the face's own 14 line (the hand-off sets no ratio there). Pass `mono` for the mono face, as the page label takes it.","default":"false","group":0},{"name":"legendLabel","type":"boolean | undefined","required":false,"description":"A legend row's label (an anatomy part's name beside its numbered disc): 500 14 on the face's own 18 line, in the foreground ink.","default":"false","group":0},{"name":"tileCaption","type":"boolean | undefined","required":false,"description":"A specimen tile's caption strip (a size or state name under its well): 500 12 on the face's own 16 line, in the secondary ink. Pass `mono` for the mono face.","default":"false","group":0},{"name":"variantTitle","type":"boolean | undefined","required":false,"description":"A variant card's title (an example's label over its note and snippet): 500 14/1.3 in the interface face and the foreground ink.","default":"false","group":0},{"name":"linkName","type":"boolean | undefined","required":false,"description":"A link tile's name (a related component beside its arrow): 600 14 on the face's own 18 line, in the foreground ink.","default":"false","group":0},{"name":"subsectionTitle","type":"boolean | undefined","required":false,"description":"A page section's own sub-heading (the \"Related components\" title over its tiles): 600 16 on the face's own 20 line in the interface face. A level-3 heading.","default":"false","group":0},{"name":"cardNote","type":"boolean | undefined","required":false,"description":"A section card's foot caption, or a note inside the card: 400 12/1.6 (19.2) in the subtle ink. Pass `mono` for the mono face, as the hand-off sets it.","default":"false","group":0},{"name":"codeLabel","type":"boolean | undefined","required":false,"description":"A code name on its own line (a variant row's label, a token's name): 400 12 on the mono face's 16 line, in the secondary ink. Pass `mono` for the mono face.","default":"false","group":0},{"name":"inlineNote","type":"boolean | undefined","required":false,"description":"A short note beside a specimen: 400 12 on the interface face's 15 line, in the subtle ink.","default":"false","group":0},{"name":"tileTitle","type":"boolean | undefined","required":false,"description":"A tile's title: the display face, 500 15/1.3 (19.5), in the foreground ink.","default":"false","group":0},{"name":"gridLabel","type":"boolean | undefined","required":false,"description":"A grid widget's label: 500 10 mono tracked .08em in caps on a 13 line, in the subtle ink.","default":"false","group":0},{"name":"tick","type":"boolean | undefined","required":false,"description":"A scale's tick label: 500 10 mono on a 13 line, in the secondary ink.","default":"false","group":0},{"name":"rowLabel","type":"boolean | undefined","required":false,"description":"A stat row's label: 500 11/1 mono tracked .06em in caps, in the subtle ink.","default":"false","group":0},{"name":"rowValue","type":"boolean | undefined","required":false,"description":"A stat row's value beside its label: the display face, 500 22/1, -.02em, in the foreground ink.","default":"false","group":0},{"name":"headlineValue","type":"boolean | undefined","required":false,"description":"A card's headline figure: the display face, 500 26/1, -.02em, in the foreground ink.","default":"false","group":0},{"name":"bigNumber","type":"boolean | undefined","required":false,"description":"A card's big number: the display face, 500 40/1, -.03em, in the foreground ink.","default":"false","group":0},{"name":"unit","type":"boolean | undefined","required":false,"description":"The unit after a figure: 400 16 on the interface face's 20 line, in the subtle ink. Nest it inside the figure's Typography so it shares the figure's baseline (`<Typography bigNumber>107<Typography unit> components</Typography></Typography>`).","default":"false","group":0},{"name":"paneTitle","type":"boolean | undefined","required":false,"description":"A pane's title: the display face, 500 16/1.2, -.01em, in the foreground ink. Pass `level` to announce it as a heading.","default":"false","group":0},{"name":"sampleLabel","type":"boolean | undefined","required":false,"description":"A sample's caption (a hue number, a series name): 400 11 on the mono face's 14 line, in the subtle ink. Pass `mono`.","default":"false","group":0},{"name":"sampleMeta","type":"boolean | undefined","required":false,"description":"A sample's meta line (a hex value, a size): 400 10 on the mono face's 13 line, in the subtle ink. Pass `mono`.","default":"false","group":0},{"name":"base","type":"boolean | undefined","required":false,"description":"The 14 px body in the foreground ink: 400 14 on the interface face's 18 line (a description list's value).","default":"false","group":0},{"name":"display","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"h1","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"h2","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"h3","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"h4","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"h5","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"lead","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"body","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"small","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"tiny","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"muted","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"caption","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"code","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"mono","type":"boolean | undefined","required":false,"description":"","default":"false","group":0},{"name":"inline","type":"boolean | undefined","required":false,"description":"With `code`: the prose code chip, a word of code inside a sentence. Regular weight at .88 of the surrounding reading role's size (pass that role beside it, `lead`, `small`, `pageBody`, `pageNote`, `pageLead` or `sectionLead`; body when none), the chip's own small corner, 1 by 5 padding, the surface fill and a hairline rim. Natively a Text nested in a Text draws the fill and horizontal padding only. Without `code` it does nothing.","default":"false","group":0},{"name":"subtle","type":"boolean | undefined","required":false,"description":"Tone (pick one; orthogonal to role). When omitted, the role's own color is used.","default":"false","group":1},{"name":"primary","type":"boolean | undefined","required":false,"description":"Tone (pick one; orthogonal to role). When omitted, the role's own color is used.","default":"false","group":1},{"name":"destructive","type":"boolean | undefined","required":false,"description":"Tone (pick one; orthogonal to role). When omitted, the role's own color is used.","default":"false","group":1},{"name":"success","type":"boolean | undefined","required":false,"description":"Tone (pick one; orthogonal to role). When omitted, the role's own color is used.","default":"false","group":1},{"name":"warning","type":"boolean | undefined","required":false,"description":"Tone (pick one; orthogonal to role). When omitted, the role's own color is used.","default":"false","group":1},{"name":"cyan","type":"boolean | undefined","required":false,"description":"The fixed cyan series hue (the hand-off's `--cyan`, `chart-2`) as an ink, whatever the palette, solved to 4.5:1 on the scheme's surfaces.","default":"false","group":1},{"name":"mint","type":"boolean | undefined","required":false,"description":"The fixed mint series hue (the hand-off's `--mint`, `chart-3`) as an ink, whatever the palette, solved like `cyan`.","default":"false","group":1},{"name":"regular","type":"boolean | undefined","required":false,"description":"Weight (pick one; orthogonal to role). When omitted, the role's own weight is used.","default":"false","group":2},{"name":"medium","type":"boolean | undefined","required":false,"description":"Weight (pick one; orthogonal to role). When omitted, the role's own weight is used.","default":"false","group":2},{"name":"semibold","type":"boolean | undefined","required":false,"description":"Weight (pick one; orthogonal to role). When omitted, the role's own weight is used.","default":"false","group":2},{"name":"bold","type":"boolean | undefined","required":false,"description":"Weight (pick one; orthogonal to role). When omitted, the role's own weight is used.","default":"false","group":2},{"name":"tightLeading","type":"boolean | undefined","required":false,"description":"Leading (orthogonal to role). Pulls the line box in to 1.25x the font size for a STACKED LOCKUP, where two lines read as one unit (a wordmark over its tagline, a title over its subtitle) and the roles reading leading would leave dead air between them. Only ever tightens, so it is safe on every role. Omit for prose: the role's own line height is the reading value.","default":"false","group":2},{"name":"natural","type":"boolean | undefined","required":false,"description":"Leading: the face's own normal line at the role's size, the line the hand-off's text takes where it sets a size with no ratio (JetBrains Mono 10, 11 and 12 px on 13, 14 and 16; Instrument Sans 12, 13 and 14 on 15, 16 and 18; Bricolage Grotesque 14 and 15 on 17 and 18). The face is the one the text is set in (`mono`, a display role, or the interface face). A size off the measured table (10 to 28 px) keeps the role's line.","default":"false","group":2},{"name":"underline","type":"boolean | undefined","required":false,"description":"Decoration (orthogonal to role / tone / weight). Underlines the text so an inline text link reads as a link, replacing the banned raw `textDecorationLine` style shim. Combines freely with every role, tone, and weight; omit for undecorated text.","default":"false","group":2},{"name":"italic","type":"boolean | undefined","required":false,"description":"Slant (orthogonal to role / tone / weight / decoration). Sets the text in the face's italic, for a word set off in prose or the italic mark of a formatting toolbar. Omit for upright text.","default":"false","group":2},{"name":"tabular","type":"boolean | undefined","required":false,"description":"Numerals (orthogonal to role / tone / weight). Tabular figures: every digit the same width, for numbers read down a column or updated in place (a table's figures, a live metric, a counter), so the column lines up and a changing value holds still. Never for prose, which keeps the face's own proportional figures.","default":"false","group":2},{"name":"href","type":"string | undefined","required":false,"description":"Renders this text as a REAL inline link on the web: react-native-web gives the root element a browser link with this destination, so middle-click, cmd-click, and open-in-new-tab work and assistive tech hears a link. Native platforms have no browser links and ignore it, so pair `href` with an `onPress` running the same navigation through the host's router. Combine with `underline` for the conventional link look. When a heading role and `href` are both set, the link role wins.","group":2},{"name":"hrefAttrs","type":"{ target?: \"_blank\" | \"_self\"; rel?: string; download?: boolean | string; } | undefined","required":false,"description":"Attributes forwarded with `href` on the web: `target`, `rel`, `download`.","group":2},{"name":"onPress","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Press handler; the native navigation path for `href` (fires on web too).","group":2},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":2},{"name":"style","type":"StyleProp<TextStyle>","required":false,"description":"For layout/positioning composition only (margins handled by Row/Column). Not a styling escape hatch: size, color, and weight come from the props above.","group":2}],"groups":[{"title":"Role","pickOne":true,"note":"Role (pick one; default is the plain body style). First-match precedence."},{"title":"Tone","pickOne":true,"note":"Tone (pick one; orthogonal to role). When omitted, the role's own color is used."},{"title":"Weight","pickOne":true,"note":"Weight (pick one; orthogonal to role). When omitted, the role's own weight is used."}],"inherits":[]}],"platformNotes":{"web":"Type scale classes for headings, body text, and helper styles.\n\n`terminal` selects the system terminal face while retaining the reading role, size, weight, and ink: pair it with `tiny`, `caption`, `small`, or a heading. The web uses the system monospace stack beginning with `ui-monospace`, SFMono-Regular, and Menlo; native platforms use Menlo or their monospace alias. Existing `mono` and code typography keep their current behavior.\n\nArgus reading roles include `subheading`, `label`, `micro`, `tag`, `eyebrow`,\n`eyebrowLg`, `stageLabel`, `statValue`, `metricValue`, and `formValue`. These extend\nTypography itself. Semantic leading and tracking props preserve the reference's\nfractional web metrics; for example `labelLeading` is the compact label line box\nand `wideTracking` its uppercase eyebrow tracking. `extraBold` selects the 800 face.\nThe owner's exact-reference directive preserves the existing 9.5px eyebrows.\n\n`foreground`, `inverse`, `action`, `actionForeground`, and `info` name the ink;\n`hue` gives a stage its theme-aware identity text. `inverseHint`, `inverseSubtle`,\n`inverseMuted`, `inverseSoft`, and `inverseFaint` express the reference's hierarchy\non branded surfaces. `numberOfLines` truncates a reading block, and accessible\nlabels and roles stay with the text. Existing roles and defaults keep working.\n\n`section` lets a heading own its `count`, muted `description` and trailing `actions`.\nThey wrap along a shared baseline, preserving dense section anatomy. Pair it with\n`h5 bold labelLeading` or `subheading bold labelLeading`; the latter uses the compact\nmetadata metrics. Actions move to the far edge and wrap below on narrow surfaces.\n\n`level={1..6}` sets the heading level assistive tech hears without changing the\nlook. A heading role exposes its own level (`hero`, `pageTitle`, `display` and `h1` at 1, `sectionTitle` at 2, `cardTitle` at 3, `h2` to `h5` at\n2 to 5, a `section` heading 6), so `<Typography h3 level={2}>` draws the h3 size\nand is announced as a level-2 heading: a real `<h2>` on the web, the header trait\nnatively. On a non-heading role `level` makes the text a heading at that level.\n`href` still wins: a link is never a heading. The level is a number because it is\nthe document outline, not a style (the same reason Row's `span` is one); the look\nstays on the boolean role axis.\n\n`hero` and `pageTitle` are the two fluid headlines, sized by the window rather than a\nfixed step: `hero` is the landing headline (56 to 112 px at 7.2 percent of the window,\na .94 line, tracked -.045em) and `pageTitle` a page's own title (40 to 64 px at 5\npercent, a 1.0 line, tracked -.04em). Both are medium-weight display face.\n\nThe page roles are the hand-off pages' own titles and leads, outside its type table:\n`sectionTitle` (a page section's heading, display 500 28/1.1), `cardTitle` (a feature\ncard's title, display 500 22/1.15), `panelTitle` (a panel's title, display 500 20/1.2),\n`tagline` (the line under a section's title, display 400 22/1.3), `pageLead` (a page's\nsummary, 18/1.55, held to the hand-off's 72ch measure), `sectionLead` (a section's introduction, 17/1.55), `cardBody` (a feature\ncard's description, 14/1.55), `sectionNote` (the note under a section's heading,\n14/1.5), `pageBody` (a page's body paragraph, 15/1.6) and `pageNote` (a page's note paragraph,\n14/1.6), the last six in the secondary ink and the last two held to an 80ch measure.\nFour more are the component page's own: `pageLabel` (a panel's \"Props\", a rail's group\nheader, a table's header cell, a previous/next eyebrow: 500 11/1 tracked .08em in caps, in\nthe subtle ink; pass `mono` for the mono face, as the hand-off's page does), `knobLabel` (a\nknob panel's label row, a knob's name and its type hint: 500 12/1 in the secondary ink, the\nhint beside it in the `muted` tone, the third ink; pass `mono` for the mono face), `guideTitle` (a\nguidance card's title, 600 16/1.3 in the interface face, a level-3 heading) and `guideBody`\n(a guidance card's paragraph, 400 13.5/1.6 in the secondary ink). `pageLabel` is not the\n`eyebrow`: that is the type table's accent-ink label tracked .1em. `pagerName` is the\nprevious or next card's name under its label: the display face, 500 18 on the face's own 22\nline (the hand-off sets no ratio), in the foreground ink. Two are the reference sheet's cells\n(the component page's props table): `specMeta` (a type or default cell, 400 12/1.55; pass\n`mono` for the mono face and `subtle` or `muted` for the ink, as the sheet's cells take\nthem) and `specText` (a description cell or an inherited-props note, 400 13/1.55 in the\nsecondary ink).\nline the same way: `pagerLabel` (the previous or next card's label over its name, the page\nlabel's 500 11 tracked .08em in caps and subtle ink on a 14 line; pass `mono`), `legendLabel`\n(a legend row's label beside its numbered disc, 500 14 on an 18 line in the foreground ink)\nand `tileCaption` (a specimen tile's caption strip, 500 12 on a 16 line in the secondary ink;\npass `mono`). Three more are the component page's Variants and Tokens sections: `variantTitle`\n(a variant card's title over its note and snippet, 500 14/1.3 in the foreground ink),\n`linkName` (a link tile's name beside its arrow, 600 14 on the face's own 18 line in the\nforeground ink) and `subsectionTitle` (a section's own sub-heading over a grid of tiles,\n600 16 on the face's own 20 line in the interface face, a level-3 heading).\n\nThe section pages' card roles are the hand-off's section cards' own text, one role per\nvalue set however many pages set it: `cardNote` (a card's foot caption or an in-card note,\n400 12/1.6 in the subtle ink; pass `mono`), `codeLabel` (a code name on its own line, a\nvariant row's label or a token's name, 400 12 on a 16 line in the secondary ink; pass\n`mono`), `inlineNote` (a note beside a specimen, 400 12 on a 15 line in the subtle ink),\n`tileTitle` (a tile's title, display 500 15/1.3), `paneTitle` (a pane's title, display 500\n16/1.2 tracked -.01em; pass `level` to announce it), `gridLabel` (a grid widget's label, 500\n10 mono tracked .08em in caps on a 13 line, subtle ink), `tick` (a scale's tick label, 500 10\nmono on a 13 line, secondary ink), `rowLabel` (a stat row's label, 500 11/1 mono tracked\n.06em in caps, subtle ink), `rowValue` (the value beside it, display 500 22/1 tracked\n-.02em), `headlineValue` (a card's headline figure, display 500 26/1 tracked -.02em),\n`bigNumber` (a card's big number, display 500 40/1 tracked -.03em), `unit` (the unit after a\nfigure, 400 16 on a 20 line in the subtle ink, nested in the figure's Typography so it shares\nits baseline), `sampleLabel` and `sampleMeta` (a sample's caption and meta line, 400 11 on 14\nand 400 10 on 13 in the subtle ink; pass `mono`) and `base` (the 14 px body in the\nforeground ink, 400 14 on an 18 line). The figures and titles rank with the titles, the\nlabels with the page label, and the notes, samples, unit and base with the reading roles.\n\n`natural` sets the text on its face's own normal line at the role's size, the line the\nhand-off's text takes where it sets a size with no ratio: JetBrains Mono 10, 11 and 12 px on\n13, 14 and 16, Instrument Sans 12, 13 and 14 on 15, 16 and 18, Bricolage Grotesque 14 and\n15 on 17 and 18 (measured in Chromium on the faces, 10 to 28 px). The face is the one the\ntext is set in: `mono`, a display role, or the interface face. It sits on the leading axis\nafter the fixed ratios and before `tightLeading`.\n\n`cyan` and `mint` are two inks on the tone axis that name a fixed series hue whatever the\npalette (the hand-off's `--cyan` and `--mint`, the `chart-2` and `chart-3` tokens), each\nsolved to 4.5:1 on the scheme's surfaces. Tone precedence: `destructive`, `warning`,\n`success`, `cyan`, `mint`, `primary`, `subtle`, `muted`.\n\n`code` is the standalone code pill (regular 13px mono on the muted fill, a 6 radius and 2\nby 6 padding). `code inline` is the prose code chip, a word of code inside a sentence: the\nhand-off's inline `<code>`, regular weight at .88 of the surrounding reading role's size\n(pass that role beside it, `lead`, `small`, `pageBody`, `pageNote`, `pageLead` or\n`sectionLead`; body when none), a 5 radius, 1 by 5 padding, the surface fill and a 1px\nhairline rim. The chip keeps its regular weight inside a strong run, as the hand-off\napplies bold and code independently. Under glass the fill is the same ink tint the pill\ntakes. Natively a Text nested in a Text has no border and no vertical box, so there the\nchip draws its fill and horizontal padding only; `inline` without `code` does nothing.","ios":"Type scale classes for headings, body text, and helper styles.\n\n`terminal` selects the system terminal face while retaining the reading role, size, weight, and ink: pair it with `tiny`, `caption`, `small`, or a heading. The web uses the system monospace stack beginning with `ui-monospace`, SFMono-Regular, and Menlo; native platforms use Menlo or their monospace alias. Existing `mono` and code typography keep their current behavior.\n\nArgus reading roles include `subheading`, `label`, `micro`, `tag`, `eyebrow`,\n`eyebrowLg`, `stageLabel`, `statValue`, `metricValue`, and `formValue`. These extend\nTypography itself. Semantic leading and tracking props preserve the reference's\nfractional web metrics; for example `labelLeading` is the compact label line box\nand `wideTracking` its uppercase eyebrow tracking. `extraBold` selects the 800 face.\nThe owner's exact-reference directive preserves the existing 9.5px eyebrows.\n\n`foreground`, `inverse`, `action`, `actionForeground`, and `info` name the ink;\n`hue` gives a stage its theme-aware identity text. `inverseHint`, `inverseSubtle`,\n`inverseMuted`, `inverseSoft`, and `inverseFaint` express the reference's hierarchy\non branded surfaces. `numberOfLines` truncates a reading block, and accessible\nlabels and roles stay with the text. Existing roles and defaults keep working.\n\n`section` lets a heading own its `count`, muted `description` and trailing `actions`.\nThey wrap along a shared baseline, preserving dense section anatomy. Pair it with\n`h5 bold labelLeading` or `subheading bold labelLeading`; the latter uses the compact\nmetadata metrics. Actions move to the far edge and wrap below on narrow surfaces.\n\n`level={1..6}` sets the heading level assistive tech hears without changing the\nlook. A heading role exposes its own level (`hero`, `pageTitle`, `display` and `h1` at 1, `sectionTitle` at 2, `cardTitle` at 3, `h2` to `h5` at\n2 to 5, a `section` heading 6), so `<Typography h3 level={2}>` draws the h3 size\nand is announced as a level-2 heading: a real `<h2>` on the web, the header trait\nnatively. On a non-heading role `level` makes the text a heading at that level.\n`href` still wins: a link is never a heading. The level is a number because it is\nthe document outline, not a style (the same reason Row's `span` is one); the look\nstays on the boolean role axis.\n\n`hero` and `pageTitle` are the two fluid headlines, sized by the window rather than a\nfixed step: `hero` is the landing headline (56 to 112 px at 7.2 percent of the window,\na .94 line, tracked -.045em) and `pageTitle` a page's own title (40 to 64 px at 5\npercent, a 1.0 line, tracked -.04em). Both are medium-weight display face.\n\nThe page roles are the hand-off pages' own titles and leads, outside its type table:\n`sectionTitle` (a page section's heading, display 500 28/1.1), `cardTitle` (a feature\ncard's title, display 500 22/1.15), `panelTitle` (a panel's title, display 500 20/1.2),\n`tagline` (the line under a section's title, display 400 22/1.3), `pageLead` (a page's\nsummary, 18/1.55, held to the hand-off's 72ch measure), `sectionLead` (a section's introduction, 17/1.55), `cardBody` (a feature\ncard's description, 14/1.55), `sectionNote` (the note under a section's heading,\n14/1.5), `pageBody` (a page's body paragraph, 15/1.6) and `pageNote` (a page's note paragraph,\n14/1.6), the last six in the secondary ink and the last two held to an 80ch measure.\nFour more are the component page's own: `pageLabel` (a panel's \"Props\", a rail's group\nheader, a table's header cell, a previous/next eyebrow: 500 11/1 tracked .08em in caps, in\nthe subtle ink; pass `mono` for the mono face, as the hand-off's page does), `knobLabel` (a\nknob panel's label row, a knob's name and its type hint: 500 12/1 in the secondary ink, the\nhint beside it in the `muted` tone, the third ink; pass `mono` for the mono face), `guideTitle` (a\nguidance card's title, 600 16/1.3 in the interface face, a level-3 heading) and `guideBody`\n(a guidance card's paragraph, 400 13.5/1.6 in the secondary ink). `pageLabel` is not the\n`eyebrow`: that is the type table's accent-ink label tracked .1em. `pagerName` is the\nprevious or next card's name under its label: the display face, 500 18 on the face's own 22\nline (the hand-off sets no ratio), in the foreground ink. Two are the reference sheet's cells\n(the component page's props table): `specMeta` (a type or default cell, 400 12/1.55; pass\n`mono` for the mono face and `subtle` or `muted` for the ink, as the sheet's cells take\nthem) and `specText` (a description cell or an inherited-props note, 400 13/1.55 in the\nsecondary ink).\nline the same way: `pagerLabel` (the previous or next card's label over its name, the page\nlabel's 500 11 tracked .08em in caps and subtle ink on a 14 line; pass `mono`), `legendLabel`\n(a legend row's label beside its numbered disc, 500 14 on an 18 line in the foreground ink)\nand `tileCaption` (a specimen tile's caption strip, 500 12 on a 16 line in the secondary ink;\npass `mono`). Three more are the component page's Variants and Tokens sections: `variantTitle`\n(a variant card's title over its note and snippet, 500 14/1.3 in the foreground ink),\n`linkName` (a link tile's name beside its arrow, 600 14 on the face's own 18 line in the\nforeground ink) and `subsectionTitle` (a section's own sub-heading over a grid of tiles,\n600 16 on the face's own 20 line in the interface face, a level-3 heading).\n\nThe section pages' card roles are the hand-off's section cards' own text, one role per\nvalue set however many pages set it: `cardNote` (a card's foot caption or an in-card note,\n400 12/1.6 in the subtle ink; pass `mono`), `codeLabel` (a code name on its own line, a\nvariant row's label or a token's name, 400 12 on a 16 line in the secondary ink; pass\n`mono`), `inlineNote` (a note beside a specimen, 400 12 on a 15 line in the subtle ink),\n`tileTitle` (a tile's title, display 500 15/1.3), `paneTitle` (a pane's title, display 500\n16/1.2 tracked -.01em; pass `level` to announce it), `gridLabel` (a grid widget's label, 500\n10 mono tracked .08em in caps on a 13 line, subtle ink), `tick` (a scale's tick label, 500 10\nmono on a 13 line, secondary ink), `rowLabel` (a stat row's label, 500 11/1 mono tracked\n.06em in caps, subtle ink), `rowValue` (the value beside it, display 500 22/1 tracked\n-.02em), `headlineValue` (a card's headline figure, display 500 26/1 tracked -.02em),\n`bigNumber` (a card's big number, display 500 40/1 tracked -.03em), `unit` (the unit after a\nfigure, 400 16 on a 20 line in the subtle ink, nested in the figure's Typography so it shares\nits baseline), `sampleLabel` and `sampleMeta` (a sample's caption and meta line, 400 11 on 14\nand 400 10 on 13 in the subtle ink; pass `mono`) and `base` (the 14 px body in the\nforeground ink, 400 14 on an 18 line). The figures and titles rank with the titles, the\nlabels with the page label, and the notes, samples, unit and base with the reading roles.\n\n`natural` sets the text on its face's own normal line at the role's size, the line the\nhand-off's text takes where it sets a size with no ratio: JetBrains Mono 10, 11 and 12 px on\n13, 14 and 16, Instrument Sans 12, 13 and 14 on 15, 16 and 18, Bricolage Grotesque 14 and\n15 on 17 and 18 (measured in Chromium on the faces, 10 to 28 px). The face is the one the\ntext is set in: `mono`, a display role, or the interface face. It sits on the leading axis\nafter the fixed ratios and before `tightLeading`.\n\n`cyan` and `mint` are two inks on the tone axis that name a fixed series hue whatever the\npalette (the hand-off's `--cyan` and `--mint`, the `chart-2` and `chart-3` tokens), each\nsolved to 4.5:1 on the scheme's surfaces. Tone precedence: `destructive`, `warning`,\n`success`, `cyan`, `mint`, `primary`, `subtle`, `muted`.\n\n`code` is the standalone code pill (regular 13px mono on the muted fill, a 6 radius and 2\nby 6 padding). `code inline` is the prose code chip, a word of code inside a sentence: the\nhand-off's inline `<code>`, regular weight at .88 of the surrounding reading role's size\n(pass that role beside it, `lead`, `small`, `pageBody`, `pageNote`, `pageLead` or\n`sectionLead`; body when none), a 5 radius, 1 by 5 padding, the surface fill and a 1px\nhairline rim. The chip keeps its regular weight inside a strong run, as the hand-off\napplies bold and code independently. Under glass the fill is the same ink tint the pill\ntakes. Natively a Text nested in a Text has no border and no vertical box, so there the\nchip draws its fill and horizontal padding only; `inline` without `code` does nothing.","android":"Type scale classes for headings, body text, and helper styles.\n\n`terminal` selects the system terminal face while retaining the reading role, size, weight, and ink: pair it with `tiny`, `caption`, `small`, or a heading. The web uses the system monospace stack beginning with `ui-monospace`, SFMono-Regular, and Menlo; native platforms use Menlo or their monospace alias. Existing `mono` and code typography keep their current behavior.\n\nArgus reading roles include `subheading`, `label`, `micro`, `tag`, `eyebrow`,\n`eyebrowLg`, `stageLabel`, `statValue`, `metricValue`, and `formValue`. These extend\nTypography itself. Semantic leading and tracking props preserve the reference's\nfractional web metrics; for example `labelLeading` is the compact label line box\nand `wideTracking` its uppercase eyebrow tracking. `extraBold` selects the 800 face.\nThe owner's exact-reference directive preserves the existing 9.5px eyebrows.\n\n`foreground`, `inverse`, `action`, `actionForeground`, and `info` name the ink;\n`hue` gives a stage its theme-aware identity text. `inverseHint`, `inverseSubtle`,\n`inverseMuted`, `inverseSoft`, and `inverseFaint` express the reference's hierarchy\non branded surfaces. `numberOfLines` truncates a reading block, and accessible\nlabels and roles stay with the text. Existing roles and defaults keep working.\n\n`section` lets a heading own its `count`, muted `description` and trailing `actions`.\nThey wrap along a shared baseline, preserving dense section anatomy. Pair it with\n`h5 bold labelLeading` or `subheading bold labelLeading`; the latter uses the compact\nmetadata metrics. Actions move to the far edge and wrap below on narrow surfaces.\n\n`level={1..6}` sets the heading level assistive tech hears without changing the\nlook. A heading role exposes its own level (`hero`, `pageTitle`, `display` and `h1` at 1, `sectionTitle` at 2, `cardTitle` at 3, `h2` to `h5` at\n2 to 5, a `section` heading 6), so `<Typography h3 level={2}>` draws the h3 size\nand is announced as a level-2 heading: a real `<h2>` on the web, the header trait\nnatively. On a non-heading role `level` makes the text a heading at that level.\n`href` still wins: a link is never a heading. The level is a number because it is\nthe document outline, not a style (the same reason Row's `span` is one); the look\nstays on the boolean role axis.\n\n`hero` and `pageTitle` are the two fluid headlines, sized by the window rather than a\nfixed step: `hero` is the landing headline (56 to 112 px at 7.2 percent of the window,\na .94 line, tracked -.045em) and `pageTitle` a page's own title (40 to 64 px at 5\npercent, a 1.0 line, tracked -.04em). Both are medium-weight display face.\n\nThe page roles are the hand-off pages' own titles and leads, outside its type table:\n`sectionTitle` (a page section's heading, display 500 28/1.1), `cardTitle` (a feature\ncard's title, display 500 22/1.15), `panelTitle` (a panel's title, display 500 20/1.2),\n`tagline` (the line under a section's title, display 400 22/1.3), `pageLead` (a page's\nsummary, 18/1.55, held to the hand-off's 72ch measure), `sectionLead` (a section's introduction, 17/1.55), `cardBody` (a feature\ncard's description, 14/1.55), `sectionNote` (the note under a section's heading,\n14/1.5), `pageBody` (a page's body paragraph, 15/1.6) and `pageNote` (a page's note paragraph,\n14/1.6), the last six in the secondary ink and the last two held to an 80ch measure.\nFour more are the component page's own: `pageLabel` (a panel's \"Props\", a rail's group\nheader, a table's header cell, a previous/next eyebrow: 500 11/1 tracked .08em in caps, in\nthe subtle ink; pass `mono` for the mono face, as the hand-off's page does), `knobLabel` (a\nknob panel's label row, a knob's name and its type hint: 500 12/1 in the secondary ink, the\nhint beside it in the `muted` tone, the third ink; pass `mono` for the mono face), `guideTitle` (a\nguidance card's title, 600 16/1.3 in the interface face, a level-3 heading) and `guideBody`\n(a guidance card's paragraph, 400 13.5/1.6 in the secondary ink). `pageLabel` is not the\n`eyebrow`: that is the type table's accent-ink label tracked .1em. `pagerName` is the\nprevious or next card's name under its label: the display face, 500 18 on the face's own 22\nline (the hand-off sets no ratio), in the foreground ink. Two are the reference sheet's cells\n(the component page's props table): `specMeta` (a type or default cell, 400 12/1.55; pass\n`mono` for the mono face and `subtle` or `muted` for the ink, as the sheet's cells take\nthem) and `specText` (a description cell or an inherited-props note, 400 13/1.55 in the\nsecondary ink).\nline the same way: `pagerLabel` (the previous or next card's label over its name, the page\nlabel's 500 11 tracked .08em in caps and subtle ink on a 14 line; pass `mono`), `legendLabel`\n(a legend row's label beside its numbered disc, 500 14 on an 18 line in the foreground ink)\nand `tileCaption` (a specimen tile's caption strip, 500 12 on a 16 line in the secondary ink;\npass `mono`). Three more are the component page's Variants and Tokens sections: `variantTitle`\n(a variant card's title over its note and snippet, 500 14/1.3 in the foreground ink),\n`linkName` (a link tile's name beside its arrow, 600 14 on the face's own 18 line in the\nforeground ink) and `subsectionTitle` (a section's own sub-heading over a grid of tiles,\n600 16 on the face's own 20 line in the interface face, a level-3 heading).\n\nThe section pages' card roles are the hand-off's section cards' own text, one role per\nvalue set however many pages set it: `cardNote` (a card's foot caption or an in-card note,\n400 12/1.6 in the subtle ink; pass `mono`), `codeLabel` (a code name on its own line, a\nvariant row's label or a token's name, 400 12 on a 16 line in the secondary ink; pass\n`mono`), `inlineNote` (a note beside a specimen, 400 12 on a 15 line in the subtle ink),\n`tileTitle` (a tile's title, display 500 15/1.3), `paneTitle` (a pane's title, display 500\n16/1.2 tracked -.01em; pass `level` to announce it), `gridLabel` (a grid widget's label, 500\n10 mono tracked .08em in caps on a 13 line, subtle ink), `tick` (a scale's tick label, 500 10\nmono on a 13 line, secondary ink), `rowLabel` (a stat row's label, 500 11/1 mono tracked\n.06em in caps, subtle ink), `rowValue` (the value beside it, display 500 22/1 tracked\n-.02em), `headlineValue` (a card's headline figure, display 500 26/1 tracked -.02em),\n`bigNumber` (a card's big number, display 500 40/1 tracked -.03em), `unit` (the unit after a\nfigure, 400 16 on a 20 line in the subtle ink, nested in the figure's Typography so it shares\nits baseline), `sampleLabel` and `sampleMeta` (a sample's caption and meta line, 400 11 on 14\nand 400 10 on 13 in the subtle ink; pass `mono`) and `base` (the 14 px body in the\nforeground ink, 400 14 on an 18 line). The figures and titles rank with the titles, the\nlabels with the page label, and the notes, samples, unit and base with the reading roles.\n\n`natural` sets the text on its face's own normal line at the role's size, the line the\nhand-off's text takes where it sets a size with no ratio: JetBrains Mono 10, 11 and 12 px on\n13, 14 and 16, Instrument Sans 12, 13 and 14 on 15, 16 and 18, Bricolage Grotesque 14 and\n15 on 17 and 18 (measured in Chromium on the faces, 10 to 28 px). The face is the one the\ntext is set in: `mono`, a display role, or the interface face. It sits on the leading axis\nafter the fixed ratios and before `tightLeading`.\n\n`cyan` and `mint` are two inks on the tone axis that name a fixed series hue whatever the\npalette (the hand-off's `--cyan` and `--mint`, the `chart-2` and `chart-3` tokens), each\nsolved to 4.5:1 on the scheme's surfaces. Tone precedence: `destructive`, `warning`,\n`success`, `cyan`, `mint`, `primary`, `subtle`, `muted`.\n\n`code` is the standalone code pill (regular 13px mono on the muted fill, a 6 radius and 2\nby 6 padding). `code inline` is the prose code chip, a word of code inside a sentence: the\nhand-off's inline `<code>`, regular weight at .88 of the surrounding reading role's size\n(pass that role beside it, `lead`, `small`, `pageBody`, `pageNote`, `pageLead` or\n`sectionLead`; body when none), a 5 radius, 1 by 5 padding, the surface fill and a 1px\nhairline rim. The chip keeps its regular weight inside a strong run, as the hand-off\napplies bold and code independently. Under glass the fill is the same ink tint the pill\ntakes. Natively a Text nested in a Text has no border and no vertical box, so there the\nchip draws its fill and horizontal padding only; `inline` without `code` does nothing."}},{"slug":"uptime-bar","name":"UptimeBar","category":"charts","description":"The statuspage strip: per-period status pills (operational, degraded, down, unknown) with a summary caption and edge labels.","source":"src/charts/uptime-bar/uptime-bar.md","url":"https://canvas.nannier.com/ai/4.2.0/components/uptime-bar.md","humanUrl":"https://canvas.nannier.com/components/uptime-bar","exports":["UptimeBar","UptimeBarProps","UptimePeriod"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"UptimeBarProps","props":[{"name":"periods","type":"UptimePeriod[]","required":true,"description":"The periods to render, oldest first; each becomes one pill."},{"name":"label","type":"string | undefined","required":false,"description":"What the strip measures (e.g. \"API\"); shown in the header and leading the accessible name."},{"name":"caption","type":"string | undefined","required":false,"description":"A summary at the header's right (e.g. \"99.98% uptime\")."},{"name":"startLabel","type":"string | undefined","required":false,"description":"Caption under the strip's left (oldest) edge (e.g. \"90 days ago\")."},{"name":"endLabel","type":"string | undefined","required":false,"description":"Caption under the strip's right (latest) edge (e.g. \"Today\")."},{"name":"midLabel","type":"string | undefined","required":false,"description":"Caption centred under the strip, between the edge captions (e.g. \"1 incident · 2 degraded days\")."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default pill height).","default":"false","group":0},{"name":"detailed","type":"boolean | undefined","required":false,"description":"Display header and taller history marks for a status overview.","default":"false","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Density","pickOne":false,"note":"Density (omit for the default pill height)."}],"inherits":[]}],"platformNotes":{"web":"The statuspage strip: per-period status pills (operational, degraded, down, unknown) with a summary caption and edge labels.\n\nThe pills run in a single row, oldest on the left, colored operational green, degraded amber, down red, or unknown muted (precedence down > degraded > unknown; an unmarked period is operational). An optional `caption` summarizes the strip above it, and `startLabel`/`endLabel` caption the physical edges below. The strip is a time axis, so it keeps left-to-right ordering in every locale, and its accessible name tallies every status.\n\n`detailed` uses a display header, taller history marks and neutral unknown periods. Hovering a period expands it with an overshooting transition; Reduced Motion keeps it still.","ios":"The statuspage strip: per-period status pills (operational, degraded, down, unknown) with a summary caption and edge labels.\n\nThe pills run in a single row, oldest on the left, colored operational green, degraded amber, down red, or unknown muted (precedence down > degraded > unknown; an unmarked period is operational). An optional `caption` summarizes the strip above it, and `startLabel`/`endLabel` caption the physical edges below. The strip is a time axis, so it keeps left-to-right ordering in every locale, and its accessible name tallies every status.\n\n`detailed` uses a display header, taller history marks and neutral unknown periods. Hovering a period expands it with an overshooting transition; Reduced Motion keeps it still.","android":"The statuspage strip: per-period status pills (operational, degraded, down, unknown) with a summary caption and edge labels.\n\nThe pills run in a single row, oldest on the left, colored operational green, degraded amber, down red, or unknown muted (precedence down > degraded > unknown; an unmarked period is operational). An optional `caption` summarizes the strip above it, and `startLabel`/`endLabel` caption the physical edges below. The strip is a time axis, so it keeps left-to-right ordering in every locale, and its accessible name tallies every status.\n\n`detailed` uses a display header, taller history marks and neutral unknown periods. Hovering a period expands it with an overshooting transition; Reduced Motion keeps it still."}},{"slug":"video","name":"Video","category":"atoms","description":"Plays a clip with an optional poster: tap to play inline, or full transport controls (the platform's own on iOS and Android, the kit's bar on the web), with boolean fit, `autoplay`, `loop` and `muted` props.","source":"src/atoms/video/video.md","url":"https://canvas.nannier.com/ai/4.2.0/components/video.md","humanUrl":"https://canvas.nannier.com/components/video","exports":["Video","VideoProps","VideoRadius","VideoSource"],"dependencies":[{"name":"expo-video","range":"*","optional":true},{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"VideoProps","props":[{"name":"source","type":"VideoSource","required":true,"description":"The clip: a remote `{ uri }`, or a bundled asset from `require(...)`."},{"name":"poster","type":"ImageSourcePropType | undefined","required":false,"description":"A still shown until the clip's first frame is on screen: a remote `{ uri }` or a bundled asset."},{"name":"contain","type":"boolean | undefined","required":false,"description":"Fit: show the whole picture, letterboxed on black. The default (pick one).","default":"false","group":0},{"name":"cover","type":"boolean | undefined","required":false,"description":"Fit: fill the frame, cropping the overflow (pick one).","default":"false","group":0},{"name":"stretch","type":"boolean | undefined","required":false,"description":"Fit: fill the frame by distorting the aspect ratio (pick one).","default":"false","group":0},{"name":"autoplay","type":"boolean | undefined","required":false,"description":"Start playing as soon as the clip is ready, unless the system asks to reduce motion. Browsers autoplay only muted clips, so pair it with `muted` on the web.","default":"false","group":0},{"name":"loop","type":"boolean | undefined","required":false,"description":"Play again from the start at the end.","default":"false","group":0},{"name":"muted","type":"boolean | undefined","required":false,"description":"Play without sound.","default":"false","group":0},{"name":"controls","type":"boolean | undefined","required":false,"description":"Transport controls: the platform's own player controls on iOS and Android, the kit's control bar on the web.","default":"false","group":0},{"name":"aspectRatio","type":"number | undefined","required":false,"description":"Width over height of the clip; the frame fills its parent's width at this ratio (default 16 / 9).","group":0},{"name":"radius","type":"ImageRadius | undefined","required":false,"description":"Corner radius from the kit's radius scale (pick one): none, sm, md, lg, xl, 2xl, 3xl, full.","group":0},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"The clip's accessible name, used in the names of its controls (default \"video\").","group":0},{"name":"onPlayingChange","type":"((playing: boolean) => void) | undefined","required":false,"description":"Called when playback starts or stops.","group":0},{"name":"onEnd","type":"(() => void) | undefined","required":false,"description":"Called when the clip plays to its end (each time round, when looping).","group":0},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the frame.","group":0},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":0}],"groups":[{"title":"Fit","pickOne":true,"note":"Fit (pick one; default `contain`). How the picture fills the frame; first match wins."}],"inherits":[]}],"platformNotes":{"web":"Plays a clip with an optional poster: tap to play inline, or full transport controls\n(the platform's own on iOS and Android, the kit's bar on the web),\nwith boolean fit, `autoplay`, `loop` and `muted` props.\n\nGive it a `source` (a `{ uri }`, or a bundled asset from `require`), an optional `poster` shown until the clip's first frame is on screen, and the clip's `aspectRatio` (width over height, 16 / 9 by default): the frame fills its parent's width at that ratio and letterboxes the picture on black, inside the v4 hand-off's frame: a 14 px corner on a hairline (`radius` picks a step of the kit's scale instead). Without `controls` it is an inline player: the whole picture is one play and pause control, a play emblem sits over the paused picture, and a spinner shows while the clip loads. With `controls` each platform shows transport its own way:\niOS and Android hand the frame to their own player controls, and the web draws\nthe kit's control bar under the picture, with play and pause, the elapsed time, a seek slider, the length, mute, and full screen.\n\n`autoplay` starts a clip once it is ready unless the system asks to reduce motion; browsers autoplay only `muted` clips, and this site's own policy blocks autoplay, so the examples here play on tap. Name every clip with `accessibilityLabel`: its controls are announced as \"Play\", \"Pause\", \"Seek\" and \"Mute\" followed by that name. Playback runs through the optional `expo-video` peer; without it the frame keeps its size and poster in a labeled frame.","ios":"Plays a clip with an optional poster: tap to play inline, or full transport controls\n(the platform's own in a native app, the kit's bar on the web),\nwith boolean fit, `autoplay`, `loop` and `muted` props.\n\nGive it a `source` (a `{ uri }`, or a bundled asset from `require`), an optional `poster` shown until the clip's first frame is on screen, and the clip's `aspectRatio` (width over height, 16 / 9 by default): the frame fills its parent's width at that ratio and letterboxes the picture on black, inside the v4 hand-off's frame: a 14 px corner on a hairline (`radius` picks a step of the kit's scale instead). Without `controls` it is an inline player: the whole picture is one play and pause control, a play emblem sits over the paused picture, and a spinner shows while the clip loads. With `controls` each platform shows transport its own way:\na native app hands the frame to the platform's own player controls, and the web draws\nthe kit's control bar under the picture, with play and pause, the elapsed time, a seek slider, the length, mute, and full screen.\n\n`autoplay` starts a clip once it is ready unless the system asks to reduce motion; browsers autoplay only `muted` clips, and this site's own policy blocks autoplay, so the examples here play on tap. Name every clip with `accessibilityLabel`: its controls are announced as \"Play\", \"Pause\", \"Seek\" and \"Mute\" followed by that name. Playback runs through the optional `expo-video` peer; without it the frame keeps its size and poster in a labeled frame.","android":"Plays a clip with an optional poster: tap to play inline, or full transport controls\n(the platform's own in a native app, the kit's bar on the web),\nwith boolean fit, `autoplay`, `loop` and `muted` props.\n\nGive it a `source` (a `{ uri }`, or a bundled asset from `require`), an optional `poster` shown until the clip's first frame is on screen, and the clip's `aspectRatio` (width over height, 16 / 9 by default): the frame fills its parent's width at that ratio and letterboxes the picture on black, inside the v4 hand-off's frame: a 14 px corner on a hairline (`radius` picks a step of the kit's scale instead). Without `controls` it is an inline player: the whole picture is one play and pause control, a play emblem sits over the paused picture, and a spinner shows while the clip loads. With `controls` each platform shows transport its own way:\na native app hands the frame to the platform's own player controls, and the web draws\nthe kit's control bar under the picture, with play and pause, the elapsed time, a seek slider, the length, mute, and full screen.\n\n`autoplay` starts a clip once it is ready unless the system asks to reduce motion; browsers autoplay only `muted` clips, and this site's own policy blocks autoplay, so the examples here play on tap. Name every clip with `accessibilityLabel`: its controls are announced as \"Play\", \"Pause\", \"Seek\" and \"Mute\" followed by that name. Playback runs through the optional `expo-video` peer; without it the frame keeps its size and poster in a labeled frame."}},{"slug":"view","name":"View","category":"atoms","description":"The layout primitive: a flex container that runs identically on iOS, Android, and the web. A View is a column by default.","source":"src/atoms/view/view.md","url":"https://canvas.nannier.com/ai/4.2.0/components/view.md","humanUrl":"https://canvas.nannier.com/components/view","exports":["View"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"View host props","groups":[],"inherits":[],"props":[{"name":"children","type":"React.ReactNode","required":false,"description":""},{"name":"hitSlop","type":"number | Insets | null | undefined","required":false,"description":"This defines how far a touch event can start away from the view. Typical interface guidelines recommend touch targets that are at least 30 - 40 points/density-independent pixels. If a Touchable view has a height of 20 the touchable height can be extended to 40 with hitSlop={{top: 10, bottom: 10, left: 0, right: 0}} NOTE The touch area never extends past the parent view bounds and the Z-index of sibling views always takes precedence if a touch hits two overlapping views."},{"name":"id","type":"string | undefined","required":false,"description":"Used to reference react managed views from native code."},{"name":"needsOffscreenAlphaCompositing","type":"boolean | undefined","required":false,"description":"Whether this view needs to rendered offscreen and composited with an alpha in order to preserve 100% correct colors and blending behavior. The default (false) falls back to drawing the component and its children with an alpha applied to the paint used to draw each element instead of rendering the full component offscreen and compositing it back with an alpha value. This default may be noticeable and undesired in the case where the View you are setting an opacity on has multiple overlapping elements (e.g. multiple overlapping Views, or text and a background). Rendering offscreen to preserve correct alpha behavior is extremely expensive and hard to debug for non-native developers, which is why it is not turned on by default. If you do need to enable this property for an animation, consider combining it with renderToHardwareTextureAndroid if the view contents are static (i.e. it doesn't need to be redrawn each frame). If that property is enabled, this View will be rendered off-screen once, saved in a hardware texture, and then composited onto the screen with an alpha each frame without having to switch rendering targets on the GPU."},{"name":"onLayout","type":"((event: LayoutChangeEvent) => void) | undefined","required":false,"description":"Invoked on mount and layout changes with {nativeEvent: { layout: {x, y, width, height}}}."},{"name":"pointerEvents","type":"\"box-none\" | \"none\" | \"box-only\" | \"auto\" | undefined","required":false,"description":" In the absence of auto property, none is much like CSS's none value. box-none is as if you had applied the CSS class: .box-none { pointer-events: none; } .box-none * { pointer-events: all; } box-only is the equivalent of .box-only { pointer-events: all; } .box-only * { pointer-events: none; } But since pointerEvents does not affect layout/appearance, and we are already deviating from the spec by adding additional modes, we opt to not include pointerEvents on style. On some platforms, we would need to implement it as a className anyways. Using style or not is an implementation detail of the platform."},{"name":"removeClippedSubviews","type":"boolean | undefined","required":false,"description":" This is a special performance property exposed by RCTView and is useful for scrolling content when there are many subviews, most of which are offscreen. For this property to be effective, it must be applied to a view that contains many subviews that extend outside its bound. The subviews must also have overflow: hidden, as should the containing view (or one of its superviews)."},{"name":"style","type":"StyleProp<ViewStyle>","required":false,"description":""},{"name":"testID","type":"string | undefined","required":false,"description":"Used to locate this view in end-to-end tests."},{"name":"nativeID","type":"string | undefined","required":false,"description":"Used to reference react managed views from native code."},{"name":"collapsable","type":"boolean | undefined","required":false,"description":"Views that are only used to layout their children or otherwise don't draw anything may be automatically removed from the native hierarchy as an optimization. Set this property to false to disable this optimization and ensure that this View exists in the native view hierarchy."},{"name":"collapsableChildren","type":"boolean | undefined","required":false,"description":"Setting to false prevents direct children of the view from being removed from the native view hierarchy, similar to the effect of setting `collapsable={false}` on each child."},{"name":"onBlur","type":"((e: BlurEvent) => void) | null | undefined","required":false,"description":"Callback that is called when the view is blurred. Note: This will only be called if the view is focusable."},{"name":"onFocus","type":"((e: FocusEvent) => void) | null | undefined","required":false,"description":"Callback that is called when the view is focused. Note: This will only be called if the view is focusable."},{"name":"renderToHardwareTextureAndroid","type":"boolean | undefined","required":false,"description":"Whether this view should render itself (and all of its children) into a single hardware texture on the GPU. On Android, this is useful for animations and interactions that only modify opacity, rotation, translation, and/or scale: in those cases, the view doesn't have to be redrawn and display lists don't need to be re-executed. The texture can just be re-used and re-composited with different parameters. The downside is that this can use up limited video memory, so this prop should be set back to false at the end of the interaction/animation."},{"name":"focusable","type":"boolean | undefined","required":false,"description":"Whether this `View` should be focusable with a non-touch input device, eg. receive focus with a hardware keyboard."},{"name":"tabIndex","type":"0 | -1 | undefined","required":false,"description":"Indicates whether this `View` should be focusable with a non-touch input device, eg. receive focus with a hardware keyboard. See https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex for more details. Supports the following values: - 0 (View is focusable) - -1 (View is not focusable)"},{"name":"shouldRasterizeIOS","type":"boolean | undefined","required":false,"description":"Whether this view should be rendered as a bitmap before compositing. On iOS, this is useful for animations and interactions that do not modify this component's dimensions nor its children; for example, when translating the position of a static view, rasterization allows the renderer to reuse a cached bitmap of a static view and quickly composite it during each frame. Rasterization incurs an off-screen drawing pass and the bitmap consumes memory. Test and measure when using this property."},{"name":"isTVSelectable","type":"boolean | undefined","required":false,"description":"*(Apple TV only)* When set to true, this view will be focusable and navigable using the Apple TV remote."},{"name":"hasTVPreferredFocus","type":"boolean | undefined","required":false,"description":"*(Apple TV only)* May be set to true to force the Apple TV focus engine to move focus to this view."},{"name":"tvParallaxShiftDistanceX","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0."},{"name":"tvParallaxShiftDistanceY","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0."},{"name":"tvParallaxTiltAngle","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 0.05."},{"name":"tvParallaxMagnification","type":"number | undefined","required":false,"description":"*(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 1.0."},{"name":"onStartShouldSetResponder","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"Does this view want to become responder on the start of a touch?"},{"name":"onMoveShouldSetResponder","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"Called for every touch move on the View when it is not the responder: does this view want to \"claim\" touch responsiveness?"},{"name":"onResponderEnd","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"If the View returns true and attempts to become the responder, one of the following will happen:"},{"name":"onResponderGrant","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"The View is now responding for touch events. This is the time to highlight and show the user what is happening"},{"name":"onResponderReject","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Something else is the responder right now and will not release it"},{"name":"onResponderMove","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"The user is moving their finger"},{"name":"onResponderRelease","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"Fired at the end of the touch, ie \"touchUp\""},{"name":"onResponderStart","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onResponderTerminationRequest","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"Something else wants to become responder. Should this view release the responder? Returning true allows release"},{"name":"onResponderTerminate","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":"The responder has been taken from the View. Might be taken by other views after a call to onResponderTerminationRequest, or might be taken by the OS without asking (happens with control center/ notification center on iOS)"},{"name":"onStartShouldSetResponderCapture","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern, where the deepest node is called first. That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers. This is desirable in most cases, because it makes sure all controls and buttons are usable. However, sometimes a parent will want to make sure that it becomes responder. This can be handled by using the capture phase. Before the responder system bubbles up from the deepest component, it will do a capture phase, firing on*ShouldSetResponderCapture. So if a parent View wants to prevent the child from becoming responder on a touch start, it should have a onStartShouldSetResponderCapture handler which returns true."},{"name":"onMoveShouldSetResponderCapture","type":"((event: GestureResponderEvent) => boolean) | undefined","required":false,"description":"onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern, where the deepest node is called first. That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers. This is desirable in most cases, because it makes sure all controls and buttons are usable. However, sometimes a parent will want to make sure that it becomes responder. This can be handled by using the capture phase. Before the responder system bubbles up from the deepest component, it will do a capture phase, firing on*ShouldSetResponderCapture. So if a parent View wants to prevent the child from becoming responder on a touch start, it should have a onStartShouldSetResponderCapture handler which returns true."},{"name":"onTouchStart","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchMove","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchEnd","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchCancel","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onTouchEndCapture","type":"((event: GestureResponderEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerEnter","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerEnterCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerLeave","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerLeaveCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerMove","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerMoveCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerCancel","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerCancelCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerDown","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerDownCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerUp","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"onPointerUpCapture","type":"((event: PointerEvent) => void) | undefined","required":false,"description":""},{"name":"accessible","type":"boolean | undefined","required":false,"description":"When true, indicates that the view is an accessibility element. By default, all the touchable elements are accessible."},{"name":"accessibilityActions","type":"readonly Readonly<{ name: AccessibilityActionName | string; label?: string | undefined; }>[] | undefined","required":false,"description":"Provides an array of custom actions available for accessibility."},{"name":"accessibilityLabel","type":"string | undefined","required":false,"description":"Overrides the text that's read by the screen reader when the user interacts with the element. By default, the label is constructed by traversing all the children and accumulating all the Text nodes separated by space."},{"name":"aria-label","type":"string | undefined","required":false,"description":"Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel https://github.com/facebook/react-native/issues/34424"},{"name":"accessibilityRole","type":"AccessibilityRole | undefined","required":false,"description":"Accessibility Role tells a person using either VoiceOver on iOS or TalkBack on Android the type of element that is focused on."},{"name":"accessibilityState","type":"AccessibilityState | undefined","required":false,"description":"Accessibility State tells a person using either VoiceOver on iOS or TalkBack on Android the state of the element currently focused on."},{"name":"aria-busy","type":"boolean | undefined","required":false,"description":"alias for accessibilityState see https://reactnative.dev/docs/accessibility#accessibilitystate"},{"name":"aria-checked","type":"boolean | \"mixed\" | undefined","required":false,"description":""},{"name":"aria-disabled","type":"boolean | undefined","required":false,"description":""},{"name":"aria-expanded","type":"boolean | undefined","required":false,"description":""},{"name":"aria-selected","type":"boolean | undefined","required":false,"description":""},{"name":"accessibilityHint","type":"string | undefined","required":false,"description":"An accessibility hint helps users understand what will happen when they perform an action on the accessibility element when that result is not obvious from the accessibility label."},{"name":"accessibilityValue","type":"AccessibilityValue | undefined","required":false,"description":"Represents the current value of a component. It can be a textual description of a component's value, or for range-based components, such as sliders and progress bars, it contains range information (minimum, current, and maximum)."},{"name":"aria-valuemax","type":"number | undefined","required":false,"description":""},{"name":"aria-valuemin","type":"number | undefined","required":false,"description":""},{"name":"aria-valuenow","type":"number | undefined","required":false,"description":""},{"name":"aria-valuetext","type":"string | undefined","required":false,"description":""},{"name":"onAccessibilityAction","type":"((event: AccessibilityActionEvent) => void) | undefined","required":false,"description":"When `accessible` is true, the system will try to invoke this function when the user performs an accessibility custom action."},{"name":"importantForAccessibility","type":"\"auto\" | \"yes\" | \"no\" | \"no-hide-descendants\" | undefined","required":false,"description":"[Android] Controlling if a view fires accessibility events and if it is reported to accessibility services."},{"name":"aria-hidden","type":"boolean | undefined","required":false,"description":"A value indicating whether the accessibility elements contained within this accessibility element are hidden."},{"name":"aria-modal","type":"boolean | undefined","required":false,"description":""},{"name":"role","type":"Role | undefined","required":false,"description":"Indicates to accessibility services to treat UI component like a specific role."},{"name":"accessibilityLabelledBy","type":"string | string[] | undefined","required":false,"description":"Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props, the text is read aloud. The value should should match the nativeID of the related element."},{"name":"aria-labelledby","type":"string | undefined","required":false,"description":"Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props, the text is read aloud. The value should should match the nativeID of the related element."},{"name":"accessibilityLiveRegion","type":"\"none\" | \"polite\" | \"assertive\" | undefined","required":false,"description":"Indicates to accessibility services whether the user should be notified when this view changes. Works for Android API >= 19 only."},{"name":"aria-live","type":"\"polite\" | \"assertive\" | \"off\" | undefined","required":false,"description":"Indicates to accessibility services whether the user should be notified when this view changes. Works for Android API >= 19 only."},{"name":"screenReaderFocusable","type":"boolean | undefined","required":false,"description":"Enables the view to be screen reader focusable, not keyboard focusable."},{"name":"accessibilityElementsHidden","type":"boolean | undefined","required":false,"description":"A Boolean value indicating whether the accessibility elements contained within this accessibility element are hidden to the screen reader."},{"name":"accessibilityViewIsModal","type":"boolean | undefined","required":false,"description":"A Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver."},{"name":"onAccessibilityEscape","type":"(() => void) | undefined","required":false,"description":"When accessible is true, the system will invoke this function when the user performs the escape gesture (scrub with two fingers)."},{"name":"onAccessibilityTap","type":"(() => void) | undefined","required":false,"description":"When `accessible` is true, the system will try to invoke this function when the user performs accessibility tap gesture."},{"name":"onMagicTap","type":"(() => void) | undefined","required":false,"description":"When accessible is true, the system will invoke this function when the user performs the magic tap gesture."},{"name":"accessibilityIgnoresInvertColors","type":"boolean | undefined","required":false,"description":"https://reactnative.dev/docs/accessibility#accessibilityignoresinvertcolorsios"},{"name":"accessibilityLanguage","type":"string | undefined","required":false,"description":"By using the accessibilityLanguage property, the screen reader will understand which language to use while reading the element's label, value and hint. The provided string value must follow the BCP 47 specification (https://www.rfc-editor.org/info/bcp47). https://reactnative.dev/docs/accessibility#accessibilitylanguage-ios"},{"name":"accessibilityShowsLargeContentViewer","type":"boolean | undefined","required":false,"description":"A Boolean value that indicates whether or not to show the item in the large content viewer. Available on iOS 13.0+ https://reactnative.dev/docs/accessibility#accessibilityshowslargecontentviewer"},{"name":"accessibilityLargeContentTitle","type":"string | undefined","required":false,"description":"When `accessibilityShowsLargeContentViewer` is set, this string will be used as title for the large content viewer. https://reactnative.dev/docs/accessibility#accessibilitylargecontenttitle"},{"name":"accessibilityRespondsToUserInteraction","type":"boolean | undefined","required":false,"description":"Blocks the user from interacting with the component through keyboard while still allowing screen reader to interact with it if this View is still accessible."}]}],"platformNotes":{"web":"The layout primitive: a flex container that\nruns identically on iOS, Android, and the web.\nA View is a column by default.\n\nReach for it directly only when no semantic primitive covers what you need: arrangement (direction, gap, alignment, padding) belongs to `Row` and `Column`, which are Views with that axis exposed as boolean props, and a bordered filled surface belongs to `Card`. Numbers are density-independent pixels.","ios":"The layout primitive: a flex container that\nruns identically on every platform Canvas supports.\nA View is a column by default.\n\nReach for it directly only when no semantic primitive covers what you need: arrangement (direction, gap, alignment, padding) belongs to `Row` and `Column`, which are Views with that axis exposed as boolean props, and a bordered filled surface belongs to `Card`. Numbers are density-independent pixels.","android":"The layout primitive: a flex container that\nruns identically on every platform Canvas supports.\nA View is a column by default.\n\nReach for it directly only when no semantic primitive covers what you need: arrangement (direction, gap, alignment, padding) belongs to `Row` and `Column`, which are Views with that axis exposed as boolean props, and a bordered filled surface belongs to `Card`. Numbers are density-independent pixels."}},{"slug":"waterfall-chart","name":"WaterfallChart","category":"charts","description":"The running-total bridge: each step floats from the running total by its signed `value`, and a `total` step snapshots the running total as an absolute bar from zero.","source":"src/charts/waterfall-chart/waterfall-chart.md","url":"https://canvas.nannier.com/ai/4.2.0/components/waterfall-chart.md","humanUrl":"https://canvas.nannier.com/components/waterfall-chart","exports":["WaterfallChart","WaterfallChartProps","WaterfallStep"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"WaterfallChartProps","props":[{"name":"steps","type":"WaterfallStep[]","required":true,"description":"The bridge's steps, in order."},{"name":"title","type":"string | undefined","required":false,"description":"Optional heading shown above the plot."},{"name":"compact","type":"boolean | undefined","required":false,"description":"Density (omit for the default plot size).","default":"false","group":0},{"name":"plain","type":"boolean | undefined","required":false,"description":"Strip the card surface for nesting inside an existing card (mirrors Stats).","default":"false","group":0},{"name":"hideGrid","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":1},{"name":"hideAxes","type":"boolean | undefined","required":false,"description":"Furniture visibility.","default":"false","group":1},{"name":"formatValue","type":"((v: number) => string) | undefined","required":false,"description":"Formats tick labels, the flag, and the accessible name.","group":1},{"name":"selected","type":"number | null | undefined","required":false,"description":"Scrub-to-inspect: the selected step index (controlled). Pass null for none.","group":1},{"name":"defaultSelected","type":"number | undefined","required":false,"description":"Scrub-to-inspect: the initially selected step (uncontrolled).","group":1},{"name":"onSelect","type":"((index: number | null) => void) | undefined","required":false,"description":"Fired when a press/scrub selects a step (or clears it with null).","group":1},{"name":"testID","type":"string | undefined","required":false,"description":"E2E hook forwarded to the root element.","group":1},{"name":"style","type":"LayoutStyle","required":false,"description":"Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.","group":1}],"groups":[{"title":"Density","pickOne":false,"note":"Density (omit for the default plot size)."},{"title":"Furniture visibility","pickOne":false}],"inherits":[]}],"platformNotes":{"web":"The running-total bridge: each step floats from the running total by its signed `value`, and a `total` step snapshots the running total as an absolute bar from zero.\n\nThe coloring is fixed semantics rather than a prop: rises green, falls red, totals the brand primary, so every bridge reads the same way. Scrubbing a step flags its change and running total.","ios":"The running-total bridge: each step floats from the running total by its signed `value`, and a `total` step snapshots the running total as an absolute bar from zero.\n\nThe coloring is fixed semantics rather than a prop: rises green, falls red, totals the brand primary, so every bridge reads the same way. Scrubbing a step flags its change and running total.","android":"The running-total bridge: each step floats from the running total by its signed `value`, and a `total` step snapshots the running total as an absolute bar from zero.\n\nThe coloring is fixed semantics rather than a prop: rises green, falls red, totals the brand primary, so every bridge reads the same way. Scrubbing a step flags its change and running total."}},{"slug":"wizard","name":"Wizard","category":"organisms","description":"A modal workflow with a fixed step sidebar, a title and status header, and footer actions around a bounded, scrolling body. The application owns stage content, validation, saving and transitions; Wizard composes the existing Dialog, Steps and Button controls.","source":"src/organisms/wizard/wizard.md","url":"https://canvas.nannier.com/ai/4.2.0/components/wizard.md","humanUrl":"https://canvas.nannier.com/components/wizard","exports":["Wizard","WizardProps"],"dependencies":[{"name":"react","range":">=18","optional":false},{"name":"react-native","range":">=0.74","optional":false},{"name":"react-native-svg","range":">=15.8.0","optional":false}],"propGroups":[{"name":"WizardProps","props":[{"name":"open","type":"boolean","required":true,"description":"Controlled modal visibility."},{"name":"title","type":"string","required":true,"description":"Names the modal and its fixed header."},{"name":"description","type":"string | undefined","required":false,"description":"Supporting text below the title."},{"name":"steps","type":"Step[]","required":true,"description":"Ordered stages; the application owns their content and transitions."},{"name":"current","type":"number","required":true,"description":"Zero-based active stage; earlier stages read as complete."},{"name":"onOpenChange","type":"(open: boolean) => void","required":true,"description":"Called when the close action, Escape or native back requests dismissal."},{"name":"panelWidth","type":"number | undefined","required":false,"description":"Maximum panel width; defaults to the hand-off's 620px and shrinks to its parent.","default":"620"},{"name":"previous","type":"{ label: string; onPress: () => void; disabled?: boolean; } | undefined","required":false,"description":"Named previous stage action at the footer's start."},{"name":"actions","type":"ReactNode","required":false,"description":"Application actions at the footer's end."},{"name":"status","type":"string | undefined","required":false,"description":"Save/progress status beside the title in the fixed header."},{"name":"children","type":"ReactNode","required":false,"description":""},{"name":"scrollBody","type":"boolean | undefined","required":false,"description":"Scroll the body (default true). Set false when a child, such as Chat, owns its scroll.","default":"true"},{"name":"embedded","type":"boolean | undefined","required":false,"description":"Show the open wizard as a non-modal specimen, for a catalogue or a showcase: it keeps its look, its dialog role and its labelling, but does not take focus, trap Tab, claim `aria-modal`, or close on Escape or native back. It renders in place, in the flow of the page, as Dialog's contained form does, rather than presenting into an OverlayProvider.","default":"false"},{"name":"testID","type":"string | undefined","required":false,"description":"Prefix for modal, steps, body-scroll and footer test hooks."}],"groups":[],"inherits":[]}],"platformNotes":{"web":"A modal workflow with a fixed step sidebar, a title and status header, and footer actions around a bounded, scrolling body. The application owns stage content, validation, saving and transitions; Wizard composes the existing Dialog, Steps and Button controls.\n\nAdd `embedded` to show an open wizard in a page as a specimen, the way a catalogue\nor a showcase does: it keeps its look, its dialog role and its labelling, but it is\nnot modal. It does not take focus, trap Tab, set `aria-modal`, or close on Escape or\nnative back, and it renders in place in the page's flow instead of presenting into an\n`OverlayProvider`.","ios":"A modal workflow with a fixed step sidebar, a title and status header, and footer actions around a bounded, scrolling body. The application owns stage content, validation, saving and transitions; Wizard composes the existing Dialog, Steps and Button controls.\n\nAdd `embedded` to show an open wizard in a page as a specimen, the way a catalogue\nor a showcase does: it keeps its look, its dialog role and its labelling, but it is\nnot modal. It does not take focus, trap Tab, set `aria-modal`, or close on Escape or\nnative back, and it renders in place in the page's flow instead of presenting into an\n`OverlayProvider`.","android":"A modal workflow with a fixed step sidebar, a title and status header, and footer actions around a bounded, scrolling body. The application owns stage content, validation, saving and transitions; Wizard composes the existing Dialog, Steps and Button controls.\n\nAdd `embedded` to show an open wizard in a page as a specimen, the way a catalogue\nor a showcase does: it keeps its look, its dialog role and its labelling, but it is\nnot modal. It does not take focus, trap Tab, set `aria-modal`, or close on Escape or\nnative back, and it renders in place in the page's flow instead of presenting into an\n`OverlayProvider`."}}]}
