@misoto22/design 0.6.1 → 0.8.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 +87 -0
- package/CLAUDE.md +1 -0
- package/README.md +62 -5
- package/bin/misoto22-design.mjs +59 -13
- package/dist/agent/Accordion.md +24 -1
- package/dist/agent/Alert.md +23 -1
- package/dist/agent/AppShell.md +30 -2
- package/dist/agent/ArchitectureFigure.md +71 -0
- package/dist/agent/AreaChart.md +27 -2
- package/dist/agent/Article.md +26 -3
- package/dist/agent/AspectRatio.md +57 -0
- package/dist/agent/Avatar.md +25 -5
- package/dist/agent/Badge.md +22 -1
- package/dist/agent/BarChart.md +29 -2
- package/dist/agent/BarList.md +27 -1
- package/dist/agent/BigNumber.md +26 -2
- package/dist/agent/BoxPlot.md +24 -1
- package/dist/agent/Breadcrumb.md +24 -2
- package/dist/agent/BulletChart.md +23 -1
- package/dist/agent/Button.md +25 -1
- package/dist/agent/Calendar.md +37 -3
- package/dist/agent/Card.md +24 -2
- package/dist/agent/Checkbox.md +23 -2
- package/dist/agent/Code.md +50 -0
- package/dist/agent/CodeBlock.md +74 -0
- package/dist/agent/Collapsible.md +22 -1
- package/dist/agent/Combobox.md +29 -3
- package/dist/agent/Command.md +25 -2
- package/dist/agent/ComposedChart.md +26 -2
- package/dist/agent/ContextMenu.md +37 -4
- package/dist/agent/DataflowFigure.md +48 -0
- package/dist/agent/DatePicker.md +34 -6
- package/dist/agent/DescriptionList.md +68 -0
- package/dist/agent/Diagram.md +27 -3
- package/dist/agent/DiagramCanvas.md +70 -0
- package/dist/agent/DiagramExportMenu.md +64 -0
- package/dist/agent/DiagramInspector.md +72 -0
- package/dist/agent/DiagramLegend.md +55 -0
- package/dist/agent/DiagramMinimap.md +68 -0
- package/dist/agent/DiagramToolbar.md +69 -0
- package/dist/agent/Dialog.md +26 -3
- package/dist/agent/DropdownMenu.md +45 -6
- package/dist/agent/EmptyState.md +26 -1
- package/dist/agent/ErrorState.md +27 -2
- package/dist/agent/Facet.md +25 -1
- package/dist/agent/Field.md +45 -4
- package/dist/agent/FigureBand.md +24 -1
- package/dist/agent/FloatingIconButton.md +23 -1
- package/dist/agent/FunnelChart.md +23 -1
- package/dist/agent/Heading.md +64 -0
- package/dist/agent/Heatmap.md +25 -1
- package/dist/agent/Histogram.md +26 -2
- package/dist/agent/Input.md +22 -1
- package/dist/agent/Kbd.md +19 -1
- package/dist/agent/LifecycleFigure.md +49 -0
- package/dist/agent/LineChart.md +26 -2
- package/dist/agent/LinkArrow.md +20 -1
- package/dist/agent/Markdown.md +68 -0
- package/dist/agent/NativeSelect.md +23 -2
- package/dist/agent/NavItem.md +21 -1
- package/dist/agent/Pagination.md +28 -2
- package/dist/agent/PieChart.md +26 -2
- package/dist/agent/Popover.md +23 -1
- package/dist/agent/Progress.md +27 -3
- package/dist/agent/RadarChart.md +26 -2
- package/dist/agent/RadialChart.md +26 -3
- package/dist/agent/RadioGroup.md +23 -2
- package/dist/agent/SankeyChart.md +25 -2
- package/dist/agent/ScatterChart.md +27 -2
- package/dist/agent/ScrollArea.md +24 -3
- package/dist/agent/SearchableMenu.md +23 -1
- package/dist/agent/Select.md +29 -3
- package/dist/agent/Separator.md +28 -4
- package/dist/agent/SequenceFigure.md +50 -0
- package/dist/agent/Sheet.md +25 -2
- package/dist/agent/Skeleton.md +24 -2
- package/dist/agent/Slider.md +27 -4
- package/dist/agent/Sparkline.md +23 -1
- package/dist/agent/Spinner.md +24 -2
- package/dist/agent/StatusDot.md +20 -1
- package/dist/agent/StatusPill.md +28 -2
- package/dist/agent/Steps.md +24 -1
- package/dist/agent/Switch.md +21 -1
- package/dist/agent/Table.md +26 -3
- package/dist/agent/Tabs.md +24 -2
- package/dist/agent/Tag.md +40 -9
- package/dist/agent/Text.md +65 -0
- package/dist/agent/Textarea.md +20 -1
- package/dist/agent/Timestamp.md +64 -0
- package/dist/agent/Toast.md +26 -2
- package/dist/agent/ToggleGroup.md +24 -2
- package/dist/agent/Toolbar.md +71 -0
- package/dist/agent/Tooltip.md +23 -1
- package/dist/agent/TreemapChart.md +24 -1
- package/dist/agent/WaterfallChart.md +24 -1
- package/dist/agent/WorkflowFigure.md +50 -0
- package/dist/agent/catalog.json +6086 -1009
- package/dist/agent/index.md +27 -4
- package/dist/article.css +16 -4
- package/dist/charts/AreaChart/AreaChart.d.ts +9 -2
- package/dist/charts/AreaChart/AreaChart.js +12 -13
- package/dist/charts/AreaChart/AreaChart.js.map +1 -1
- package/dist/charts/BarChart/BarChart.d.ts +14 -3
- package/dist/charts/BarChart/BarChart.js +20 -12
- package/dist/charts/BarChart/BarChart.js.map +1 -1
- package/dist/charts/BarList/BarList.d.ts +9 -1
- package/dist/charts/BarList/BarList.js +9 -1
- package/dist/charts/BarList/BarList.js.map +1 -1
- package/dist/charts/BigNumber/BigNumber.d.ts +19 -3
- package/dist/charts/BigNumber/BigNumber.js +25 -5
- package/dist/charts/BigNumber/BigNumber.js.map +1 -1
- package/dist/charts/BoxPlot/BoxPlot.js +4 -2
- package/dist/charts/BoxPlot/BoxPlot.js.map +1 -1
- package/dist/charts/BulletChart/BulletChart.js +28 -7
- package/dist/charts/BulletChart/BulletChart.js.map +1 -1
- package/dist/charts/ComposedChart/ComposedChart.d.ts +9 -2
- package/dist/charts/ComposedChart/ComposedChart.js +10 -10
- package/dist/charts/ComposedChart/ComposedChart.js.map +1 -1
- package/dist/charts/FunnelChart/FunnelChart.d.ts +7 -2
- package/dist/charts/FunnelChart/FunnelChart.js +6 -16
- package/dist/charts/FunnelChart/FunnelChart.js.map +1 -1
- package/dist/charts/Heatmap/Heatmap.d.ts +17 -3
- package/dist/charts/Heatmap/Heatmap.js +20 -11
- package/dist/charts/Heatmap/Heatmap.js.map +1 -1
- package/dist/charts/Histogram/Histogram.d.ts +24 -1
- package/dist/charts/Histogram/Histogram.js +43 -11
- package/dist/charts/Histogram/Histogram.js.map +1 -1
- package/dist/charts/LineChart/LineChart.d.ts +9 -2
- package/dist/charts/LineChart/LineChart.js +11 -12
- package/dist/charts/LineChart/LineChart.js.map +1 -1
- package/dist/charts/PieChart/PieChart.d.ts +15 -3
- package/dist/charts/PieChart/PieChart.js +14 -6
- package/dist/charts/PieChart/PieChart.js.map +1 -1
- package/dist/charts/RadarChart/RadarChart.d.ts +15 -3
- package/dist/charts/RadarChart/RadarChart.js +11 -9
- package/dist/charts/RadarChart/RadarChart.js.map +1 -1
- package/dist/charts/RadialChart/RadialChart.d.ts +22 -4
- package/dist/charts/RadialChart/RadialChart.js +28 -6
- package/dist/charts/RadialChart/RadialChart.js.map +1 -1
- package/dist/charts/SankeyChart/SankeyChart.d.ts +16 -4
- package/dist/charts/SankeyChart/SankeyChart.js +14 -6
- package/dist/charts/SankeyChart/SankeyChart.js.map +1 -1
- package/dist/charts/ScatterChart/ScatterChart.d.ts +24 -3
- package/dist/charts/ScatterChart/ScatterChart.js +21 -15
- package/dist/charts/ScatterChart/ScatterChart.js.map +1 -1
- package/dist/charts/Sparkline/Sparkline.js +5 -3
- package/dist/charts/Sparkline/Sparkline.js.map +1 -1
- package/dist/charts/TreemapChart/TreemapChart.d.ts +7 -2
- package/dist/charts/TreemapChart/TreemapChart.js +20 -11
- package/dist/charts/TreemapChart/TreemapChart.js.map +1 -1
- package/dist/charts/WaterfallChart/WaterfallChart.js +4 -2
- package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -1
- package/dist/charts/index.d.ts +2 -1
- package/dist/charts/lib/export.d.ts +34 -43
- package/dist/charts/lib/export.js +16 -158
- package/dist/charts/lib/export.js.map +1 -1
- package/dist/charts/lib/figure.d.ts +21 -1
- package/dist/charts/lib/figure.js +5 -2
- package/dist/charts/lib/figure.js.map +1 -1
- 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/toolbar.d.ts +1 -0
- package/dist/components/Accordion/Accordion.js +8 -1
- package/dist/components/Accordion/Accordion.js.map +1 -1
- package/dist/components/AppShell/AppShell.d.ts +6 -0
- package/dist/components/AppShell/AppShell.js +34 -4
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/Article/Article.d.ts +11 -4
- package/dist/components/Article/Article.js +13 -0
- package/dist/components/Article/Article.js.map +1 -1
- 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 +12 -3
- package/dist/components/Avatar/Avatar.js +6 -1
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +6 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +15 -0
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -1
- package/dist/components/Button/Button.js +14 -0
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +29 -3
- package/dist/components/Calendar/Calendar.js +60 -12
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Card/Card.d.ts +6 -0
- package/dist/components/Card/Card.js +1 -1
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +5 -2
- package/dist/components/Checkbox/Checkbox.js +12 -2
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- 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 +141 -0
- package/dist/components/CodeBlock/CodeBlock.js +123 -0
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.js +10 -2
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/Combobox/Combobox.d.ts +15 -1
- package/dist/components/Combobox/Combobox.js +25 -5
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Command/Command.d.ts +4 -2
- package/dist/components/Command/Command.js +13 -1
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.d.ts +30 -5
- package/dist/components/ContextMenu/ContextMenu.js +32 -2
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +36 -4
- package/dist/components/DatePicker/DatePicker.js +55 -12
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- 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 +8 -3
- package/dist/components/Diagram/Diagram.js +82 -10
- package/dist/components/Diagram/Diagram.js.map +1 -1
- package/dist/components/Dialog/Dialog.d.ts +18 -3
- package/dist/components/Dialog/Dialog.js +20 -2
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +49 -11
- package/dist/components/DropdownMenu/DropdownMenu.js +32 -2
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.d.ts +25 -1
- package/dist/components/EmptyState/EmptyState.js +3 -1
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/ErrorState/ErrorState.d.ts +22 -1
- package/dist/components/ErrorState/ErrorState.js +11 -2
- package/dist/components/ErrorState/ErrorState.js.map +1 -1
- package/dist/components/Field/Field.d.ts +70 -3
- package/dist/components/Field/Field.js +53 -12
- package/dist/components/Field/Field.js.map +1 -1
- 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/FloatingIconButton/FloatingIconButton.js +2 -0
- package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -1
- 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/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/NativeSelect/NativeSelect.d.ts +6 -0
- package/dist/components/NativeSelect/NativeSelect.js +2 -3
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -1
- package/dist/components/Pagination/Pagination.d.ts +24 -1
- package/dist/components/Pagination/Pagination.js +6 -3
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Progress/Progress.d.ts +17 -5
- package/dist/components/Progress/Progress.js +18 -6
- package/dist/components/Progress/Progress.js.map +1 -1
- package/dist/components/RadioGroup/RadioGroup.d.ts +6 -0
- package/dist/components/RadioGroup/RadioGroup.js +11 -1
- package/dist/components/RadioGroup/RadioGroup.js.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.d.ts +15 -0
- package/dist/components/ScrollArea/ScrollArea.js +2 -2
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
- package/dist/components/SearchableMenu/SearchableMenu.d.ts +11 -2
- package/dist/components/SearchableMenu/SearchableMenu.js +24 -2
- package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -1
- package/dist/components/Select/Select.d.ts +18 -2
- package/dist/components/Select/Select.js +20 -3
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Separator/Separator.d.ts +21 -3
- package/dist/components/Separator/Separator.js +9 -1
- package/dist/components/Separator/Separator.js.map +1 -1
- package/dist/components/Sheet/Sheet.d.ts +3 -0
- package/dist/components/Sheet/Sheet.js +11 -2
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Skeleton/Skeleton.d.ts +8 -1
- package/dist/components/Skeleton/Skeleton.js +1 -1
- package/dist/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/components/Slider/Slider.d.ts +21 -3
- package/dist/components/Slider/Slider.js +54 -27
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Spinner/Spinner.d.ts +8 -0
- package/dist/components/Spinner/Spinner.js +3 -2
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/components/StatusPill/StatusPill.d.ts +5 -0
- package/dist/components/StatusPill/StatusPill.js +6 -0
- package/dist/components/StatusPill/StatusPill.js.map +1 -1
- package/dist/components/Table/Table.d.ts +6 -0
- package/dist/components/Table/Table.js +3 -1
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Tag/Tag.d.ts +68 -9
- package/dist/components/Tag/Tag.js +50 -10
- package/dist/components/Tag/Tag.js.map +1 -1
- 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/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 +9 -1
- package/dist/components/Toast/Toast.js +27 -4
- package/dist/components/Toast/Toast.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +6 -1
- package/dist/components/ToggleGroup/ToggleGroup.js +11 -1
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
- 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/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 +85 -0
- package/dist/diagrams/lib/route.js +178 -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 +90 -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/index.d.ts +16 -4
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/keyframes.css +57 -3
- package/dist/lib/overlay-container.d.ts +14 -4
- package/dist/lib/overlay-container.js.map +1 -1
- 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/warn.d.ts +73 -0
- package/dist/lib/warn.js +38 -0
- package/dist/lib/warn.js.map +1 -0
- package/dist/semantic.css +51 -6
- package/dist/styles.css +1 -1
- package/dist/tokens.css +20 -2
- package/dist/tokens.d.ts +17 -1
- package/dist/tokens.js +121 -36
- package/dist/tokens.json +121 -36
- package/llms.txt +35 -0
- package/package.json +9 -2
- package/skills/misoto22-design/SKILL.md +21 -7
- package/skills/misoto22-design/evals/evals.json +84 -0
- package/skills/misoto22-design/rules/a11y.md +55 -3
- package/skills/misoto22-design/rules/forms.md +5 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# DescriptionList
|
|
2
|
+
|
|
3
|
+
One record’s fields, as a real <dl> rather than a grid of divs.
|
|
4
|
+
|
|
5
|
+
- Group: Surfaces
|
|
6
|
+
- Import: `import { DescriptionList } from '@misoto22/design'`
|
|
7
|
+
- Version: 0.8.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/description-list/
|
|
9
|
+
- Related: table, card, timestamp
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
One record seen from the front — a detail page, a summary panel. Several records seen from above is a Table.
|
|
14
|
+
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **List** (required) — The <dl>. It is the element that carries the pairing: a grid of divs looks identical and tells a screen reader there are two columns of unrelated text.
|
|
18
|
+
- **Pair** (required) — A <div> around each dt/dd, which the HTML specification allows inside a <dl> precisely so a pair can be laid out as a unit. It is what the hairline is drawn on, so the rule crosses the whole row rather than stopping in the column gap.
|
|
19
|
+
- **Term** (required) — item.term, rendered as <dt> at --ink-3-aa. In the row layout it holds a 12rem column at sm and above and stacks below it, because a 12rem label column on a phone leaves the value about eight characters wide.
|
|
20
|
+
- **Description** (required) — item.description, rendered as <dd> at --ink-2 with its browser margin reset. It takes a node, not a string, so a value can be a Badge, a link or a Timestamp.
|
|
21
|
+
- **Hairline** — divided, on by default: a --rule under every pair but the last. Turn it off inside a Card, which already has an edge of its own.
|
|
22
|
+
|
|
23
|
+
## Best practices
|
|
24
|
+
|
|
25
|
+
### Do
|
|
26
|
+
|
|
27
|
+
- Let it render nothing when items is empty. It returns null rather than an empty bordered box, so the page above is free to show an EmptyState instead of a hairline around no content.
|
|
28
|
+
- Put an element in description when the value is a state or a link — it is a <dd>, so a Badge, an anchor or a Timestamp belongs there and a string of text does not have to be faked into one.
|
|
29
|
+
- Pass id on each item when rows are added, removed or reordered. The index is the key without one, which is right for the fixed field list a record page renders and wrong for a list that changes shape.
|
|
30
|
+
|
|
31
|
+
### Don’t
|
|
32
|
+
|
|
33
|
+
- Do not reach for it to show several records. Every dt would repeat down the page and a reader comparing two records has to hold both in their head — that is what a Table’s column headings exist to avoid.
|
|
34
|
+
- Do not use layout="row" inside a narrow sidebar. It only collapses on the sm breakpoint, which is the viewport, not the container — a 12rem label column inside a 20rem panel leaves nothing for the value. Use layout="stacked" there.
|
|
35
|
+
|
|
36
|
+
## Accessibility
|
|
37
|
+
|
|
38
|
+
- A real <dl>, <dt> and <dd>, which is what tells a screen reader that a label names the value beside it.
|
|
39
|
+
- Each pair is grouped in a <div>, which the specification permits inside a <dl> and which assistive technology reads through.
|
|
40
|
+
- An empty list renders null rather than an empty <dl>, so nothing announces a list with no items in it.
|
|
41
|
+
|
|
42
|
+
## DescriptionList
|
|
43
|
+
|
|
44
|
+
A record's fields: label, value, label, value. The single most repeated shape in any detail page, and the one most often hand-built out of a `<div>` grid — which loses the only thing the markup was carrying. A `<dl>` tells a screen reader that "Owner" names the thing beside it; a grid of divs tells it there are two columns of unrelated text, and the reader has to infer the pairing from reading order alone. Reach for `Table` instead when there are several records. This is one record seen from the front; a table is many records seen from above. Each pair is wrapped in a `<div>` — which the HTML specification allows inside a `<dl>` precisely so a pair can be laid out as a unit — so the hairline runs the full width of the row rather than stopping in the column gap. An empty `items` renders `null` rather than an empty bordered box. A record with no fields is a state the page above should be handling with an `EmptyState`, and a hairline around nothing looks like a component that failed to load.
|
|
45
|
+
|
|
46
|
+
### Props
|
|
47
|
+
|
|
48
|
+
- `items` (required) — `DescriptionListItem[]`. The pairs, in the order they should read. An empty array renders nothing.
|
|
49
|
+
- `layout` — `DescriptionListLayout` default `'row'`. How the value sits relative to its label. See DescriptionListLayout.
|
|
50
|
+
- `divided` — `boolean` default `true`. Draws a hairline under every pair but the last. Off for a list inside a card that already has an edge, on for a list that is the page's structure.
|
|
51
|
+
|
|
52
|
+
Also accepts: `HTMLAttributes<HTMLDListElement>`.
|
|
53
|
+
|
|
54
|
+
## Types
|
|
55
|
+
|
|
56
|
+
- `DescriptionListLayout` = `'row' | 'stacked'`
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
<DescriptionList
|
|
62
|
+
items={[
|
|
63
|
+
{ term: 'Owner', description: 'Henry Chen' },
|
|
64
|
+
{ term: 'Status', description: <Badge tone="success">Deployed</Badge> },
|
|
65
|
+
]}
|
|
66
|
+
/>
|
|
67
|
+
<DescriptionList layout="stacked" divided={false} items={fields} />
|
|
68
|
+
```
|
package/dist/agent/Diagram.md
CHANGED
|
@@ -4,7 +4,7 @@ A flow or architecture figure, drawn out of the system’s own parts.
|
|
|
4
4
|
|
|
5
5
|
- Group: Display
|
|
6
6
|
- Import: `import { Diagram } from '@misoto22/design'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/diagram/
|
|
9
9
|
- Related: card, figure-band
|
|
10
10
|
|
|
@@ -12,11 +12,35 @@ A flow or architecture figure, drawn out of the system’s own parts.
|
|
|
12
12
|
|
|
13
13
|
A picture of structure, in a page rather than in a terminal. Nesting is containment and an edge is a step between siblings — a diagram that needs arbitrary wiring wants a drawing, not this.
|
|
14
14
|
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **Frame** (required) — The <figure role="group"> and the panel inside it: a --rule hairline on the --radius-lg corner over --paper-2, with fluid padding and overflow-x-auto on a hairline scrollbar — so a wide figure scrolls inside its own box instead of widening the page.
|
|
18
|
+
- **Leaf plate** — A node with NO children: a bordered card on --paper, or filled with --accent when accent is set. Its label breaks inside itself, because an identifier like TenantMainMiddleware has no break opportunity and would otherwise run into the plate’s edge.
|
|
19
|
+
- **Container band** — A node WITH children: a labelled hairline — ink at the top rank, --rule-2 below it — with its children underneath and no frame of its own. That is the whole design: drawing a container as another box puts three borders around anything two levels deep.
|
|
20
|
+
- **Node note** — node.note, a mono line beside a band’s label or under a plate’s. One short line, a step back from the name.
|
|
21
|
+
- **Edge mark** — The arrow between two adjacent siblings an edge names, with the edge’s label under it. aria-hidden, and rotated a quarter turn below the sm breakpoint, where a row of nodes stacks into a column and the arrow has to point the way the layout actually runs.
|
|
22
|
+
- **Caption** — spec.caption, printed under the frame — as a <div>, not a <figcaption>, because an article stylesheet styles figcaption unlayered and an unlayered rule beats a utility whatever the specificity.
|
|
23
|
+
|
|
24
|
+
## Best practices
|
|
25
|
+
|
|
26
|
+
### Do
|
|
27
|
+
|
|
28
|
+
- Write an edge from a node to the node immediately after it in the same rank, in that order. An edge between non-adjacent nodes, or one written to→from, draws no arrow — and now says so in the console rather than leaving the author to spot a missing arrow in a picture that otherwise looks finished.
|
|
29
|
+
- Keep ids unique across the whole spec. Each edge is now spent at the first pair that matches it, so a reused pair no longer draws the arrow twice — but the arrow lands on whichever pair comes first, which is a diagram asserting something nobody wrote.
|
|
30
|
+
- Give the spec a caption or a label. The figure’s role="group" is named by whichever is present, and with neither the reader is told there is a group and never told what of.
|
|
31
|
+
|
|
32
|
+
### Don’t
|
|
33
|
+
|
|
34
|
+
- accent is read only in the plate branch, so setting it on a node with children compiles, type-checks and paints nothing — a container is a band, and a band has no fill to take. Development says so; a production build does not.
|
|
35
|
+
- direction is read only from a node that HAS children. Set on a leaf it is ignored, because the axis a leaf sits on belongs to its parent — and, like accent on a band, it is reported in development rather than silently dropped.
|
|
36
|
+
- Do not put six nodes across the top rank. A row is flex-col below sm and only flex-row above it, so a figure that reads as a pipeline on a desktop is six stacked plates and five arrows on a phone.
|
|
37
|
+
|
|
15
38
|
## Accessibility
|
|
16
39
|
|
|
17
40
|
- A <figure> with role="group", named by its caption, so the whole picture is one thing a reader can skip.
|
|
18
41
|
- Arrows are aria-hidden: assistive tech reads the nodes in document order and has no use for a glyph pointing at the next one.
|
|
19
42
|
- Server-rendered markup, not a canvas — every label is real text a screen reader and a search engine can read.
|
|
43
|
+
- A spec the renderer cannot honour — an unmatched edge, a duplicate id, accent on a band, direction on a leaf — prints a named warning in development, because the alternative is a confident picture of something else.
|
|
20
44
|
|
|
21
45
|
## Diagram
|
|
22
46
|
|
|
@@ -36,8 +60,8 @@ A flow or architecture diagram, drawn out of the system's own parts. The alterna
|
|
|
36
60
|
edges: [{ from: 'edge', to: 'app', label: 'HTTPS' }],
|
|
37
61
|
nodes: [
|
|
38
62
|
{ id: 'edge', label: 'Edge', note: 'CDN' },
|
|
39
|
-
{ id: 'app', label: 'Application',
|
|
40
|
-
{ label: 'Router' },
|
|
63
|
+
{ id: 'app', label: 'Application', children: [
|
|
64
|
+
{ label: 'Router', accent: true },
|
|
41
65
|
{ label: 'Handlers' },
|
|
42
66
|
] },
|
|
43
67
|
],
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# DiagramCanvas
|
|
2
|
+
|
|
3
|
+
A frame that a picture larger than it can be panned and zoomed inside.
|
|
4
|
+
|
|
5
|
+
- Group: Diagrams
|
|
6
|
+
- Import: `import { DiagramCanvas } from '@misoto22/design/diagrams'`
|
|
7
|
+
- Version: 0.8.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/diagram-canvas/
|
|
9
|
+
- Related: diagram-minimap, architecture-figure, scroll-area
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
Any oversized figure — an SVG, an image, a table that will not fold. It knows nothing about nodes, which is what makes it reusable.
|
|
14
|
+
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **Frame** (required) — The outer box: a fixed height — 24rem unless height says otherwise — a hairline, the diagram ground, and overflow hidden. It is the window the artwork is bigger than.
|
|
18
|
+
- **Viewport** (required) — The focusable layer inside it: role="group" with a name, tabIndex 0, the drag handlers, the key handler and a focus ring drawn inside the frame. This is the tab stop, and it is what makes the keys pressable at all.
|
|
19
|
+
- **Stage** (required) — The wrapper the translate and scale are applied to. The transform is on the wrapper and never on the child, so the figure inside keeps its own coordinate space and every measurement taken inside it stays true.
|
|
20
|
+
- **Zoom controls** — The cluster pinned to the bottom corner: zoom out, the current percentage — which is also the reset button, named for what it does — and zoom in. controls={false} removes the cluster and leaves the keys.
|
|
21
|
+
- **Keyboard hint** (required) — A visually hidden paragraph, referenced by aria-describedby, saying that the frame drags and which keys pan, zoom and reset. Nothing on screen carries that sentence.
|
|
22
|
+
|
|
23
|
+
## Best practices
|
|
24
|
+
|
|
25
|
+
### Do
|
|
26
|
+
|
|
27
|
+
- Name it. label is the group’s accessible name and it defaults to "Diagram canvas", so two canvases on one page announce the same thing until each is given its own.
|
|
28
|
+
- Strip the figure inside to its artwork with heading={false}, legend="hidden" and cards={false}. Everything in the frame pans and zooms together, so a title left on travels away from the diagram it names and a key leaves the frame at exactly the zoom that made a reader want it.
|
|
29
|
+
- Move the view through the ref — zoomIn, zoomOut, reset, centerOn — rather than re-rendering the child at a new size. centerOn takes a point in the content’s own coordinates, which is what a minimap reports back.
|
|
30
|
+
- Hand onViewChange straight to a minimap. Each view carries the frame it was measured against as well as the scale and the offset, and that pair is the whole of the arithmetic a viewport rectangle is — the frame being the one number nothing outside the canvas can measure.
|
|
31
|
+
|
|
32
|
+
### Don’t
|
|
33
|
+
|
|
34
|
+
- Nothing clamps the pan. The offset is whatever the drag or the arrow keys left it at, so the artwork can be pushed entirely outside the frame; 0 and the reset button are the whole way back, and controls={false} without a replacement takes the pointer’s half of that away.
|
|
35
|
+
- The scale stops at 0.35. A figure more than about three times the frame cannot be zoomed out far enough to be seen whole, so the frame has to be sized for the diagram — a minimap answers where you are, never what is there.
|
|
36
|
+
- The wheel is left alone and the thumb is not: the frame sets touch-action to none, so a finger dragged inside it pans the diagram and never scrolls the page. A full-width canvas in an article is a band a touch reader has to swipe around rather than through, which is the argument for giving it a height short enough to leave page beside it.
|
|
37
|
+
|
|
38
|
+
## Accessibility
|
|
39
|
+
|
|
40
|
+
- The frame is a real tab stop, so the keyboard controls can be pressed at all.
|
|
41
|
+
- A plain wheel scrolls the page. Zoom needs the platform modifier, so the canvas is never a scroll trap in the middle of an article.
|
|
42
|
+
|
|
43
|
+
## Keyboard
|
|
44
|
+
|
|
45
|
+
- + / = — Zooms in about the centre of the frame.
|
|
46
|
+
- - — Zooms out.
|
|
47
|
+
- 0 — Resets the scale and the offset together.
|
|
48
|
+
- ← / → / ↑ / ↓ — Pans. Shift pans further per press.
|
|
49
|
+
|
|
50
|
+
## DiagramCanvas
|
|
51
|
+
|
|
52
|
+
A frame that a picture larger than it can be moved around inside. Pan with a drag, zoom with the controls or with ⌘/Ctrl and the wheel, and reset with a key. That is the whole of it — this is deliberately a VIEWPORT and not a diagram editor: nothing here knows what a node is, so it works for any oversized figure, an SVG, an image, a table that will not fold. Three decisions here are not obvious. **A plain wheel scrolls the page, not the diagram.** A canvas that swallows the wheel is a scroll trap: a reader flicking down an article hits the figure and the page stops moving for no reason they can see. Zooming needs the modifier — which is also the platform gesture for zoom everywhere else, and is what a trackpad pinch already sends. **The transform is on a wrapper, not on the content.** The child keeps its own coordinate space, so a figure inside can still be measured, exported and read by anything that walks it. Scaling the child directly would make every `getBoundingClientRect` inside it a lie. **Keyboard first, and the frame is a real tab stop.** `+` / `-` / `0` and the arrow keys move the view; the frame takes focus so they can be pressed at all. A canvas that only answers a drag is a canvas half the readers cannot operate.
|
|
53
|
+
|
|
54
|
+
### Props
|
|
55
|
+
|
|
56
|
+
- `children` (required) — `ReactNode`.
|
|
57
|
+
- `className` — `string`.
|
|
58
|
+
- `height` — `string` default `'24rem'`. How tall the frame is. Anything CSS accepts.
|
|
59
|
+
- `onViewChange` — `(view: CanvasView) => void`. Told about every view change, for a minimap or a percentage readout.
|
|
60
|
+
- `controls` — `boolean` default `true`. Hides the built-in zoom controls, for a caller supplying its own.
|
|
61
|
+
- `label` — `string` default `'Diagram canvas'`. Names the region for assistive tech.
|
|
62
|
+
- `ref` — `Ref<DiagramCanvasHandle>`.
|
|
63
|
+
|
|
64
|
+
## Examples
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
<DiagramCanvas height="26rem" label="Request path">
|
|
68
|
+
<ArchitectureFigure spec={spec} heading={false} legend="hidden" cards={false} />
|
|
69
|
+
</DiagramCanvas>
|
|
70
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# DiagramExportMenu
|
|
2
|
+
|
|
3
|
+
Taking the figure off the page: PNG, JPEG, WebP, SVG and a 1200×630 share card.
|
|
4
|
+
|
|
5
|
+
- Group: Diagrams
|
|
6
|
+
- Import: `import { DiagramExportMenu } from '@misoto22/design/diagrams'`
|
|
7
|
+
- Version: 0.8.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/diagram-export-menu/
|
|
9
|
+
- Related: dropdown-menu, diagram-toolbar
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
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.
|
|
14
|
+
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **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.
|
|
18
|
+
- **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".
|
|
19
|
+
- **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.
|
|
20
|
+
- **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.
|
|
21
|
+
- **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.
|
|
22
|
+
- **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.
|
|
23
|
+
|
|
24
|
+
## Best practices
|
|
25
|
+
|
|
26
|
+
### Do
|
|
27
|
+
|
|
28
|
+
- 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.
|
|
29
|
+
- 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.
|
|
30
|
+
- 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.
|
|
31
|
+
- 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.
|
|
32
|
+
- 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.
|
|
33
|
+
|
|
34
|
+
### Don’t
|
|
35
|
+
|
|
36
|
+
- 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.
|
|
37
|
+
- 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.
|
|
38
|
+
- 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.
|
|
39
|
+
|
|
40
|
+
## Accessibility
|
|
41
|
+
|
|
42
|
+
- A failed export is reported through onResult rather than swallowed: a click that quietly does nothing is indistinguishable from a broken button.
|
|
43
|
+
|
|
44
|
+
## DiagramExportMenu
|
|
45
|
+
|
|
46
|
+
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.
|
|
47
|
+
|
|
48
|
+
### Props
|
|
49
|
+
|
|
50
|
+
- `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.
|
|
51
|
+
- `title` (required) — `string`. Names the file, and is printed on the share card.
|
|
52
|
+
- `trigger` — `ReactNode`. Replaces the trigger.
|
|
53
|
+
- `className` — `string`.
|
|
54
|
+
- `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".
|
|
55
|
+
- `onResult` — `(result: ExportResult) => void`. Told what happened, so a page can raise a toast.
|
|
56
|
+
- `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.
|
|
57
|
+
|
|
58
|
+
## exportFigure
|
|
59
|
+
|
|
60
|
+
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.
|
|
61
|
+
|
|
62
|
+
## Types
|
|
63
|
+
|
|
64
|
+
- `ExportFormat` = `'png' | 'jpeg' | 'webp' | 'svg' | 'share-card'`
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# DiagramInspector
|
|
2
|
+
|
|
3
|
+
What the reader just picked, written out beside the picture.
|
|
4
|
+
|
|
5
|
+
- Group: Diagrams
|
|
6
|
+
- Import: `import { DiagramInspector } from '@misoto22/design/diagrams'`
|
|
7
|
+
- Version: 0.8.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/diagram-inspector/
|
|
9
|
+
- Related: card, diagram-canvas
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
A node holds about eight words before it stops being a node. Everything past those — the port, the owner, the six relationships — belongs here.
|
|
14
|
+
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **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.
|
|
18
|
+
- **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.
|
|
19
|
+
- **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.
|
|
20
|
+
- **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.
|
|
21
|
+
- **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.
|
|
22
|
+
- **Actions** — A wrap of caller-supplied buttons under the facts: copy the id, open the source the node was read out of.
|
|
23
|
+
|
|
24
|
+
## Best practices
|
|
25
|
+
|
|
26
|
+
### Do
|
|
27
|
+
|
|
28
|
+
- 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.
|
|
29
|
+
- 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.
|
|
30
|
+
- 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.
|
|
31
|
+
|
|
32
|
+
### Don’t
|
|
33
|
+
|
|
34
|
+
- 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.
|
|
35
|
+
- 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.
|
|
36
|
+
|
|
37
|
+
## Accessibility
|
|
38
|
+
|
|
39
|
+
- 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.
|
|
40
|
+
- Relationships are real buttons when they carry onSelect, which is how the graph becomes walkable peer by peer from the keyboard.
|
|
41
|
+
|
|
42
|
+
## DiagramInspector
|
|
43
|
+
|
|
44
|
+
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.
|
|
45
|
+
|
|
46
|
+
### Props
|
|
47
|
+
|
|
48
|
+
- `eyebrow` — `string`. The kicker over the title — what KIND of thing this panel is showing.
|
|
49
|
+
- `title` (required) — `string`.
|
|
50
|
+
- `description` — `ReactNode`.
|
|
51
|
+
- `facts` — `InspectorFact[]` default `[]`.
|
|
52
|
+
- `links` — `InspectorLink[]` default `[]`.
|
|
53
|
+
- `actions` — `ReactNode`. Buttons under the facts — copy a link, open the source.
|
|
54
|
+
- `onClose` — `() => void`.
|
|
55
|
+
- `className` — `string`.
|
|
56
|
+
- `floating` — `boolean`. Renders as a floating panel over the surface rather than in the flow.
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
<DiagramInspector
|
|
62
|
+
eyebrow="Service"
|
|
63
|
+
title="API Server"
|
|
64
|
+
description="FastAPI, behind the load balancer."
|
|
65
|
+
facts={[
|
|
66
|
+
{ label: 'Port', value: '8000', mono: true },
|
|
67
|
+
{ label: 'Id', value: 'api', mono: true },
|
|
68
|
+
]}
|
|
69
|
+
links={[{ direction: 'out', label: 'SQL', peer: 'PostgreSQL' }]}
|
|
70
|
+
onClose={() => setSelected(null)}
|
|
71
|
+
/>
|
|
72
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# DiagramLegend
|
|
2
|
+
|
|
3
|
+
The key: which drawn form means which kind of thing.
|
|
4
|
+
|
|
5
|
+
- Group: Diagrams
|
|
6
|
+
- Import: `import { DiagramLegend } from '@misoto22/design/diagrams'`
|
|
7
|
+
- Version: 0.8.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/diagram-legend/
|
|
9
|
+
- Related: architecture-figure, lifecycle-figure
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
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.
|
|
14
|
+
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **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.
|
|
18
|
+
- **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.
|
|
19
|
+
- **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.
|
|
20
|
+
- **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.
|
|
21
|
+
- **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.
|
|
22
|
+
|
|
23
|
+
## Best practices
|
|
24
|
+
|
|
25
|
+
### Do
|
|
26
|
+
|
|
27
|
+
- 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.
|
|
28
|
+
- 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.
|
|
29
|
+
- 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.
|
|
30
|
+
|
|
31
|
+
### Don’t
|
|
32
|
+
|
|
33
|
+
- 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.
|
|
34
|
+
- 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.
|
|
35
|
+
|
|
36
|
+
## Accessibility
|
|
37
|
+
|
|
38
|
+
- A list of pairs rather than a row of spans, so the count is part of what a screen reader says about it.
|
|
39
|
+
- kindLegend, variantLegend and stateLegend build the standard sets out of the renderers’ own drawing code, so the key can never drift from the figure.
|
|
40
|
+
|
|
41
|
+
## DiagramLegend
|
|
42
|
+
|
|
43
|
+
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.
|
|
44
|
+
|
|
45
|
+
### Props
|
|
46
|
+
|
|
47
|
+
- `entries` (required) — `DiagramLegendEntry[]`.
|
|
48
|
+
- `title` — `string | null` default `'Key'`. The kicker before the row. Pass null for a bare row.
|
|
49
|
+
- `className` — `string`.
|
|
50
|
+
|
|
51
|
+
## Examples
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
<DiagramLegend entries={kindLegend(['backend', 'database'])} />
|
|
55
|
+
```
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# DiagramMinimap
|
|
2
|
+
|
|
3
|
+
Where you are in something bigger than the window.
|
|
4
|
+
|
|
5
|
+
- Group: Diagrams
|
|
6
|
+
- Import: `import { DiagramMinimap } from '@misoto22/design/diagrams'`
|
|
7
|
+
- Version: 0.8.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/diagram-minimap/
|
|
9
|
+
- Related: diagram-canvas
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
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.
|
|
14
|
+
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **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.
|
|
18
|
+
- **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.
|
|
19
|
+
- **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.
|
|
20
|
+
- **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.
|
|
21
|
+
|
|
22
|
+
## Best practices
|
|
23
|
+
|
|
24
|
+
### Do
|
|
25
|
+
|
|
26
|
+
- 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.
|
|
27
|
+
- 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.
|
|
28
|
+
- 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.
|
|
29
|
+
- 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.
|
|
30
|
+
|
|
31
|
+
### Don’t
|
|
32
|
+
|
|
33
|
+
- 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.
|
|
34
|
+
- 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.
|
|
35
|
+
|
|
36
|
+
## Accessibility
|
|
37
|
+
|
|
38
|
+
- 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.
|
|
39
|
+
|
|
40
|
+
## DiagramMinimap
|
|
41
|
+
|
|
42
|
+
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.
|
|
43
|
+
|
|
44
|
+
### Props
|
|
45
|
+
|
|
46
|
+
- `content` (required) — `{ width: number; height: number }`. The whole artwork, at its natural size in CSS pixels.
|
|
47
|
+
- `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.
|
|
48
|
+
- `view` (required) — `CanvasView`. Where that frame currently sits — a `DiagramCanvas`'s `onViewChange`.
|
|
49
|
+
- `children` — `ReactNode`. A miniature of the artwork. Usually the same figure, rendered again.
|
|
50
|
+
- `onSeek` — `(x: number, y: number) => void`. Called with a point in CONTENT coordinates when the reader picks one.
|
|
51
|
+
- `width` — `number` default `200`. How wide the map is, in CSS pixels. Height follows the aspect ratio.
|
|
52
|
+
- `className` — `string`.
|
|
53
|
+
- `label` — `string` default `'Diagram overview'`.
|
|
54
|
+
|
|
55
|
+
## Examples
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
const canvas = useRef<DiagramCanvasHandle>(null)
|
|
59
|
+
const [view, setView] = useState({ scale: 1, x: 0, y: 0 })
|
|
60
|
+
// …
|
|
61
|
+
<DiagramMinimap
|
|
62
|
+
content={{ width: 1400, height: 620 }}
|
|
63
|
+
view={view}
|
|
64
|
+
onSeek={(x, y) => canvas.current?.centerOn(x, y)}
|
|
65
|
+
>
|
|
66
|
+
<ArchitectureFigure spec={spec} heading={false} legend="hidden" cards={false} />
|
|
67
|
+
</DiagramMinimap>
|
|
68
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# DiagramToolbar
|
|
2
|
+
|
|
3
|
+
A bar of actions belonging to the surface underneath them.
|
|
4
|
+
|
|
5
|
+
- Group: Diagrams
|
|
6
|
+
- Import: `import { DiagramToolbar } from '@misoto22/design/diagrams'`
|
|
7
|
+
- Version: 0.8.0
|
|
8
|
+
- Docs: https://ui.misoto22.com/components/diagram-toolbar/
|
|
9
|
+
- Related: floating-icon-button, diagram-export-menu
|
|
10
|
+
|
|
11
|
+
## When to reach for it
|
|
12
|
+
|
|
13
|
+
FloatingIconButton is one pinned action. This is the container for several, so they read as one object rather than as a scatter.
|
|
14
|
+
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- **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.
|
|
18
|
+
- **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.
|
|
19
|
+
- **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.
|
|
20
|
+
- **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.
|
|
21
|
+
- **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.
|
|
22
|
+
|
|
23
|
+
## Best practices
|
|
24
|
+
|
|
25
|
+
### Do
|
|
26
|
+
|
|
27
|
+
- 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.
|
|
28
|
+
- 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.
|
|
29
|
+
- 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.
|
|
30
|
+
|
|
31
|
+
### Don’t
|
|
32
|
+
|
|
33
|
+
- 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.
|
|
34
|
+
- 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.
|
|
35
|
+
- 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.
|
|
36
|
+
|
|
37
|
+
## Accessibility
|
|
38
|
+
|
|
39
|
+
- 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.
|
|
40
|
+
|
|
41
|
+
## DiagramToolbar
|
|
42
|
+
|
|
43
|
+
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.
|
|
44
|
+
|
|
45
|
+
### Props
|
|
46
|
+
|
|
47
|
+
- `children` (required) — `ReactNode`.
|
|
48
|
+
- `placement` — `'inline' | 'floating'` default `'inline'`. Where it sits. `floating` pins it over the surface it acts on.
|
|
49
|
+
- `align` — `'start' | 'end'` default `'end'`. Which corner a floating bar pins to.
|
|
50
|
+
- `label` (required) — `string`.
|
|
51
|
+
|
|
52
|
+
Also accepts: `Omit<ComponentProps<'div'>, 'children'>`.
|
|
53
|
+
|
|
54
|
+
## DiagramToolbarGroup
|
|
55
|
+
|
|
56
|
+
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.
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
<DiagramToolbar label="Diagram actions" placement="floating">
|
|
62
|
+
<DiagramToolbarGroup>
|
|
63
|
+
<Button size="sm" variant="ghost">Theme</Button>
|
|
64
|
+
</DiagramToolbarGroup>
|
|
65
|
+
<DiagramToolbarGroup>
|
|
66
|
+
<DiagramExportMenu targetRef={svg} title="Request path" />
|
|
67
|
+
</DiagramToolbarGroup>
|
|
68
|
+
</DiagramToolbar>
|
|
69
|
+
```
|
package/dist/agent/Dialog.md
CHANGED
|
@@ -4,10 +4,33 @@ A modal surface: portal, scrim, centred panel.
|
|
|
4
4
|
|
|
5
5
|
- Group: Overlays
|
|
6
6
|
- Import: `import { Dialog } from '@misoto22/design'`
|
|
7
|
-
- Version: 0.
|
|
7
|
+
- Version: 0.8.0
|
|
8
8
|
- Docs: https://ui.misoto22.com/components/dialog/
|
|
9
9
|
- Related: dropdown-menu, tooltip
|
|
10
10
|
|
|
11
|
+
## Anatomy
|
|
12
|
+
|
|
13
|
+
- **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.
|
|
14
|
+
- **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.
|
|
15
|
+
- **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.
|
|
16
|
+
- **Description** — description, a quiet line under the title. It shares one wrapper with the title, so hideTitle hides both.
|
|
17
|
+
- **Close** — The 36px X in the top-end corner, rendered while showClose is true (the default) and carrying its own aria-label of “Close”.
|
|
18
|
+
|
|
19
|
+
## Best practices
|
|
20
|
+
|
|
21
|
+
### Do
|
|
22
|
+
|
|
23
|
+
- 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.
|
|
24
|
+
- 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.
|
|
25
|
+
- 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.
|
|
26
|
+
- 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.
|
|
27
|
+
|
|
28
|
+
### Don’t
|
|
29
|
+
|
|
30
|
+
- 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.
|
|
31
|
+
- 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.
|
|
32
|
+
- 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.
|
|
33
|
+
|
|
11
34
|
## Accessibility
|
|
12
35
|
|
|
13
36
|
- Radix owns the focus trap, Escape, the scroll lock and aria-modal.
|
|
@@ -28,11 +51,11 @@ Radix Dialog root + trigger + close, re-exported as typed passthroughs.
|
|
|
28
51
|
|
|
29
52
|
## DialogContent
|
|
30
53
|
|
|
31
|
-
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
|
|
54
|
+
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.
|
|
32
55
|
|
|
33
56
|
### Props
|
|
34
57
|
|
|
35
|
-
- `title` — `ReactNode`. Heading text.
|
|
58
|
+
- `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.
|
|
36
59
|
- `description` — `ReactNode`. Sub-heading under the title.
|
|
37
60
|
- `className` — `string`.
|
|
38
61
|
- `showClose` — `boolean` default `true`. Show the top-right close control (default true).
|