@misoto22/folio 0.0.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +88 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +21 -0
- package/README.md +208 -2
- package/bin/folio-design.mjs +277 -0
- package/bin/migrate-legacy.mjs +81 -0
- package/dist/agent/Accordion.md +65 -0
- package/dist/agent/Actions.md +49 -0
- package/dist/agent/Alert.md +65 -0
- package/dist/agent/AppShell.md +69 -0
- package/dist/agent/ArchitectureFigure.md +72 -0
- package/dist/agent/AreaChart.md +94 -0
- package/dist/agent/Article.md +65 -0
- package/dist/agent/AspectRatio.md +58 -0
- package/dist/agent/Avatar.md +53 -0
- package/dist/agent/Badge.md +62 -0
- package/dist/agent/BarChart.md +93 -0
- package/dist/agent/BarList.md +67 -0
- package/dist/agent/BigNumber.md +70 -0
- package/dist/agent/BoxPlot.md +82 -0
- package/dist/agent/Breadcrumb.md +55 -0
- package/dist/agent/BulletChart.md +71 -0
- package/dist/agent/Button.md +81 -0
- package/dist/agent/Calendar.md +77 -0
- package/dist/agent/CalendarHeatmap.md +75 -0
- package/dist/agent/Card.md +72 -0
- package/dist/agent/Checkbox.md +57 -0
- package/dist/agent/Code.md +51 -0
- package/dist/agent/CodeBlock.md +77 -0
- package/dist/agent/Collapsible.md +68 -0
- package/dist/agent/Collection.md +169 -0
- package/dist/agent/ColorPicker.md +76 -0
- package/dist/agent/Combobox.md +77 -0
- package/dist/agent/Command.md +122 -0
- package/dist/agent/ComposedChart.md +82 -0
- package/dist/agent/Contact.md +90 -0
- package/dist/agent/Content.md +70 -0
- package/dist/agent/ContextMenu.md +93 -0
- package/dist/agent/Conversation.md +247 -0
- package/dist/agent/DataflowFigure.md +49 -0
- package/dist/agent/DatePicker.md +104 -0
- package/dist/agent/DescriptionList.md +69 -0
- package/dist/agent/Diagram.md +71 -0
- package/dist/agent/DiagramCanvas.md +71 -0
- package/dist/agent/DiagramExportMenu.md +65 -0
- package/dist/agent/DiagramInspector.md +73 -0
- package/dist/agent/DiagramLegend.md +56 -0
- package/dist/agent/DiagramMinimap.md +69 -0
- package/dist/agent/DiagramToolbar.md +70 -0
- package/dist/agent/Dialog.md +76 -0
- package/dist/agent/DropdownMenu.md +110 -0
- package/dist/agent/EmptyState.md +63 -0
- package/dist/agent/ErrorState.md +67 -0
- package/dist/agent/Evidence.md +165 -0
- package/dist/agent/Facet.md +107 -0
- package/dist/agent/Field.md +79 -0
- package/dist/agent/FigureBand.md +49 -0
- package/dist/agent/FloatingIconButton.md +61 -0
- package/dist/agent/FunnelChart.md +75 -0
- package/dist/agent/Heading.md +65 -0
- package/dist/agent/Heatmap.md +78 -0
- package/dist/agent/Histogram.md +88 -0
- package/dist/agent/Input.md +52 -0
- package/dist/agent/Kbd.md +48 -0
- package/dist/agent/LifecycleFigure.md +50 -0
- package/dist/agent/LineChart.md +85 -0
- package/dist/agent/LinkArrow.md +49 -0
- package/dist/agent/Markdown.md +69 -0
- package/dist/agent/Media.md +261 -0
- package/dist/agent/Metric.md +70 -0
- package/dist/agent/Metrics.md +114 -0
- package/dist/agent/Music.md +86 -0
- package/dist/agent/NativeSelect.md +62 -0
- package/dist/agent/NavItem.md +56 -0
- package/dist/agent/NumberField.md +73 -0
- package/dist/agent/PageHeader.md +69 -0
- package/dist/agent/Pagination.md +70 -0
- package/dist/agent/PieChart.md +80 -0
- package/dist/agent/Popover.md +80 -0
- package/dist/agent/Portfolio.md +93 -0
- package/dist/agent/PortfolioIndex.md +34 -0
- package/dist/agent/Progress.md +58 -0
- package/dist/agent/RadarChart.md +79 -0
- package/dist/agent/RadialChart.md +81 -0
- package/dist/agent/RadioGroup.md +66 -0
- package/dist/agent/Reading.md +233 -0
- package/dist/agent/Recovery.md +72 -0
- package/dist/agent/SankeyChart.md +85 -0
- package/dist/agent/ScatterChart.md +80 -0
- package/dist/agent/ScrollArea.md +62 -0
- package/dist/agent/SearchPalette.md +51 -0
- package/dist/agent/SearchableMenu.md +69 -0
- package/dist/agent/Select.md +102 -0
- package/dist/agent/Separator.md +60 -0
- package/dist/agent/SequenceFigure.md +51 -0
- package/dist/agent/Sheet.md +82 -0
- package/dist/agent/Sidebar.md +194 -0
- package/dist/agent/SiteNavigation.md +62 -0
- package/dist/agent/SiteShell.md +67 -0
- package/dist/agent/Skeleton.md +96 -0
- package/dist/agent/Slider.md +67 -0
- package/dist/agent/Sparkline.md +68 -0
- package/dist/agent/Spinner.md +62 -0
- package/dist/agent/StatusDot.md +56 -0
- package/dist/agent/StatusPill.md +55 -0
- package/dist/agent/Steps.md +68 -0
- package/dist/agent/Switch.md +50 -0
- package/dist/agent/Table.md +111 -0
- package/dist/agent/Tabs.md +71 -0
- package/dist/agent/Tag.md +67 -0
- package/dist/agent/Text.md +66 -0
- package/dist/agent/Textarea.md +46 -0
- package/dist/agent/Timeline.md +114 -0
- package/dist/agent/Timestamp.md +65 -0
- package/dist/agent/Toast.md +51 -0
- package/dist/agent/ToggleGroup.md +67 -0
- package/dist/agent/Toolbar.md +72 -0
- package/dist/agent/Tooltip.md +74 -0
- package/dist/agent/TreemapChart.md +76 -0
- package/dist/agent/WaterfallChart.md +86 -0
- package/dist/agent/Workbench.md +142 -0
- package/dist/agent/WorkflowFigure.md +51 -0
- package/dist/agent/catalog.json +8055 -0
- package/dist/agent/index.md +185 -0
- package/dist/article.css +407 -0
- package/dist/charts/AreaChart/AreaChart.d.ts +198 -0
- package/dist/charts/AreaChart/AreaChart.js +479 -0
- package/dist/charts/AreaChart/AreaChart.js.map +1 -0
- package/dist/charts/BarChart/BarChart.d.ts +190 -0
- package/dist/charts/BarChart/BarChart.js +599 -0
- package/dist/charts/BarChart/BarChart.js.map +1 -0
- package/dist/charts/BarList/BarList.d.ts +65 -0
- package/dist/charts/BarList/BarList.js +79 -0
- package/dist/charts/BarList/BarList.js.map +1 -0
- package/dist/charts/BigNumber/BigNumber.d.ts +72 -0
- package/dist/charts/BigNumber/BigNumber.js +51 -0
- package/dist/charts/BigNumber/BigNumber.js.map +1 -0
- package/dist/charts/BoxPlot/BoxPlot.d.ts +177 -0
- package/dist/charts/BoxPlot/BoxPlot.js +497 -0
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -0
- package/dist/charts/BulletChart/BulletChart.d.ts +100 -0
- package/dist/charts/BulletChart/BulletChart.js +197 -0
- package/dist/charts/BulletChart/BulletChart.js.map +1 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.d.ts +106 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.js +103 -0
- package/dist/charts/CalendarHeatmap/CalendarHeatmap.js.map +1 -0
- package/dist/charts/ComposedChart/ComposedChart.d.ts +178 -0
- package/dist/charts/ComposedChart/ComposedChart.js +667 -0
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -0
- package/dist/charts/Facet/Facet.d.ts +240 -0
- package/dist/charts/Facet/Facet.js +133 -0
- package/dist/charts/Facet/Facet.js.map +1 -0
- package/dist/charts/Facet/panels.d.ts +187 -0
- package/dist/charts/Facet/panels.js +203 -0
- package/dist/charts/Facet/panels.js.map +1 -0
- package/dist/charts/FunnelChart/FunnelChart.d.ts +106 -0
- package/dist/charts/FunnelChart/FunnelChart.js +137 -0
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -0
- package/dist/charts/Heatmap/Heatmap.d.ts +101 -0
- package/dist/charts/Heatmap/Heatmap.js +125 -0
- package/dist/charts/Heatmap/Heatmap.js.map +1 -0
- package/dist/charts/Histogram/Histogram.d.ts +188 -0
- package/dist/charts/Histogram/Histogram.js +382 -0
- package/dist/charts/Histogram/Histogram.js.map +1 -0
- package/dist/charts/LineChart/LineChart.d.ts +174 -0
- package/dist/charts/LineChart/LineChart.js +485 -0
- package/dist/charts/LineChart/LineChart.js.map +1 -0
- package/dist/charts/PieChart/PieChart.d.ts +140 -0
- package/dist/charts/PieChart/PieChart.js +317 -0
- package/dist/charts/PieChart/PieChart.js.map +1 -0
- package/dist/charts/RadarChart/RadarChart.d.ts +135 -0
- package/dist/charts/RadarChart/RadarChart.js +303 -0
- package/dist/charts/RadarChart/RadarChart.js.map +1 -0
- package/dist/charts/RadialChart/RadialChart.d.ts +142 -0
- package/dist/charts/RadialChart/RadialChart.js +279 -0
- package/dist/charts/RadialChart/RadialChart.js.map +1 -0
- package/dist/charts/SankeyChart/SankeyChart.d.ts +149 -0
- package/dist/charts/SankeyChart/SankeyChart.js +509 -0
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -0
- package/dist/charts/ScatterChart/ScatterChart.d.ts +149 -0
- package/dist/charts/ScatterChart/ScatterChart.js +275 -0
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -0
- package/dist/charts/Sparkline/Sparkline.d.ts +53 -0
- package/dist/charts/Sparkline/Sparkline.js +95 -0
- package/dist/charts/Sparkline/Sparkline.js.map +1 -0
- package/dist/charts/TreemapChart/TreemapChart.d.ts +98 -0
- package/dist/charts/TreemapChart/TreemapChart.js +127 -0
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -0
- package/dist/charts/WaterfallChart/WaterfallChart.d.ts +164 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js +321 -0
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -0
- package/dist/charts/index.d.ts +43 -0
- package/dist/charts/index.js +130 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/charts/lib/annotations.d.ts +103 -0
- package/dist/charts/lib/annotations.js +99 -0
- package/dist/charts/lib/annotations.js.map +1 -0
- package/dist/charts/lib/axis.d.ts +18 -0
- package/dist/charts/lib/axis.js +21 -0
- package/dist/charts/lib/axis.js.map +1 -0
- package/dist/charts/lib/background.d.ts +33 -0
- package/dist/charts/lib/background.js +173 -0
- package/dist/charts/lib/background.js.map +1 -0
- package/dist/charts/lib/brush.d.ts +94 -0
- package/dist/charts/lib/brush.js +535 -0
- package/dist/charts/lib/brush.js.map +1 -0
- package/dist/charts/lib/chart.d.ts +94 -0
- package/dist/charts/lib/chart.js +149 -0
- package/dist/charts/lib/chart.js.map +1 -0
- package/dist/charts/lib/dot.d.ts +29 -0
- package/dist/charts/lib/dot.js +78 -0
- package/dist/charts/lib/dot.js.map +1 -0
- package/dist/charts/lib/empty.d.ts +31 -0
- package/dist/charts/lib/empty.js +24 -0
- package/dist/charts/lib/empty.js.map +1 -0
- package/dist/charts/lib/export.d.ts +94 -0
- package/dist/charts/lib/export.js +62 -0
- package/dist/charts/lib/export.js.map +1 -0
- package/dist/charts/lib/figure.d.ts +81 -0
- package/dist/charts/lib/figure.js +62 -0
- package/dist/charts/lib/figure.js.map +1 -0
- package/dist/charts/lib/format.d.ts +46 -0
- package/dist/charts/lib/format.js +56 -0
- package/dist/charts/lib/format.js.map +1 -0
- package/dist/charts/lib/legend.d.ts +45 -0
- package/dist/charts/lib/legend.js +117 -0
- package/dist/charts/lib/legend.js.map +1 -0
- package/dist/charts/lib/loading.d.ts +48 -0
- package/dist/charts/lib/loading.js +105 -0
- package/dist/charts/lib/loading.js.map +1 -0
- package/dist/charts/lib/paint.d.ts +154 -0
- package/dist/charts/lib/paint.js +551 -0
- package/dist/charts/lib/paint.js.map +1 -0
- package/dist/charts/lib/scale.d.ts +23 -0
- package/dist/charts/lib/scale.js +13 -0
- package/dist/charts/lib/scale.js.map +1 -0
- package/dist/charts/lib/selection.d.ts +20 -0
- package/dist/charts/lib/selection.js +18 -0
- package/dist/charts/lib/selection.js.map +1 -0
- package/dist/charts/lib/sonify-control.d.ts +163 -0
- package/dist/charts/lib/sonify-control.js +172 -0
- package/dist/charts/lib/sonify-control.js.map +1 -0
- package/dist/charts/lib/sonify.d.ts +248 -0
- package/dist/charts/lib/sonify.js +262 -0
- package/dist/charts/lib/sonify.js.map +1 -0
- package/dist/charts/lib/toolbar.d.ts +144 -0
- package/dist/charts/lib/toolbar.js +156 -0
- package/dist/charts/lib/toolbar.js.map +1 -0
- package/dist/charts/lib/tooltip.d.ts +59 -0
- package/dist/charts/lib/tooltip.js +135 -0
- package/dist/charts/lib/tooltip.js.map +1 -0
- package/dist/charts/lib/values.d.ts +56 -0
- package/dist/charts/lib/values.js +71 -0
- package/dist/charts/lib/values.js.map +1 -0
- package/dist/charts/lib/zoom.d.ts +139 -0
- package/dist/charts/lib/zoom.js +314 -0
- package/dist/charts/lib/zoom.js.map +1 -0
- package/dist/components/Accordion/Accordion.d.ts +34 -0
- package/dist/components/Accordion/Accordion.js +43 -0
- package/dist/components/Accordion/Accordion.js.map +1 -0
- package/dist/components/Alert/Alert.d.ts +32 -0
- package/dist/components/Alert/Alert.js +49 -0
- package/dist/components/Alert/Alert.js.map +1 -0
- package/dist/components/AppShell/AppShell.d.ts +58 -0
- package/dist/components/AppShell/AppShell.js +126 -0
- package/dist/components/AppShell/AppShell.js.map +1 -0
- package/dist/components/Article/Article.d.ts +58 -0
- package/dist/components/Article/Article.js +34 -0
- package/dist/components/Article/Article.js.map +1 -0
- package/dist/components/AspectRatio/AspectRatio.d.ts +46 -0
- package/dist/components/AspectRatio/AspectRatio.js +33 -0
- package/dist/components/AspectRatio/AspectRatio.js.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +38 -0
- package/dist/components/Avatar/Avatar.js +44 -0
- package/dist/components/Avatar/Avatar.js.map +1 -0
- package/dist/components/Badge/Badge.d.ts +30 -0
- package/dist/components/Badge/Badge.js +29 -0
- package/dist/components/Badge/Badge.js.map +1 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +37 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +46 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/components/Button/Button.d.ts +70 -0
- package/dist/components/Button/Button.js +95 -0
- package/dist/components/Button/Button.js.map +1 -0
- package/dist/components/Calendar/Calendar.d.ts +54 -0
- package/dist/components/Calendar/Calendar.js +369 -0
- package/dist/components/Calendar/Calendar.js.map +1 -0
- package/dist/components/Card/Card.d.ts +55 -0
- package/dist/components/Card/Card.js +64 -0
- package/dist/components/Card/Card.js.map +1 -0
- package/dist/components/Checkbox/Checkbox.d.ts +26 -0
- package/dist/components/Checkbox/Checkbox.js +34 -0
- package/dist/components/Checkbox/Checkbox.js.map +1 -0
- package/dist/components/Code/Code.d.ts +30 -0
- package/dist/components/Code/Code.js +21 -0
- package/dist/components/Code/Code.js.map +1 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +145 -0
- package/dist/components/CodeBlock/CodeBlock.js +114 -0
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.d.ts +45 -0
- package/dist/components/Collapsible/Collapsible.js +60 -0
- package/dist/components/Collapsible/Collapsible.js.map +1 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +67 -0
- package/dist/components/ColorPicker/ColorPicker.js +334 -0
- package/dist/components/ColorPicker/ColorPicker.js.map +1 -0
- package/dist/components/Combobox/Combobox.d.ts +77 -0
- package/dist/components/Combobox/Combobox.js +170 -0
- package/dist/components/Combobox/Combobox.js.map +1 -0
- package/dist/components/Command/Command.d.ts +125 -0
- package/dist/components/Command/Command.js +204 -0
- package/dist/components/Command/Command.js.map +1 -0
- package/dist/components/ContextMenu/ContextMenu.d.ts +63 -0
- package/dist/components/ContextMenu/ContextMenu.js +109 -0
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -0
- package/dist/components/DatePicker/DatePicker.d.ts +130 -0
- package/dist/components/DatePicker/DatePicker.js +257 -0
- package/dist/components/DatePicker/DatePicker.js.map +1 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +73 -0
- package/dist/components/DescriptionList/DescriptionList.js +35 -0
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -0
- package/dist/components/Diagram/Diagram.d.ts +86 -0
- package/dist/components/Diagram/Diagram.js +211 -0
- package/dist/components/Diagram/Diagram.js.map +1 -0
- package/dist/components/Dialog/Dialog.d.ts +63 -0
- package/dist/components/Dialog/Dialog.js +90 -0
- package/dist/components/Dialog/Dialog.js.map +1 -0
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +87 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +120 -0
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -0
- package/dist/components/EmptyState/EmptyState.d.ts +55 -0
- package/dist/components/EmptyState/EmptyState.js +32 -0
- package/dist/components/EmptyState/EmptyState.js.map +1 -0
- package/dist/components/ErrorState/ErrorState.d.ts +55 -0
- package/dist/components/ErrorState/ErrorState.js +41 -0
- package/dist/components/ErrorState/ErrorState.js.map +1 -0
- package/dist/components/Field/Field.d.ts +111 -0
- package/dist/components/Field/Field.js +95 -0
- package/dist/components/Field/Field.js.map +1 -0
- package/dist/components/Field/field-control.d.ts +31 -0
- package/dist/components/Field/field-control.js +12 -0
- package/dist/components/Field/field-control.js.map +1 -0
- package/dist/components/FigureBand/FigureBand.d.ts +31 -0
- package/dist/components/FigureBand/FigureBand.js +51 -0
- package/dist/components/FigureBand/FigureBand.js.map +1 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.d.ts +29 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js +34 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -0
- package/dist/components/Heading/Heading.d.ts +62 -0
- package/dist/components/Heading/Heading.js +44 -0
- package/dist/components/Heading/Heading.js.map +1 -0
- package/dist/components/Input/Input.d.ts +22 -0
- package/dist/components/Input/Input.js +21 -0
- package/dist/components/Input/Input.js.map +1 -0
- package/dist/components/Kbd/Kbd.d.ts +27 -0
- package/dist/components/Kbd/Kbd.js +21 -0
- package/dist/components/Kbd/Kbd.js.map +1 -0
- package/dist/components/LinkArrow/LinkArrow.d.ts +24 -0
- package/dist/components/LinkArrow/LinkArrow.js +24 -0
- package/dist/components/LinkArrow/LinkArrow.js.map +1 -0
- package/dist/components/Markdown/Markdown.d.ts +139 -0
- package/dist/components/Markdown/Markdown.js +135 -0
- package/dist/components/Markdown/Markdown.js.map +1 -0
- package/dist/components/Markdown/inline.d.ts +29 -0
- package/dist/components/Markdown/inline.js +74 -0
- package/dist/components/Markdown/inline.js.map +1 -0
- package/dist/components/Markdown/nodes.d.ts +65 -0
- package/dist/components/Markdown/nodes.js +1 -0
- package/dist/components/Markdown/nodes.js.map +1 -0
- package/dist/components/Markdown/parse.d.ts +24 -0
- package/dist/components/Markdown/parse.js +110 -0
- package/dist/components/Markdown/parse.js.map +1 -0
- package/dist/components/Markdown/slug.d.ts +15 -0
- package/dist/components/Markdown/slug.js +7 -0
- package/dist/components/Markdown/slug.js.map +1 -0
- package/dist/components/Metric/Metric.d.ts +61 -0
- package/dist/components/Metric/Metric.js +51 -0
- package/dist/components/Metric/Metric.js.map +1 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +33 -0
- package/dist/components/NativeSelect/NativeSelect.js +44 -0
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -0
- package/dist/components/NavItem/NavItem.d.ts +39 -0
- package/dist/components/NavItem/NavItem.js +31 -0
- package/dist/components/NavItem/NavItem.js.map +1 -0
- package/dist/components/NumberField/NumberField.d.ts +69 -0
- package/dist/components/NumberField/NumberField.js +162 -0
- package/dist/components/NumberField/NumberField.js.map +1 -0
- package/dist/components/PageHeader/PageHeader.d.ts +92 -0
- package/dist/components/PageHeader/PageHeader.js +37 -0
- package/dist/components/PageHeader/PageHeader.js.map +1 -0
- package/dist/components/Pagination/Pagination.d.ts +67 -0
- package/dist/components/Pagination/Pagination.js +112 -0
- package/dist/components/Pagination/Pagination.js.map +1 -0
- package/dist/components/Popover/Popover.d.ts +39 -0
- package/dist/components/Popover/Popover.js +57 -0
- package/dist/components/Popover/Popover.js.map +1 -0
- package/dist/components/Progress/Progress.d.ts +43 -0
- package/dist/components/Progress/Progress.js +57 -0
- package/dist/components/Progress/Progress.js.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +49 -0
- package/dist/components/RadioGroup/RadioGroup.js +53 -0
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/components/ScrollArea/ScrollArea.d.ts +46 -0
- package/dist/components/ScrollArea/ScrollArea.js +54 -0
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -0
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +68 -0
- package/dist/components/SearchableMenu/SearchableMenu.js +101 -0
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -0
- package/dist/components/Select/Select.d.ts +87 -0
- package/dist/components/Select/Select.js +130 -0
- package/dist/components/Select/Select.js.map +1 -0
- package/dist/components/Separator/Separator.d.ts +48 -0
- package/dist/components/Separator/Separator.js +43 -0
- package/dist/components/Separator/Separator.js.map +1 -0
- package/dist/components/Sheet/Sheet.d.ts +43 -0
- package/dist/components/Sheet/Sheet.js +79 -0
- package/dist/components/Sheet/Sheet.js.map +1 -0
- package/dist/components/Sidebar/Sidebar.d.ts +357 -0
- package/dist/components/Sidebar/Sidebar.js +447 -0
- package/dist/components/Sidebar/Sidebar.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.d.ts +70 -0
- package/dist/components/Skeleton/Skeleton.js +44 -0
- package/dist/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/components/Slider/Slider.d.ts +74 -0
- package/dist/components/Slider/Slider.js +143 -0
- package/dist/components/Slider/Slider.js.map +1 -0
- package/dist/components/Spinner/Spinner.d.ts +58 -0
- package/dist/components/Spinner/Spinner.js +49 -0
- package/dist/components/Spinner/Spinner.js.map +1 -0
- package/dist/components/StatusDot/StatusDot.d.ts +29 -0
- package/dist/components/StatusDot/StatusDot.js +44 -0
- package/dist/components/StatusDot/StatusDot.js.map +1 -0
- package/dist/components/StatusPill/StatusPill.d.ts +30 -0
- package/dist/components/StatusPill/StatusPill.js +37 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -0
- package/dist/components/Steps/Steps.d.ts +65 -0
- package/dist/components/Steps/Steps.js +25 -0
- package/dist/components/Steps/Steps.js.map +1 -0
- package/dist/components/Switch/Switch.d.ts +23 -0
- package/dist/components/Switch/Switch.js +23 -0
- package/dist/components/Switch/Switch.js.map +1 -0
- package/dist/components/Table/Table.d.ts +116 -0
- package/dist/components/Table/Table.js +137 -0
- package/dist/components/Table/Table.js.map +1 -0
- package/dist/components/Tabs/Tabs.d.ts +37 -0
- package/dist/components/Tabs/Tabs.js +205 -0
- package/dist/components/Tabs/Tabs.js.map +1 -0
- package/dist/components/Tag/Tag.d.ts +87 -0
- package/dist/components/Tag/Tag.js +62 -0
- package/dist/components/Tag/Tag.js.map +1 -0
- package/dist/components/Text/Text.d.ts +62 -0
- package/dist/components/Text/Text.js +30 -0
- package/dist/components/Text/Text.js.map +1 -0
- package/dist/components/Textarea/Textarea.d.ts +20 -0
- package/dist/components/Textarea/Textarea.js +32 -0
- package/dist/components/Textarea/Textarea.js.map +1 -0
- package/dist/components/Timestamp/Timestamp.d.ts +59 -0
- package/dist/components/Timestamp/Timestamp.js +56 -0
- package/dist/components/Timestamp/Timestamp.js.map +1 -0
- package/dist/components/Toast/Toast.d.ts +32 -0
- package/dist/components/Toast/Toast.js +64 -0
- package/dist/components/Toast/Toast.js.map +1 -0
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +46 -0
- package/dist/components/ToggleGroup/ToggleGroup.js +88 -0
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -0
- package/dist/components/Toolbar/Toolbar.d.ts +55 -0
- package/dist/components/Toolbar/Toolbar.js +43 -0
- package/dist/components/Toolbar/Toolbar.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.d.ts +43 -0
- package/dist/components/Tooltip/Tooltip.js +40 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +55 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +175 -0
- package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.d.ts +28 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.js +148 -0
- package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +78 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +229 -0
- package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +106 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +123 -0
- package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.d.ts +70 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.js +94 -0
- package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.d.ts +42 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.js +35 -0
- package/dist/diagrams/DiagramLegend/DiagramLegend.js.map +1 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +77 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +106 -0
- package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.d.ts +48 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.js +53 -0
- package/dist/diagrams/DiagramToolbar/DiagramToolbar.js.map +1 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.d.ts +31 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +234 -0
- package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.d.ts +38 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.js +261 -0
- package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +36 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +259 -0
- package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -0
- package/dist/diagrams/index.d.ts +17 -0
- package/dist/diagrams/index.js +29 -0
- package/dist/diagrams/index.js.map +1 -0
- package/dist/diagrams/lib/dev.d.ts +61 -0
- package/dist/diagrams/lib/dev.js +96 -0
- package/dist/diagrams/lib/dev.js.map +1 -0
- package/dist/diagrams/lib/frame.d.ts +138 -0
- package/dist/diagrams/lib/frame.js +131 -0
- package/dist/diagrams/lib/frame.js.map +1 -0
- package/dist/diagrams/lib/geometry.d.ts +114 -0
- package/dist/diagrams/lib/geometry.js +113 -0
- package/dist/diagrams/lib/geometry.js.map +1 -0
- package/dist/diagrams/lib/legend.d.ts +32 -0
- package/dist/diagrams/lib/legend.js +84 -0
- package/dist/diagrams/lib/legend.js.map +1 -0
- package/dist/diagrams/lib/marks.d.ts +207 -0
- package/dist/diagrams/lib/marks.js +480 -0
- package/dist/diagrams/lib/marks.js.map +1 -0
- package/dist/diagrams/lib/route.d.ts +106 -0
- package/dist/diagrams/lib/route.js +201 -0
- package/dist/diagrams/lib/route.js.map +1 -0
- package/dist/diagrams/lib/wires.d.ts +59 -0
- package/dist/diagrams/lib/wires.js +94 -0
- package/dist/diagrams/lib/wires.js.map +1 -0
- package/dist/diagrams/spec.d.ts +405 -0
- package/dist/diagrams/spec.js +1 -0
- package/dist/diagrams/spec.js.map +1 -0
- package/dist/fonts/hanken-grotesk-300.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-400.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-500.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-600.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-700.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-400.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-500.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-600.woff2 +0 -0
- package/dist/fonts/newsreader-300.woff2 +0 -0
- package/dist/fonts/newsreader-400.woff2 +0 -0
- package/dist/fonts/newsreader-500.woff2 +0 -0
- package/dist/fonts/newsreader-600.woff2 +0 -0
- package/dist/fonts.css +96 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/keyframes.css +300 -0
- package/dist/lib/cn.d.ts +21 -0
- package/dist/lib/cn.js +9 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/lib/color.d.ts +80 -0
- package/dist/lib/color.js +189 -0
- package/dist/lib/color.js.map +1 -0
- package/dist/lib/control.d.ts +32 -0
- package/dist/lib/control.js +14 -0
- package/dist/lib/control.js.map +1 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/numeric.d.ts +35 -0
- package/dist/lib/numeric.js +29 -0
- package/dist/lib/numeric.js.map +1 -0
- package/dist/lib/overlay-container.d.ts +48 -0
- package/dist/lib/overlay-container.js +15 -0
- package/dist/lib/overlay-container.js.map +1 -0
- package/dist/lib/slot-content.d.ts +8 -0
- package/dist/lib/slot-content.js +17 -0
- package/dist/lib/slot-content.js.map +1 -0
- package/dist/lib/step-rail.d.ts +45 -0
- package/dist/lib/step-rail.js +47 -0
- package/dist/lib/step-rail.js.map +1 -0
- package/dist/lib/svg-export.d.ts +138 -0
- package/dist/lib/svg-export.js +198 -0
- package/dist/lib/svg-export.js.map +1 -0
- package/dist/lib/useClipboardCopy.d.ts +30 -0
- package/dist/lib/useClipboardCopy.js +37 -0
- package/dist/lib/useClipboardCopy.js.map +1 -0
- package/dist/lib/useSelectionIndicator.d.ts +29 -0
- package/dist/lib/useSelectionIndicator.js +49 -0
- package/dist/lib/useSelectionIndicator.js.map +1 -0
- package/dist/lib/warn.d.ts +73 -0
- package/dist/lib/warn.js +38 -0
- package/dist/lib/warn.js.map +1 -0
- package/dist/semantic.css +200 -0
- package/dist/styles.css +98 -0
- package/dist/themes.css +607 -0
- package/dist/tokens/brand.d.ts +47 -0
- package/dist/tokens/brand.js +38 -0
- package/dist/tokens/brand.js.map +1 -0
- package/dist/tokens.css +666 -0
- package/dist/tokens.d.ts +205 -0
- package/dist/tokens.js +1056 -0
- package/dist/tokens.json +1055 -0
- package/dist/website/Actions/Actions.d.ts +34 -0
- package/dist/website/Actions/Actions.js +29 -0
- package/dist/website/Actions/Actions.js.map +1 -0
- package/dist/website/Collection/Collection.d.ts +128 -0
- package/dist/website/Collection/Collection.js +162 -0
- package/dist/website/Collection/Collection.js.map +1 -0
- package/dist/website/Contact/Contact.d.ts +87 -0
- package/dist/website/Contact/Contact.js +94 -0
- package/dist/website/Contact/Contact.js.map +1 -0
- package/dist/website/Content/CodePanel.d.ts +27 -0
- package/dist/website/Content/CodePanel.js +30 -0
- package/dist/website/Content/CodePanel.js.map +1 -0
- package/dist/website/Content/Content.d.ts +29 -0
- package/dist/website/Content/Content.js +38 -0
- package/dist/website/Content/Content.js.map +1 -0
- package/dist/website/Conversation/Conversation.d.ts +193 -0
- package/dist/website/Conversation/Conversation.js +252 -0
- package/dist/website/Conversation/Conversation.js.map +1 -0
- package/dist/website/Evidence/Evidence.d.ts +116 -0
- package/dist/website/Evidence/Evidence.js +142 -0
- package/dist/website/Evidence/Evidence.js.map +1 -0
- package/dist/website/Media/Media.d.ts +173 -0
- package/dist/website/Media/Media.js +225 -0
- package/dist/website/Media/Media.js.map +1 -0
- package/dist/website/Media/MediaLightbox.d.ts +18 -0
- package/dist/website/Media/MediaLightbox.js +38 -0
- package/dist/website/Media/MediaLightbox.js.map +1 -0
- package/dist/website/Metrics/Metrics.d.ts +74 -0
- package/dist/website/Metrics/Metrics.js +96 -0
- package/dist/website/Metrics/Metrics.js.map +1 -0
- package/dist/website/Music/Music.d.ts +60 -0
- package/dist/website/Music/Music.js +80 -0
- package/dist/website/Music/Music.js.map +1 -0
- package/dist/website/Portfolio/FrameLayout.d.ts +9 -0
- package/dist/website/Portfolio/FrameLayout.js +42 -0
- package/dist/website/Portfolio/FrameLayout.js.map +1 -0
- package/dist/website/Portfolio/Portfolio.d.ts +49 -0
- package/dist/website/Portfolio/Portfolio.js +66 -0
- package/dist/website/Portfolio/Portfolio.js.map +1 -0
- package/dist/website/Portfolio/QuestionCard.d.ts +22 -0
- package/dist/website/Portfolio/QuestionCard.js +33 -0
- package/dist/website/Portfolio/QuestionCard.js.map +1 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.d.ts +21 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.js +31 -0
- package/dist/website/PortfolioIndex/PortfolioIndex.js.map +1 -0
- package/dist/website/Reading/Reading.d.ts +203 -0
- package/dist/website/Reading/Reading.js +357 -0
- package/dist/website/Reading/Reading.js.map +1 -0
- package/dist/website/Recovery/Recovery.d.ts +39 -0
- package/dist/website/Recovery/Recovery.js +96 -0
- package/dist/website/Recovery/Recovery.js.map +1 -0
- package/dist/website/SearchPalette/SearchPalette.d.ts +59 -0
- package/dist/website/SearchPalette/SearchPalette.js +120 -0
- package/dist/website/SearchPalette/SearchPalette.js.map +1 -0
- package/dist/website/SiteNavigation/SiteNavigation.d.ts +46 -0
- package/dist/website/SiteNavigation/SiteNavigation.js +101 -0
- package/dist/website/SiteNavigation/SiteNavigation.js.map +1 -0
- package/dist/website/SiteShell/SiteShell.d.ts +45 -0
- package/dist/website/SiteShell/SiteShell.js +46 -0
- package/dist/website/SiteShell/SiteShell.js.map +1 -0
- package/dist/website/Timeline/Timeline.d.ts +80 -0
- package/dist/website/Timeline/Timeline.js +99 -0
- package/dist/website/Timeline/Timeline.js.map +1 -0
- package/dist/website/Workbench/Chronology.d.ts +32 -0
- package/dist/website/Workbench/Chronology.js +32 -0
- package/dist/website/Workbench/Chronology.js.map +1 -0
- package/dist/website/Workbench/ContactRow.d.ts +13 -0
- package/dist/website/Workbench/ContactRow.js +11 -0
- package/dist/website/Workbench/ContactRow.js.map +1 -0
- package/dist/website/Workbench/PhotoMosaic.d.ts +13 -0
- package/dist/website/Workbench/PhotoMosaic.js +15 -0
- package/dist/website/Workbench/PhotoMosaic.js.map +1 -0
- package/dist/website/Workbench/Reveal.d.ts +19 -0
- package/dist/website/Workbench/Reveal.js +29 -0
- package/dist/website/Workbench/Reveal.js.map +1 -0
- package/dist/website/Workbench/ToolStrip.d.ts +18 -0
- package/dist/website/Workbench/ToolStrip.js +15 -0
- package/dist/website/Workbench/ToolStrip.js.map +1 -0
- package/dist/website/Workbench/Workbench.d.ts +23 -0
- package/dist/website/Workbench/Workbench.js +22 -0
- package/dist/website/Workbench/Workbench.js.map +1 -0
- package/dist/website/Workbench/WorkbenchCard.d.ts +29 -0
- package/dist/website/Workbench/WorkbenchCard.js +21 -0
- package/dist/website/Workbench/WorkbenchCard.js.map +1 -0
- package/dist/website/Workbench/WorkbenchEntries.d.ts +22 -0
- package/dist/website/Workbench/WorkbenchEntries.js +24 -0
- package/dist/website/Workbench/WorkbenchEntries.js.map +1 -0
- package/dist/website/Workbench/WorkbenchFigure.d.ts +20 -0
- package/dist/website/Workbench/WorkbenchFigure.js +15 -0
- package/dist/website/Workbench/WorkbenchFigure.js.map +1 -0
- package/dist/website/Workbench/WorkbenchHero.d.ts +24 -0
- package/dist/website/Workbench/WorkbenchHero.js +24 -0
- package/dist/website/Workbench/WorkbenchHero.js.map +1 -0
- package/dist/website/Workbench/theme.d.ts +22 -0
- package/dist/website/Workbench/theme.js +12 -0
- package/dist/website/Workbench/theme.js.map +1 -0
- package/dist/website/index.d.ts +38 -0
- package/dist/website/index.js +32 -0
- package/dist/website/index.js.map +1 -0
- package/dist/website-actions.css +6 -0
- package/dist/website-base.css +46 -0
- package/dist/website-collection.css +89 -0
- package/dist/website-contact.css +29 -0
- package/dist/website-content.css +20 -0
- package/dist/website-controls.css +91 -0
- package/dist/website-conversation.css +115 -0
- package/dist/website-evidence.css +56 -0
- package/dist/website-media.css +227 -0
- package/dist/website-metrics.css +15 -0
- package/dist/website-music.css +27 -0
- package/dist/website-portfolio.css +94 -0
- package/dist/website-reading.css +159 -0
- package/dist/website-recovery.css +28 -0
- package/dist/website-search.css +26 -0
- package/dist/website-shell.css +89 -0
- package/dist/website-timeline.css +43 -0
- package/dist/website-workbench.css +162 -0
- package/dist/website.css +26 -0
- package/llms.txt +35 -0
- package/package.json +163 -5
- package/skills/folio-design/SKILL.md +228 -0
- package/skills/folio-design/evals/claims.json +95 -0
- package/skills/folio-design/evals/evals.json +84 -0
- package/skills/folio-design/rules/a11y.md +167 -0
- package/skills/folio-design/rules/composition.md +108 -0
- package/skills/folio-design/rules/forms.md +135 -0
- package/skills/folio-design/rules/naming.md +155 -0
- package/skills/folio-design/rules/tokens.md +135 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# DiagramExportMenu
|
|
2
|
+
|
|
3
|
+
Taking the figure off the page: PNG, JPEG, WebP, SVG and a 1200×630 share card.
|
|
4
|
+
|
|
5
|
+
- Kind: component
|
|
6
|
+
- Group: Diagrams
|
|
7
|
+
- Import: `import { DiagramExportMenu } from '@misoto22/folio/diagrams'`
|
|
8
|
+
- Version: 0.17.0
|
|
9
|
+
- Docs: https://ui.misoto22.com/components/diagram-export-menu/
|
|
10
|
+
- Related: dropdown-menu, diagram-toolbar
|
|
11
|
+
|
|
12
|
+
## When to reach for it
|
|
13
|
+
|
|
14
|
+
It does the export rather than emitting a format name, because the interesting half — baking custom properties into real colours before serialising — is the half a caller would not know to write.
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
- **Trigger** (required) — A small secondary button reading Export, or whatever trigger replaces it — the replacement is slotted, so it becomes the menu’s own control rather than sitting next to one.
|
|
19
|
+
- **Menu** (required) — A dropdown aligned to the trigger’s end, in three labelled groups separated by rules: Image, Vector, Share. The grouping is the answer to "which of these five do I want".
|
|
20
|
+
- **Format row** (required) — One menu row per format, with its name and a mono hint under it — "Lossless, 2× for retina", "Compact, flattened onto paper". Real menu rows, so the arrow keys walk them, typing jumps to one, and picking one closes the menu over the file it just wrote. The running one gains an ellipsis and every row is disabled until it finishes, so a second click cannot start a second export.
|
|
21
|
+
- **Serialiser** (required) — The part with nothing to point at: the artwork is cloned, every node’s computed paint is written inline, and the clone is placed on a plate the size of the picture plus its padding. It is what stops var(--ink) arriving in a document with no stylesheet and painting nothing.
|
|
22
|
+
- **Share card** — A fixed 1200 × 630 frame with the title printed on it and the whole diagram letterboxed inside — never cropped to fill, because a card cropped to fill is a picture of a different diagram.
|
|
23
|
+
- **Result** — onResult, called with the format, an ok or the Error, and the source that produced it. It is the only place a failed export is reported.
|
|
24
|
+
|
|
25
|
+
## Best practices
|
|
26
|
+
|
|
27
|
+
### Do
|
|
28
|
+
|
|
29
|
+
- Point targetRef at the wrapper rather than at an svg you found yourself. The export looks for the artwork marker first, which is what stops a page whose toolbar sits inside the same wrapper from exporting a picture of a chevron.
|
|
30
|
+
- Export after the artwork has been measured. The serialiser reads the element’s box and throws when it is still zero, so a call made in the same tick as the mount fails loudly instead of writing an empty file.
|
|
31
|
+
- Take onResult and put a failure in front of the reader. An unmeasured figure, a canvas tainted by a cross-origin image, a browser that returned no 2D context — each is reported there rather than thrown at the click, and the alternative is a menu item that quietly does nothing.
|
|
32
|
+
- Read source alongside ok. built-in says a file reached the browser; caller says your own onExport resolved, which is exactly what a handler that did nothing also does — the menu cannot see inside your pipeline and no longer reports as though it can.
|
|
33
|
+
- Pass background={null} for a figure going onto a coloured page. Every other export paints the reader’s own surface behind the artwork, and JPEG is flattened onto that surface whatever this says, because a transparent JPEG is a black one.
|
|
34
|
+
|
|
35
|
+
### Don’t
|
|
36
|
+
|
|
37
|
+
- The file is the artwork and the theme the reader was in. Paint is read off the live element, so a figure exported from a dark page is a dark image in a light document; and the toolbar, the inspector and the figure’s own hidden summary list are HTML, so none of them travels with it.
|
|
38
|
+
- Do not treat the SVG as a pixel-exact record. The isolated document cannot fetch the page’s web fonts, so the type falls back to what the machine has — the words and the line breaks are already fixed, but a name that just fitted its plate on screen can overrun its own rule in the file.
|
|
39
|
+
- The output is sized from the artwork’s box ON SCREEN rather than from its viewBox, so a figure sitting at 4× inside a DiagramCanvas serialises four times larger and then rasterises at 2× on top of that. Reset the view before exporting, or a reader gets a file whose dimensions record where the zoom happened to be.
|
|
40
|
+
|
|
41
|
+
## Accessibility
|
|
42
|
+
|
|
43
|
+
- A failed export is reported through onResult rather than swallowed: a click that quietly does nothing is indistinguishable from a broken button.
|
|
44
|
+
|
|
45
|
+
## DiagramExportMenu
|
|
46
|
+
|
|
47
|
+
Taking the figure off the page: five files, one menu. WHY THE MENU DOES THE WORK rather than handing back a format: every one of these exports is the same six steps — find the `<svg>`, walk it with `getComputedStyle` to bake the custom properties into real colours, serialise, rasterise, name the file, hand it to the browser — and only the last two differ between them. A menu that emitted `'png'` and left the caller to do the rest would be a menu that every consumer reimplements, badly, and the interesting half (a serialised SVG resolves `var(--ink)` to nothing and comes out invisible) is exactly the half a caller would not know to write. `onExport` is still there for a page with its own pipeline — a server-side renderer, a different frame size — and taking it turns everything below into a no-op, which is why a result from that path says `source: 'caller'`: this component cannot see whether the handler produced a file, so it does not report that it did. What each format actually is, stated rather than implied. **SVG** is the artwork with resolved colours. It is editable and it is the only lossless one, but it carries no web fonts: a machine without the family renders it in a fallback, so type metrics will differ. **The ground** is the reader's own surface unless `background` says otherwise. `background={null}` exports on transparency — for a figure being dropped onto a coloured page — except in JPEG, which has no alpha and is flattened onto paper whatever is asked for. **PNG, JPEG and WebP** are the browser's own rasteriser re-drawing that SVG at 2×. Not a screenshot — antialiasing and any effect a page stylesheet applied from OUTSIDE the `<svg>` are not in it. **JPEG has no alpha**, so it is flattened onto the resolved paper colour rather than onto black, which is what a transparent PNG becomes when a format with no transparency is asked to hold it. **The share card** is a 1200 × 630 frame with the title on it and the whole diagram letterboxed inside — never cropped. A card that cropped to fill the frame would be a picture of a different diagram.
|
|
48
|
+
|
|
49
|
+
### Props
|
|
50
|
+
|
|
51
|
+
- `targetRef` (required) — `RefObject<HTMLElement | SVGSVGElement | null>`. The `<svg>` to export, or an element containing exactly one. A ref rather than a selector, because a page can hold several figures and a selector would export whichever the document happened to reach first.
|
|
52
|
+
- `title` (required) — `string`. Names the file, and is printed on the share card.
|
|
53
|
+
- `trigger` — `ReactNode`. Replaces the trigger.
|
|
54
|
+
- `className` — `string`.
|
|
55
|
+
- `onExport` — `(format: ExportFormat) => void | Promise<void>`. Runs instead of the built-in export — for a caller with its own pipeline. Taking it turns everything below into a no-op, INCLUDING the part that knows whether a file was produced: a result from this path reports `source: 'caller'` and an `ok` that means only "your handler resolved".
|
|
56
|
+
- `onResult` — `(result: ExportResult) => void`. Told what happened, so a page can raise a toast.
|
|
57
|
+
- `background` — `string | null`. Painted behind the artwork. Defaults to the surface the reader is looking at; `null` exports on a transparent ground. JPEG has no alpha channel, so it is flattened onto the reader's own paper whatever this says — a transparent JPEG is a black one.
|
|
58
|
+
|
|
59
|
+
## exportFigure
|
|
60
|
+
|
|
61
|
+
One figure, one format, one file. Exported so a page can wire a keyboard shortcut or its own button to exactly what the menu does, without reimplementing the six steps.
|
|
62
|
+
|
|
63
|
+
## Types
|
|
64
|
+
|
|
65
|
+
- `ExportFormat` = `'png' | 'jpeg' | 'webp' | 'svg' | 'share-card'`
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# DiagramInspector
|
|
2
|
+
|
|
3
|
+
What the reader just picked, written out beside the picture.
|
|
4
|
+
|
|
5
|
+
- Kind: component
|
|
6
|
+
- Group: Diagrams
|
|
7
|
+
- Import: `import { DiagramInspector } from '@misoto22/folio/diagrams'`
|
|
8
|
+
- Version: 0.17.0
|
|
9
|
+
- Docs: https://ui.misoto22.com/components/diagram-inspector/
|
|
10
|
+
- Related: card, diagram-canvas
|
|
11
|
+
|
|
12
|
+
## When to reach for it
|
|
13
|
+
|
|
14
|
+
A node holds about eight words before it stops being a node. Everything past those — the port, the owner, the six relationships — belongs here.
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
- **Region** (required) — A <section> named "<title> details" with aria-live="polite", on a panel plate. A region and not a dialog: nothing traps focus and nothing demands dismissal, because the reader clicked a node rather than opening a window.
|
|
19
|
+
- **Heading** (required) — The eyebrow over the title — what KIND of thing this is, then what it is called. The eyebrow is where the plate’s own kicker word belongs, so the panel and the picture say the same thing about the same node.
|
|
20
|
+
- **Facts** — A definition list, one term and value per row, the value settable in mono for an id, a path, a port. A list rather than a grid of divs, because a grid tells a screen reader nothing about which value belongs to which label.
|
|
21
|
+
- **Relationships** — One row per edge the node takes part in, each becoming a real button when it carries onSelect. The arrow glyph is hidden and the direction spelled out beside it, so "to" and "from" are heard rather than guessed.
|
|
22
|
+
- **Close** — A small control named for what it does — clearing the selection, not closing a window. It is the only thing that can empty the panel.
|
|
23
|
+
- **Actions** — A wrap of caller-supplied buttons under the facts: copy the id, open the source the node was read out of.
|
|
24
|
+
|
|
25
|
+
## Best practices
|
|
26
|
+
|
|
27
|
+
### Do
|
|
28
|
+
|
|
29
|
+
- Pair it with the figure’s onSelectNode. That is what turns the hidden summary list into real buttons, and without it the panel can only ever be filled by a pointer — the plates in the picture are presentational by construction.
|
|
30
|
+
- Give every relationship an onSelect. The rows become buttons and the graph becomes walkable peer by peer, which is how a keyboard reader gets from a node to the node it is connected to without going back through the list.
|
|
31
|
+
- Move the long facts here and leave about eight words on the plate. A box holding a port, an owning team and a file path grows to fit all three rather than clipping them, and a figure of boxes that size is a document with lines drawn on it.
|
|
32
|
+
|
|
33
|
+
### Don’t
|
|
34
|
+
|
|
35
|
+
- Two facts sharing a label are two rows, and neither says which is which. They are keyed by position, so both render — and a panel with "Source" twice leaves the reader deducing from the values what the labels should have said. Name them apart when they mean different things.
|
|
36
|
+
- floating pins the panel over the surface, so it covers that corner of the diagram for as long as it is mounted. It has no dismissal contract of its own — passing no onClose leaves the reader nothing to press and the corner hidden until the selection changes.
|
|
37
|
+
|
|
38
|
+
## Accessibility
|
|
39
|
+
|
|
40
|
+
- A labelled region with aria-live="polite", not a dialog: the reader clicked a node, they did not open anything, so focus is never trapped or demanded.
|
|
41
|
+
- Relationships are real buttons when they carry onSelect, which is how the graph becomes walkable peer by peer from the keyboard.
|
|
42
|
+
|
|
43
|
+
## DiagramInspector
|
|
44
|
+
|
|
45
|
+
What the reader just picked, written out. A diagram can hold about eight words per node before it stops being a diagram and starts being a document with lines drawn on it. Everything past those eight — the port, the owning team, the file it was read out of, the six relationships it takes part in — belongs beside the picture rather than inside it, and this is that place. NOT A DIALOG, and that is deliberate. An inspector is a REGION that changes with the selection, not a modal. Giving it `role="dialog"` would trap focus and demand dismissal for something the reader never opened — they clicked a node, and the panel followed. So it is a labelled region with `aria-live="polite"`, which is what makes a screen reader announce the new selection without stealing the cursor from whatever the reader was doing. The relationships are real buttons when they carry `onSelect`, which is how the diagram becomes navigable from the keyboard: a reader can walk the graph peer by peer without ever touching the picture.
|
|
46
|
+
|
|
47
|
+
### Props
|
|
48
|
+
|
|
49
|
+
- `eyebrow` — `string`. The kicker over the title — what KIND of thing this panel is showing.
|
|
50
|
+
- `title` (required) — `string`.
|
|
51
|
+
- `description` — `ReactNode`.
|
|
52
|
+
- `facts` — `InspectorFact[]` default `[]`.
|
|
53
|
+
- `links` — `InspectorLink[]` default `[]`.
|
|
54
|
+
- `actions` — `ReactNode`. Buttons under the facts — copy a link, open the source.
|
|
55
|
+
- `onClose` — `() => void`.
|
|
56
|
+
- `className` — `string`.
|
|
57
|
+
- `floating` — `boolean`. Renders as a floating panel over the surface rather than in the flow.
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
<DiagramInspector
|
|
63
|
+
eyebrow="Service"
|
|
64
|
+
title="API Server"
|
|
65
|
+
description="FastAPI, behind the load balancer."
|
|
66
|
+
facts={[
|
|
67
|
+
{ label: 'Port', value: '8000', mono: true },
|
|
68
|
+
{ label: 'Id', value: 'api', mono: true },
|
|
69
|
+
]}
|
|
70
|
+
links={[{ direction: 'out', label: 'SQL', peer: 'PostgreSQL' }]}
|
|
71
|
+
onClose={() => setSelected(null)}
|
|
72
|
+
/>
|
|
73
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# DiagramLegend
|
|
2
|
+
|
|
3
|
+
The key: which drawn form means which kind of thing.
|
|
4
|
+
|
|
5
|
+
- Kind: component
|
|
6
|
+
- Group: Diagrams
|
|
7
|
+
- Import: `import { DiagramLegend } from '@misoto22/folio/diagrams'`
|
|
8
|
+
- Version: 0.17.0
|
|
9
|
+
- Docs: https://ui.misoto22.com/components/diagram-legend/
|
|
10
|
+
- Related: architecture-figure, lifecycle-figure
|
|
11
|
+
|
|
12
|
+
## When to reach for it
|
|
13
|
+
|
|
14
|
+
Not optional furniture in a monochrome system. When a queue and a cache differ by a sigil rather than a colour, this is the only place a reader is told what the sigil means.
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
- **Row** (required) — A wrapping, baseline-aligned row over a top rule. Inside a figure it sits between the picture and the conclusion cards, which is where a reader looks after failing to recognise a mark.
|
|
19
|
+
- **Kicker** — The word Key before the row. title={null} drops it for a bare row, and the list keeps that word as its own accessible name either way.
|
|
20
|
+
- **List** (required) — A <ul> of pairs rather than a row of spans, so the count is part of what a screen reader says about it — "list, six items" is the first useful fact about a key.
|
|
21
|
+
- **Sample** (required) — A 14 × 14 svg carrying the entry’s own markup, hidden from assistive technology. Markup rather than a name from a fixed list, because a key has to show the SAME mark the figure drew.
|
|
22
|
+
- **Label** (required) — The word beside the mark, in the meta voice. The standard builders take it from the same table the plate’s eyebrow prints, so a plate reading SERVICE is never explained by a key reading Datastore.
|
|
23
|
+
|
|
24
|
+
## Best practices
|
|
25
|
+
|
|
26
|
+
### Do
|
|
27
|
+
|
|
28
|
+
- Build the entries with kindLegend, variantLegend or stateLegend. They are made out of the renderers’ own drawing code, so the key cannot come to show a mark the figure does not draw or a word the plate does not print.
|
|
29
|
+
- Leave a figure’s legend at "auto". It lists only the kinds actually drawn; "all" prints seven kinds beside a figure using three, which is four claims the picture does not support.
|
|
30
|
+
- Pass title={null} when the key sits under a caption that already says what it is. The list keeps Key as its accessible name, so the kicker can go without the row losing its name.
|
|
31
|
+
|
|
32
|
+
### Don’t
|
|
33
|
+
|
|
34
|
+
- A key is not where a distinction is MADE. The two state tokens are the only hues these figures spend and each terminal is also its own plate shape — a difference carried by colour alone is one a reader can only look up, an entry at a time, after noticing there is a key at all.
|
|
35
|
+
- legend="hidden" is not free on a figure of tagged plates. A plate prints its tag OR the kind word in the same eyebrow slot and the tag wins, so on a tagged plate the kind is carried by the sigil alone — hiding the key takes the only thing that teaches that sigil off the page.
|
|
36
|
+
|
|
37
|
+
## Accessibility
|
|
38
|
+
|
|
39
|
+
- A list of pairs rather than a row of spans, so the count is part of what a screen reader says about it.
|
|
40
|
+
- kindLegend, variantLegend and stateLegend build the standard sets out of the renderers’ own drawing code, so the key can never drift from the figure.
|
|
41
|
+
|
|
42
|
+
## DiagramLegend
|
|
43
|
+
|
|
44
|
+
The key: which drawn form means which kind of thing. Not optional furniture in a monochrome system, and this is the one place that has to be said plainly. When the difference between a queue and a cache is a sigil rather than a colour, the key is the only place a reader is told what the sigil means — a figure whose forms are undocumented is a figure whose forms might as well not have been drawn. A `<ul>` rather than a row of `<span>`s: it is a list of pairs, and the count is part of what a screen reader should say about it.
|
|
45
|
+
|
|
46
|
+
### Props
|
|
47
|
+
|
|
48
|
+
- `entries` (required) — `DiagramLegendEntry[]`.
|
|
49
|
+
- `title` — `string | null` default `'Key'`. The kicker before the row. Pass null for a bare row.
|
|
50
|
+
- `className` — `string`.
|
|
51
|
+
|
|
52
|
+
## Examples
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
<DiagramLegend entries={kindLegend(['backend', 'database'])} />
|
|
56
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# DiagramMinimap
|
|
2
|
+
|
|
3
|
+
Where you are in something bigger than the window.
|
|
4
|
+
|
|
5
|
+
- Kind: component
|
|
6
|
+
- Group: Diagrams
|
|
7
|
+
- Import: `import { DiagramMinimap } from '@misoto22/folio/diagrams'`
|
|
8
|
+
- Version: 0.17.0
|
|
9
|
+
- Docs: https://ui.misoto22.com/components/diagram-minimap/
|
|
10
|
+
- Related: diagram-canvas
|
|
11
|
+
|
|
12
|
+
## When to reach for it
|
|
13
|
+
|
|
14
|
+
Pairs with DiagramCanvas. The viewport rectangle is derived from the canvas’s own view, never stored — a map that disagrees with its territory is worse than none.
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
- **Map frame** (required) — A fixed-width plate — 200px unless width says otherwise — whose height follows the artwork’s own aspect ratio, named as a group so it is not an unlabelled box beside the figure.
|
|
19
|
+
- **Miniature** (required) — The children under a CSS scale of width over content.width, anchored top-left, hidden from assistive technology and transparent to the pointer. Drawn only once content has a size — at width 0 the scale would be 1 and the miniature would be the artwork’s top-left corner at full size. It answers "what is there" at a glance and nothing more.
|
|
20
|
+
- **Viewport rectangle** (required) — An accent-washed rectangle computed from the canvas’s view and the map’s scale, clipped to the plate so a viewport panned past the artwork stops claiming a map that reaches further, and floored at a few pixels so a deep zoom still leaves something on screen to see. It is derived on every render and never stored.
|
|
21
|
+
- **Seek layer** — The transparent layer over the map that turns a press, or a drag that STARTED on it, into a point in CONTENT coordinates and hands it to onSeek. A button pressed elsewhere and dragged across it moves nothing. Nor does the map itself — it has no authority over the view.
|
|
22
|
+
|
|
23
|
+
## Best practices
|
|
24
|
+
|
|
25
|
+
### Do
|
|
26
|
+
|
|
27
|
+
- Feed it the canvas’s own onViewChange. The rectangle is arithmetic on those three numbers, so a map wired that way cannot disagree with the frame it maps — and keeping a second copy of where the viewport is, is exactly how one comes to.
|
|
28
|
+
- Measure content at the artwork’s natural CSS size. Everything here is scaled by width over content.width, so a wrong content width scales the miniature and the rectangle by the same wrong factor: the map still looks plausible and points at the wrong part of the picture. A width of 0 draws an empty plate instead, which is what a measurement that has not landed yet should look like.
|
|
29
|
+
- Let the canvas say how big the frame is. Every view a DiagramCanvas emits carries the frame it was measured against, so passing onViewChange through is enough — the frame prop is for a frame this component cannot be told about, and a hand-declared one is the single number that makes the rectangle lie.
|
|
30
|
+
- Send onSeek straight to the canvas handle’s centerOn. The point arrives in content coordinates, which is the space centerOn already takes, so recentring needs no conversion of your own.
|
|
31
|
+
|
|
32
|
+
### Don’t
|
|
33
|
+
|
|
34
|
+
- It is pointer-only and hidden from assistive technology: no tab stop, no keys, and the miniature deliberately publishes nothing because the figure it mirrors already does. The canvas’s arrow keys stay the keyboard’s route to a far corner, so the minimap must never be the only way to reach one.
|
|
35
|
+
- The miniature is the same markup shrunk, not a simplified drawing — every label goes down with it, so a wide figure at 200px is a shape rather than a reading copy. It answers where you are; what a node says is the figure’s job.
|
|
36
|
+
|
|
37
|
+
## Accessibility
|
|
38
|
+
|
|
39
|
+
- The miniature is aria-hidden. The figure it mirrors already publishes its own summary, and a second copy would read the whole diagram out twice.
|
|
40
|
+
|
|
41
|
+
## DiagramMinimap
|
|
42
|
+
|
|
43
|
+
Where you are in something bigger than the window. Two things at once, and both are needed: a miniature of the whole artwork, and a rectangle showing which part of it the frame is currently over. The miniature alone answers "what is there"; the rectangle answers "and where am I", which is the question a reader who has just panned twice actually has. THE RECTANGLE IS DERIVED, never stored. Its position comes out of the canvas's own view — the same three numbers the canvas is already transforming by — divided by the map's scale, and clamped to the plate: a viewport that has been panned past the edge of the artwork is a viewport half over blank paper, and drawing the rectangle out there claims the map extends somewhere it does not. Keeping a second copy of "where the viewport is" is how a minimap comes to disagree with the thing it is a map of, and a map that disagrees is worse than none. NOTHING IS DRAWN UNTIL THE ARTWORK HAS A SIZE. `content` is usually a measurement, and a measurement's first value is zero — so the scale would be 1, the miniature would be the artwork's top-left corner at full size, and the rectangle would sit over it meaning nothing. An empty plate for one frame is the honest version of "not yet". CLICKING RECENTRES rather than jumping. `onSeek` reports a point in CONTENT coordinates, which is what a canvas's `centerOn` takes. The minimap does not move anything itself: it has no authority over the view, it only says where the reader pointed. A drag keeps seeking, and only a drag that STARTED on the map does — a button held down somewhere else and dragged across is not this component's gesture to answer.
|
|
44
|
+
|
|
45
|
+
### Props
|
|
46
|
+
|
|
47
|
+
- `content` (required) — `{ width: number; height: number }`. The whole artwork, at its natural size in CSS pixels.
|
|
48
|
+
- `frame` — `{ width: number; height: number }`. The frame the artwork is being looked at through, in CSS pixels. Optional because a `DiagramCanvas` now reports its own frame on every view it emits: wire `onViewChange` straight through and this is already right. Pass it only for a frame this component cannot be told about.
|
|
49
|
+
- `view` (required) — `CanvasView`. Where that frame currently sits — a `DiagramCanvas`'s `onViewChange`.
|
|
50
|
+
- `children` — `ReactNode`. A miniature of the artwork. Usually the same figure, rendered again.
|
|
51
|
+
- `onSeek` — `(x: number, y: number) => void`. Called with a point in CONTENT coordinates when the reader picks one.
|
|
52
|
+
- `width` — `number` default `200`. How wide the map is, in CSS pixels. Height follows the aspect ratio.
|
|
53
|
+
- `className` — `string`.
|
|
54
|
+
- `label` — `string` default `'Diagram overview'`.
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
const canvas = useRef<DiagramCanvasHandle>(null)
|
|
60
|
+
const [view, setView] = useState({ scale: 1, x: 0, y: 0 })
|
|
61
|
+
// …
|
|
62
|
+
<DiagramMinimap
|
|
63
|
+
content={{ width: 1400, height: 620 }}
|
|
64
|
+
view={view}
|
|
65
|
+
onSeek={(x, y) => canvas.current?.centerOn(x, y)}
|
|
66
|
+
>
|
|
67
|
+
<ArchitectureFigure spec={spec} heading={false} legend="hidden" cards={false} />
|
|
68
|
+
</DiagramMinimap>
|
|
69
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# DiagramToolbar
|
|
2
|
+
|
|
3
|
+
A bar of actions belonging to the surface underneath them.
|
|
4
|
+
|
|
5
|
+
- Kind: component
|
|
6
|
+
- Group: Diagrams
|
|
7
|
+
- Import: `import { DiagramToolbar } from '@misoto22/folio/diagrams'`
|
|
8
|
+
- Version: 0.17.0
|
|
9
|
+
- Docs: https://ui.misoto22.com/components/diagram-toolbar/
|
|
10
|
+
- Related: floating-icon-button, diagram-export-menu
|
|
11
|
+
|
|
12
|
+
## When to reach for it
|
|
13
|
+
|
|
14
|
+
FloatingIconButton is one pinned action. This is the container for several, so they read as one object rather than as a scatter.
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
- **Bar** (required) — role="toolbar" with a horizontal orientation, on a panel plate with a hairline and the system’s corner. One plate and one border is what makes six pinned buttons read as one object instead of as six.
|
|
19
|
+
- **Name** (required) — label, which becomes the bar’s accessible name. It is a required prop with no default, because a toolbar that announces its role and nothing else is a group a screen reader cannot tell from the next one.
|
|
20
|
+
- **Group** (required) — DiagramToolbarGroup: one run of related controls, divided by a hairline on its leading edge rather than by space. The first group carries no rule, so the bar does not open with a divider.
|
|
21
|
+
- **Controls** (required) — The children, at whatever size the caller gives them. The bar sets the gap and paints no state of its own — a button in here is the same button it is anywhere else.
|
|
22
|
+
- **Pin** — placement="floating" takes the bar out of the flow and pins it to the top edge of the nearest POSITIONED ancestor, at the sticky rank — under every anchored panel and every dialog — with align choosing the corner. placement="inline" leaves it in the flow and pins nothing.
|
|
23
|
+
|
|
24
|
+
## Best practices
|
|
25
|
+
|
|
26
|
+
### Do
|
|
27
|
+
|
|
28
|
+
- Give label the bar’s job rather than its shape — "Diagram actions", not "Toolbar" — because a page with a figure and a table otherwise announces two toolbars and distinguishes neither.
|
|
29
|
+
- Divide with DiagramToolbarGroup rather than with a gap. The rule is drawn on the group, and a gap wide enough to read as a boundary is also wide enough to stop the bar reading as one object, which is the reason the controls were collected at all.
|
|
30
|
+
- Keep it to a handful of controls. There is no roving focus here, so Tab visits every one of them: ten actions in the bar is ten stops between the reader and the rest of the page.
|
|
31
|
+
|
|
32
|
+
### Don’t
|
|
33
|
+
|
|
34
|
+
- A floating bar sits over the surface, not beside it. Whatever is in that corner of the figure is underneath it — pad the surface, or use placement="inline" and let the bar take its own row.
|
|
35
|
+
- role="toolbar" is a promise about the keyboard as well as a name: a reader is told this is a toolbar and expects the arrow keys to move inside it. For two buttons that merely sit next to each other, a plain div makes no promise this component then has to keep.
|
|
36
|
+
- A floating bar is a SIBLING of the canvas inside a positioned wrapper, never a child of it. Everything handed to DiagramCanvas renders inside the transformed stage, so a bar passed as a child zooms and pans away with the diagram it was put there to control — and with no positioned ancestor at all it pins to whichever box further up the page happens to be one.
|
|
37
|
+
|
|
38
|
+
## Accessibility
|
|
39
|
+
|
|
40
|
+
- role="toolbar" announces a toolbar rather than six unrelated buttons. It does not implement roving focus — Tab visits every control, which is honest for a bar of three.
|
|
41
|
+
|
|
42
|
+
## DiagramToolbar
|
|
43
|
+
|
|
44
|
+
A bar of actions that belong to the surface underneath them. The package already has `FloatingIconButton` for ONE pinned action. This is the container for several — which is a different problem, because several pinned buttons need to read as one object rather than as a scatter: one plate, one border, hairlines between the groups, and a single `role="toolbar"` so a screen reader announces a toolbar instead of six unrelated buttons. `role="toolbar"` also changes the keyboard contract, and callers should know what they are opting into: arrow keys are expected to move between the controls and Tab is expected to leave the bar. This component does not implement roving focus for you — a bar of three buttons where Tab visits all three is honest and fine — so pass `placement="inline"` and skip the role by using a plain `<div>` if that is not what you want.
|
|
45
|
+
|
|
46
|
+
### Props
|
|
47
|
+
|
|
48
|
+
- `children` (required) — `ReactNode`.
|
|
49
|
+
- `placement` — `'inline' | 'floating'` default `'inline'`. Where it sits. `floating` pins it over the surface it acts on.
|
|
50
|
+
- `align` — `'start' | 'end'` default `'end'`. Which corner a floating bar pins to.
|
|
51
|
+
- `label` (required) — `string`.
|
|
52
|
+
|
|
53
|
+
Also accepts: `Omit<ComponentProps<'div'>, 'children'>`.
|
|
54
|
+
|
|
55
|
+
## DiagramToolbarGroup
|
|
56
|
+
|
|
57
|
+
One run of related controls inside the bar. Separated by a hairline rather than by space, because a gap large enough to read as a group boundary is also large enough to stop the bar reading as one object — which is the whole reason the controls were collected into a bar.
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
<DiagramToolbar label="Diagram actions" placement="floating">
|
|
63
|
+
<DiagramToolbarGroup>
|
|
64
|
+
<Button size="sm" variant="ghost">Theme</Button>
|
|
65
|
+
</DiagramToolbarGroup>
|
|
66
|
+
<DiagramToolbarGroup>
|
|
67
|
+
<DiagramExportMenu targetRef={svg} title="Request path" />
|
|
68
|
+
</DiagramToolbarGroup>
|
|
69
|
+
</DiagramToolbar>
|
|
70
|
+
```
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Dialog
|
|
2
|
+
|
|
3
|
+
A modal surface: portal, scrim, centred panel.
|
|
4
|
+
|
|
5
|
+
- Kind: component
|
|
6
|
+
- Group: Overlays
|
|
7
|
+
- Import: `import { Dialog } from '@misoto22/folio'`
|
|
8
|
+
- Version: 0.17.0
|
|
9
|
+
- Docs: https://ui.misoto22.com/components/dialog/
|
|
10
|
+
- Related: dropdown-menu, tooltip
|
|
11
|
+
|
|
12
|
+
## Anatomy
|
|
13
|
+
|
|
14
|
+
- **Scrim** (required) — The full-viewport --scrim layer at --z-overlay (200). It is what a click outside lands on, and it paints over everything the page had pinned below that rank — a FloatingIconButton at 100 included. Not over an anchored panel: those sit at 220 precisely so a Select opened inside this dialog is still reachable.
|
|
15
|
+
- **Panel** (required) — The centred box at --z-modal (210), capped at min(92vw, 32rem) wide and 85vh tall, scrolling its own body past that. It centres itself with a translate, which has consequences for anything fixed inside it.
|
|
16
|
+
- **Title** (required) — title, rendered as the Radix Title. Always present: when title is omitted a visually hidden one is rendered reading the literal word “Dialog”, and development warns DIALOG_TITLE_MISSING — the fallback exists so an unnamed modal is not shipped, not so one can be.
|
|
17
|
+
- **Description** — description, a quiet line under the title. It shares one wrapper with the title, so hideTitle hides both.
|
|
18
|
+
- **Close** — The 36px X in the top-end corner, rendered while showClose is true (the default) and carrying its own aria-label of “Close”.
|
|
19
|
+
|
|
20
|
+
## Best practices
|
|
21
|
+
|
|
22
|
+
### Do
|
|
23
|
+
|
|
24
|
+
- Pass title even when you set hideTitle: with no title at all the fallback accessible name is the literal string “Dialog”, so every unnamed modal in the app is announced as the same thing — and it passes an automated accessibility check while doing it, which is why development warns instead of leaving it to a review.
|
|
25
|
+
- Wrap the cancelling control in DialogClose rather than flipping your own state — the close then runs through Radix, which returns focus to the trigger instead of dropping it at the top of the document.
|
|
26
|
+
- Keep it to what fits. The panel stops at 32rem by 85vh and scrolls its own body past that, so a form long enough to scroll has become a Sheet, which gets the full height of the viewport, or a page.
|
|
27
|
+
- Leave showClose on unless the panel supplies its own exit: Escape and the scrim are the only other ways out and neither is visible, so showClose={false} on a dialog full of content is a room with an unmarked door.
|
|
28
|
+
|
|
29
|
+
### Don’t
|
|
30
|
+
|
|
31
|
+
- An OverlayContainer whose element is not positioned hands the dialog the wrong box: naming a container switches the panel from fixed to absolute, and an unpositioned container sends it to the nearest positioned ancestor instead — usually the page, which looks like the container was ignored.
|
|
32
|
+
- Two dialogs open at once are ordered by the DOM, not by a rank: both sit at --z-modal, so the one mounted last paints over the first — a command palette summoned over a dialog lands on top because it opened second, and reversing that order reverses the picture.
|
|
33
|
+
- The panel centres itself with a transform, which makes it the containing block for every position: fixed descendant — a FloatingIconButton dropped inside a dialog pins to the panel’s corner rather than the screen’s.
|
|
34
|
+
|
|
35
|
+
## Accessibility
|
|
36
|
+
|
|
37
|
+
- Radix owns the focus trap, Escape, the scroll lock and aria-modal.
|
|
38
|
+
- A dialog without a visible heading still renders a hidden title, rather than shipping an unnamed modal.
|
|
39
|
+
|
|
40
|
+
## Keyboard
|
|
41
|
+
|
|
42
|
+
- Escape — Closes it, and focus returns to the trigger it came from.
|
|
43
|
+
- Tab — Cycles inside the dialog; focus cannot leave while it is open.
|
|
44
|
+
|
|
45
|
+
## Dialog
|
|
46
|
+
|
|
47
|
+
Radix Dialog root + trigger + close, re-exported as typed passthroughs.
|
|
48
|
+
|
|
49
|
+
## DialogTrigger
|
|
50
|
+
|
|
51
|
+
## DialogClose
|
|
52
|
+
|
|
53
|
+
## DialogContent
|
|
54
|
+
|
|
55
|
+
A modal surface: portal → scrim → centred panel. Radix owns the focus trap, the escape key, the scroll lock and the `aria-modal` wiring — all of which a hand-rolled dialog gets subtly wrong, usually by leaving focus behind in the page underneath. Radix requires a `Dialog.Title` whether or not one is shown, so a dialog without a visible heading still renders a hidden one rather than shipping an unnamed modal — and warns in development, because the fallback it renders is the literal word "Dialog" and a placeholder that passes an accessibility check is how the problem survives a review. Portals into the element an enclosing `OverlayContainer` names, and switches from viewport positioning to container positioning when there is one. A `fixed` panel covers the page whatever it is portalled into, so honouring the container without that swap would have moved the markup and left the picture unchanged.
|
|
56
|
+
|
|
57
|
+
### Props
|
|
58
|
+
|
|
59
|
+
- `title` — `ReactNode`. Heading text. Pass one even when `hideTitle` is set. Radix requires a title, so omitting it renders a hidden fallback reading the literal word "Dialog" — which satisfies an automated accessibility check and announces every unnamed modal in the application as the same thing. Development says so out loud.
|
|
60
|
+
- `description` — `ReactNode`. Sub-heading under the title.
|
|
61
|
+
- `className` — `string`.
|
|
62
|
+
- `showClose` — `boolean` default `true`. Show the top-right close control (default true).
|
|
63
|
+
- `hideTitle` — `boolean` default `false`. Keeps the title for assistive tech and hides it visually. For a surface whose purpose is obvious to anyone who can see it — a command palette, a media lightbox — where a printed heading would be furniture. The title itself is never optional: Radix requires one, and a modal with no accessible name drops a screen reader into an unnamed region.
|
|
64
|
+
|
|
65
|
+
Also accepts: `Omit<ComponentProps<typeof DialogPrimitive.Content>, 'title' | 'className'>`.
|
|
66
|
+
|
|
67
|
+
## Examples
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
<Dialog>
|
|
71
|
+
<DialogTrigger asChild><Button>Delete</Button></DialogTrigger>
|
|
72
|
+
<DialogContent title="Delete file" description="This cannot be undone.">
|
|
73
|
+
<DialogClose asChild><Button variant="secondary">Cancel</Button></DialogClose>
|
|
74
|
+
</DialogContent>
|
|
75
|
+
</Dialog>
|
|
76
|
+
```
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# DropdownMenu
|
|
2
|
+
|
|
3
|
+
A menu of actions.
|
|
4
|
+
|
|
5
|
+
- Kind: component
|
|
6
|
+
- Group: Overlays
|
|
7
|
+
- Import: `import { DropdownMenu } from '@misoto22/folio'`
|
|
8
|
+
- Version: 0.17.0
|
|
9
|
+
- Docs: https://ui.misoto22.com/components/dropdown-menu/
|
|
10
|
+
- Related: dialog, select
|
|
11
|
+
|
|
12
|
+
## When to reach for it
|
|
13
|
+
|
|
14
|
+
Actions. Items that navigate belong in a nav; items that set a value are a Select or a RadioGroup.
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
- **Trigger** (required) — A passthrough to Radix, which renders its own bare button unless you pass asChild. It carries aria-haspopup and data-state, which is what lets a Button show that its menu is open.
|
|
19
|
+
- **Panel** (required) — The portalled menu: at least 11rem wide, 6px off the trigger, colliding with 8px of padding against the viewport or the OverlayContainer frame. It has no max height, so it flips rather than scrolls.
|
|
20
|
+
- **Item** — A row. icon takes either spelling — the icon component, sized to 16px here, or a rendered element, placed as given; destructive paints the row --danger; disabled drops pointer events and the opacity.
|
|
21
|
+
- **Label** — A mono eyebrow, on its own. Visual only — Radix renders it as a plain div, and the arrow keys skip it. DropdownMenuGroup is the one that heads rows: it renders role="group" and points its aria-labelledby at this.
|
|
22
|
+
- **Group** — A named section: role="group" around the rows, with label rendered inside it as the Label and named through aria-labelledby. The wiring is the component’s job because a caller doing it by hand has to invent an id.
|
|
23
|
+
- **Separator** — A hairline between groups, and a real role="separator" — which a menu permits, unlike the listbox a Command palette is built on.
|
|
24
|
+
|
|
25
|
+
## Best practices
|
|
26
|
+
|
|
27
|
+
### Do
|
|
28
|
+
|
|
29
|
+
- Pass icon the component — icon={Settings} — and let the row size it, so a menu of ten rows draws ten icons at one size rather than ten sizes. The element spelling is accepted too, and used to be the exact opposite of what CommandItem took one import away.
|
|
30
|
+
- Give the trigger asChild and a real Button: without it Radix renders its own unstyled button, and the menu ends up hanging off a control that is not part of the system’s set.
|
|
31
|
+
- Hold a dialog’s open state yourself and call event.preventDefault() in the item’s onSelect — selecting a row closes the menu, and Radix’s close moves focus back to the trigger, which arrives after the dialog has claimed it and pulls the reader straight back out.
|
|
32
|
+
- Stop at about a dozen rows. There is no max height on the panel, so a longer menu grows until it hits the collision padding and flips above the trigger — SearchableMenu is the same list once it has outgrown this one.
|
|
33
|
+
|
|
34
|
+
### Don’t
|
|
35
|
+
|
|
36
|
+
- Radix defaults modal to true and nothing here overrides it, so while the menu is open the page behind is scroll-locked and its pointer events are off — a menu is not the place for something the reader is meant to consult the page while using.
|
|
37
|
+
- A bare DropdownMenuLabel over rows is a picture of a heading: Radix’s MenuLabel is a plain div with no role and nothing tying it to what follows, so the sections a sighted reader sees arrive as one undivided list. DropdownMenuGroup renders both halves and wires them together.
|
|
38
|
+
- There is no checkbox item, radio item or submenu in this package’s exports — a menu that needs a checked state has to import from @radix-ui/react-dropdown-menu directly, and that row arrives with none of this file’s styling on it.
|
|
39
|
+
|
|
40
|
+
## Accessibility
|
|
41
|
+
|
|
42
|
+
- Inside a bounded frame — a device preview, an embedded console — wrap the subtree in `<OverlayContainer container={el}>`. The panel then renders into that element and collides with its edges instead of the viewport’s, and inherits the `dir` and `data-density` set there.
|
|
43
|
+
- Highlight is driven by data-highlighted, which covers hover AND keyboard focus — styling :hover alone leaves the keyboard user unable to see where they are.
|
|
44
|
+
- DropdownMenuGroup segments the menu for a screen reader as well as for the eye; a bare Label does it for the eye alone.
|
|
45
|
+
|
|
46
|
+
## Keyboard
|
|
47
|
+
|
|
48
|
+
- Enter / Space / ↓ — Opens the menu and lands on the first item.
|
|
49
|
+
- ↑ / ↓ — Moves between items.
|
|
50
|
+
- a–z — Jumps to the next item starting with that letter.
|
|
51
|
+
- Escape — Closes the menu and returns focus to the trigger.
|
|
52
|
+
|
|
53
|
+
## DropdownMenu
|
|
54
|
+
|
|
55
|
+
Radix DropdownMenu root + trigger, re-exported as typed passthroughs.
|
|
56
|
+
|
|
57
|
+
## DropdownMenuTrigger
|
|
58
|
+
|
|
59
|
+
## DropdownMenuContent
|
|
60
|
+
|
|
61
|
+
A menu surface. A menu is a list of ACTIONS. If the items navigate somewhere, they belong in a nav; if they set a value, that is a `Select` or a `RadioGroup` — this package ships no checkbox or radio menu item, and a plain item pretending to be a choice loses the checked state a screen reader needs.
|
|
62
|
+
|
|
63
|
+
Also accepts: `ComponentProps<typeof DropdownMenuPrimitive.Content>`.
|
|
64
|
+
|
|
65
|
+
## DropdownMenuItem
|
|
66
|
+
|
|
67
|
+
A menu row. Highlight is driven by Radix's `data-highlighted`, which covers both pointer hover and keyboard focus — styling `:hover` alone leaves the keyboard user unable to see where they are.
|
|
68
|
+
|
|
69
|
+
### Props
|
|
70
|
+
|
|
71
|
+
- `icon` — `RemixiconComponentType | ReactNode`. Optional leading icon, rendered before the label. Either spelling: `icon={Settings}` passes the component and this sizes it, `icon={<Settings size={16} />}` passes the element and this places it. The two used to mean opposite things one import apart — `CommandItem.icon` took the element while this took the component — and the wrong one did not fail a type check into anything actionable, it failed at render.
|
|
72
|
+
- `destructive` — `boolean` default `false`. Paints the row as destructive. Use for delete, revoke, disconnect.
|
|
73
|
+
|
|
74
|
+
Also accepts: `ComponentProps<typeof DropdownMenuPrimitive.Item>`.
|
|
75
|
+
|
|
76
|
+
## DropdownMenuSeparator
|
|
77
|
+
|
|
78
|
+
Hairline divider between menu groups.
|
|
79
|
+
|
|
80
|
+
## DropdownMenuLabel
|
|
81
|
+
|
|
82
|
+
Mono eyebrow heading, on its own. Visual only: Radix renders it as a bare `<div>` with no role, so it segments the menu for a reader who can see it and for nobody else. Reach for `DropdownMenuGroup` when the eyebrow is a HEADING over rows; this is right for a line that heads nothing — the signed-in address at the top of an account menu.
|
|
83
|
+
|
|
84
|
+
## DropdownMenuGroup
|
|
85
|
+
|
|
86
|
+
A named section of a menu. The eyebrow alone was a picture of a heading. Radix's `MenuLabel` carries no role and no `aria-labelledby` wiring, and `MenuGroup` — which does carry `role="group"` — was not re-exported by this package at all, so a sighted reader saw three labelled sections and a screen-reader user got one undifferentiated list. This renders the group, renders the label inside it, and points the one at the other, which is the whole of the fix and not something a caller should have to remember.
|
|
87
|
+
|
|
88
|
+
### Props
|
|
89
|
+
|
|
90
|
+
- `label` — `ReactNode`. The eyebrow over the rows, and the group's accessible name.
|
|
91
|
+
|
|
92
|
+
Also accepts: `ComponentProps<typeof DropdownMenuPrimitive.Group>`.
|
|
93
|
+
|
|
94
|
+
## Examples
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
<DropdownMenu>
|
|
98
|
+
<DropdownMenuTrigger asChild><Button variant="secondary">Menu</Button></DropdownMenuTrigger>
|
|
99
|
+
<DropdownMenuContent>
|
|
100
|
+
<DropdownMenuGroup label="Account">
|
|
101
|
+
<DropdownMenuItem icon={Settings}>Settings</DropdownMenuItem>
|
|
102
|
+
</DropdownMenuGroup>
|
|
103
|
+
<DropdownMenuSeparator />
|
|
104
|
+
<DropdownMenuItem icon={LogOut}>Sign out</DropdownMenuItem>
|
|
105
|
+
</DropdownMenuContent>
|
|
106
|
+
</DropdownMenu>
|
|
107
|
+
<DropdownMenuGroup label="Account">
|
|
108
|
+
<DropdownMenuItem icon={Settings}>Settings</DropdownMenuItem>
|
|
109
|
+
</DropdownMenuGroup>
|
|
110
|
+
```
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# EmptyState
|
|
2
|
+
|
|
3
|
+
A collection with nothing in it — yet.
|
|
4
|
+
|
|
5
|
+
- Kind: component
|
|
6
|
+
- Group: Feedback
|
|
7
|
+
- Import: `import { EmptyState } from '@misoto22/folio'`
|
|
8
|
+
- Version: 0.17.0
|
|
9
|
+
- Docs: https://ui.misoto22.com/components/empty-state/
|
|
10
|
+
- Related: error-state, skeleton
|
|
11
|
+
|
|
12
|
+
## When to reach for it
|
|
13
|
+
|
|
14
|
+
Nothing went wrong. The copy says what to do, not what failed.
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
- **Frame** (required) — A centred column with 80px of padding above and below and --page-pad either side. View-scale, and carrying no role and no live region of its own.
|
|
19
|
+
- **Medallion** — The optional Remix Icon glyph at 24px inside a 56px --stone circle, aria-hidden. Decoration that gives the column something to start from, never the message.
|
|
20
|
+
- **Title** (required) — title in the heading face at --fs-sub, rendered through Heading. level picks the element and defaults to 2; the size does not follow it, so the title is --fs-sub at every level.
|
|
21
|
+
- **Description** — description in --ink-3-aa, capped at 24rem so it stays a readable measure while the column stays centred.
|
|
22
|
+
- **Action** — The one thing to do next, 32px below the description and the only interactive element the frame offers.
|
|
23
|
+
|
|
24
|
+
## Best practices
|
|
25
|
+
|
|
26
|
+
### Do
|
|
27
|
+
|
|
28
|
+
- Announce the swap yourself. This component has no role and no live region, so replacing a SkeletonPage with it removes the region that said “Loading projects” and puts nothing in its place — a screen reader is left at the last thing it heard.
|
|
29
|
+
- Say which kind of empty this is. The same component serves a collection that is new and one that a filter has emptied, and “No projects yet” shown over an active filter tells the reader their projects are gone.
|
|
30
|
+
- Set level from the heading above it. The default of 2 is right directly under a page’s h1; inside a section that already has its own h2, pass 3. Get it wrong and the outline gains a hole a screen reader navigates by.
|
|
31
|
+
|
|
32
|
+
### Don’t
|
|
33
|
+
|
|
34
|
+
- Do not show it for a failed request. A reader told the collection is empty acts on it — creating the record they already have, or reporting a data loss that never happened — and the recovery from that costs more than the error page would have.
|
|
35
|
+
- Do not put it inside a card or a panel. 160px of vertical padding is sized to stand in for a view, and in a bordered box it reads as a box with a hole in it.
|
|
36
|
+
- Do not write a paragraph into description. It is capped at 24rem and centred, so long copy becomes a narrow ragged column that the eye returns from before the sentence that mattered.
|
|
37
|
+
|
|
38
|
+
## EmptyState
|
|
39
|
+
|
|
40
|
+
A collection with nothing in it — yet. Distinct from `ErrorState`: nothing went wrong here, so the copy says what to do rather than what failed. The two are different components because the shared temptation — one component with a `variant` — produces error pages that read like empty folders.
|
|
41
|
+
|
|
42
|
+
### Props
|
|
43
|
+
|
|
44
|
+
- `icon` — `RemixiconComponentType`. Optional Remix Icon glyph, shown muted inside a quiet circle.
|
|
45
|
+
- `title` (required) — `ReactNode`.
|
|
46
|
+
- `description` — `ReactNode`.
|
|
47
|
+
- `action` — `ReactNode`. The one thing to do next. An empty state without an action is a dead end.
|
|
48
|
+
- `level` — `HeadingLevel` default `2`. The heading level `title` opens, in the document the empty state lands in. Defaults to `2`, which is the placement this component is sized for: it stands in for a whole view inside a page that already has an `h1`, so the level below that one is the level that does not leave a hole in heading navigation. Under a section that already has its own `h2`, pass `3`. The default was `3` and fixed, which was wrong in the ordinary case and impossible to correct — the documentation could name the rule but a caller had no prop to follow it with. `2` is the common case rather than a compromise, and it is optional rather than required because the correct placement has one answer often enough that making every existing call site restate it would buy nothing. The size does not follow the level. `title` renders at `--fs-sub` at every level, because moving a state down the outline is a fact about the document and not a request for smaller type.
|
|
49
|
+
|
|
50
|
+
Also accepts: `Omit<HTMLAttributes<HTMLDivElement>, 'title'>`.
|
|
51
|
+
|
|
52
|
+
## Examples
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
<EmptyState
|
|
56
|
+
icon={Inbox}
|
|
57
|
+
title="No projects yet"
|
|
58
|
+
description="Create your first project to get started."
|
|
59
|
+
action={<Button>New project</Button>}
|
|
60
|
+
/>
|
|
61
|
+
// Inside a section that already has its own heading.
|
|
62
|
+
<EmptyState level={3} title="No invoices yet" />
|
|
63
|
+
```
|