@mittwald/flow-react-components 0.2.0-alpha.921 → 0.2.0-alpha.926
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 +39 -0
- package/CHANGELOG.md +26 -0
- package/PATTERNS.md +893 -0
- package/dist/assets/doc-properties.json +3936 -3835
- package/dist/css/all-layered.css +1 -1
- package/dist/css/all.css +1 -1
- package/dist/js/_virtual/_.locale.json@8d5024994f97657f895a4e2a188d2d8a.mjs +2 -0
- package/dist/js/_virtual/_.locale.json@8d5024994f97657f895a4e2a188d2d8a.mjs.map +1 -1
- package/dist/js/packages/components/src/components/AccentBox/AccentBox.mjs +2 -2
- package/dist/js/packages/components/src/components/AccentBox/AccentBox.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Accordion/Accordion.mjs +2 -2
- package/dist/js/packages/components/src/components/Accordion/Accordion.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Action/models/ActionStateContext.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ActionGroup/ActionGroup.mjs +32 -4
- package/dist/js/packages/components/src/components/ActionGroup/ActionGroup.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ActionGroup/ActionGroup.module.scss.mjs +8 -6
- package/dist/js/packages/components/src/components/ActionGroup/ActionGroup.module.scss.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Alert/Alert.mjs +2 -3
- package/dist/js/packages/components/src/components/Alert/Alert.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Avatar/Avatar.mjs +2 -2
- package/dist/js/packages/components/src/components/Avatar/Avatar.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Breadcrumb/components/BreadcrumbItem/BreadcrumbItem.mjs +1 -1
- package/dist/js/packages/components/src/components/Breadcrumb/components/BreadcrumbItem/BreadcrumbItem.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Button/Button.mjs +2 -2
- package/dist/js/packages/components/src/components/Button/Button.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Calendar/Calendar.mjs +0 -1
- package/dist/js/packages/components/src/components/Calendar/Calendar.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Calendar/components/CalendarHeader/CalendarHeader.mjs +1 -1
- package/dist/js/packages/components/src/components/Calendar/components/CalendarHeader/CalendarHeader.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Calendar/components/RangeCalendar/RangeCalendar.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/CartesianChart.mjs +2 -2
- package/dist/js/packages/components/src/components/CartesianChart/CartesianChart.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/components/Area/Area.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/components/ChartTooltip/ChartTooltip.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/components/Line/Line.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/components/XAxis/XAxis.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CartesianChart/components/YAxis/YAxis.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CounterBadge/CounterBadge.mjs +0 -1
- package/dist/js/packages/components/src/components/CounterBadge/CounterBadge.mjs.map +1 -1
- package/dist/js/packages/components/src/components/DateRangePicker/DateRangePicker.mjs +1 -1
- package/dist/js/packages/components/src/components/DateRangePicker/components/DateRangeInput/DateRangeInput.mjs +1 -1
- package/dist/js/packages/components/src/components/DateRangePicker/components/DateRangeInput/DateRangeInput.mjs.map +1 -1
- package/dist/js/packages/components/src/components/DonutChart/components/DonutChartLegend.mjs.map +1 -1
- package/dist/js/packages/components/src/components/DonutChart/components/DonutChartValue.mjs.map +1 -1
- package/dist/js/packages/components/src/components/EmulatedBoldText/EmulatedBoldText.mjs +0 -1
- package/dist/js/packages/components/src/components/EmulatedBoldText/EmulatedBoldText.mjs.map +1 -1
- package/dist/js/packages/components/src/components/FileCard/components/DeleteButton/DeleteButton.mjs +1 -1
- package/dist/js/packages/components/src/components/FileCard/components/DeleteButton/DeleteButton.mjs.map +1 -1
- package/dist/js/packages/components/src/components/FileCard/components/FileSizeText/FileSizeText.mjs +0 -1
- package/dist/js/packages/components/src/components/FileCard/components/FileSizeText/FileSizeText.mjs.map +1 -1
- package/dist/js/packages/components/src/components/FileField/FileField.mjs +1 -1
- package/dist/js/packages/components/src/components/FileField/FileField.mjs.map +1 -1
- package/dist/js/packages/components/src/components/FileField/FileField.module.scss.mjs +3 -3
- package/dist/js/packages/components/src/components/FileField/components/FileInput.mjs +2 -1
- package/dist/js/packages/components/src/components/FileField/components/FileInput.mjs.map +1 -1
- package/dist/js/packages/components/src/components/FileField/components/FileInput.module.scss.mjs +4 -2
- package/dist/js/packages/components/src/components/FileField/components/FileInput.module.scss.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Icon/Icon.mjs +2 -2
- package/dist/js/packages/components/src/components/Icon/Icon.mjs.map +1 -1
- package/dist/js/packages/components/src/components/IllustratedMessage/IllustratedMessage.mjs +3 -2
- package/dist/js/packages/components/src/components/IllustratedMessage/IllustratedMessage.mjs.map +1 -1
- package/dist/js/packages/components/src/components/InlineCode/InlineCode.mjs +2 -2
- package/dist/js/packages/components/src/components/InlineCode/InlineCode.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Kbd/Kbd.mjs +2 -2
- package/dist/js/packages/components/src/components/Kbd/Kbd.mjs.map +1 -1
- package/dist/js/packages/components/src/components/LightBox/LightBox.mjs +2 -0
- package/dist/js/packages/components/src/components/LightBox/LightBox.mjs.map +1 -1
- package/dist/js/packages/components/src/components/LightBox/components/LightBoxGalleryItem/LightBoxGalleryItem.mjs +1 -0
- package/dist/js/packages/components/src/components/LightBox/components/LightBoxGalleryItem/LightBoxGalleryItem.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Link/components/LinkIcon/LinkIcon.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/List.mjs +1 -0
- package/dist/js/packages/components/src/components/List/List.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Footer/Footer.mjs +17 -2
- package/dist/js/packages/components/src/components/List/components/Footer/Footer.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Footer/components/PaginationInfos/PaginationInfos.mjs +3 -1
- package/dist/js/packages/components/src/components/List/components/Footer/components/PaginationInfos/PaginationInfos.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Footer/components/ShowNextBatchButton/ShowNextBatchButton.mjs +0 -1
- package/dist/js/packages/components/src/components/List/components/Footer/components/ShowNextBatchButton/ShowNextBatchButton.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Header/Header.mjs +2 -2
- package/dist/js/packages/components/src/components/List/components/Header/Header.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Header/Header.module.css.mjs +2 -2
- package/dist/js/packages/components/src/components/List/components/Header/components/AllFiltersModal/FilterAccordion.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Header/components/AllFiltersModal/FilterAccordionCheckboxGroup.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Header/components/AllFiltersModal/FilterAccordionDateRange.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Header/components/AllFiltersModal/FilterAccordionRadioGroup.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Header/components/AllFiltersModal/SortingAccordion.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Header/components/SortingContextMenu/SortingMenuItem.mjs +1 -1
- package/dist/js/packages/components/src/components/List/components/Header/components/SortingContextMenu/SortingMenuItem.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Items/Items.mjs +17 -1
- package/dist/js/packages/components/src/components/List/components/Items/Items.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Items/components/Item/Item.mjs +5 -2
- package/dist/js/packages/components/src/components/List/components/Items/components/Item/Item.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Items/hooks/useInfiniteScrollTrigger.mjs +41 -0
- package/dist/js/packages/components/src/components/List/components/Items/hooks/useInfiniteScrollTrigger.mjs.map +1 -0
- package/dist/js/packages/components/src/components/List/components/ListSummary/ListSummary.mjs +0 -1
- package/dist/js/packages/components/src/components/List/components/ListSummary/ListSummary.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/model/List.mjs +3 -0
- package/dist/js/packages/components/src/components/List/model/List.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/model/filter/DateRangeFilter.mjs +1 -1
- package/dist/js/packages/components/src/components/List/model/types.mjs.map +1 -1
- package/dist/js/packages/components/src/components/LoadingSpinner/LoadingSpinner.mjs.map +1 -1
- package/dist/js/packages/components/src/components/MarkdownEditor/MarkdownEditor.mjs +2 -2
- package/dist/js/packages/components/src/components/MarkdownEditor/MarkdownEditor.mjs.map +1 -1
- package/dist/js/packages/components/src/components/MarkdownEditor/components/ModeButton.mjs.map +1 -1
- package/dist/js/packages/components/src/components/MarkdownEditor/components/Toolbar.mjs.map +1 -1
- package/dist/js/packages/components/src/components/MarkdownEditor/components/ToolbarButton.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Message/Message.mjs +2 -1
- package/dist/js/packages/components/src/components/Message/Message.mjs.map +1 -1
- package/dist/js/packages/components/src/components/MessageThread/components/MessageSeparator/MessageSeparator.mjs +0 -1
- package/dist/js/packages/components/src/components/MessageThread/components/MessageSeparator/MessageSeparator.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Option/Option.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ValidationResultEntry/ValidationResultEntry.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ProgressBar/ProgressBar.mjs +2 -2
- package/dist/js/packages/components/src/components/ProgressBar/ProgressBar.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ProgressBar/components/ProgressBarBar.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ProgressBar/components/ProgressBarLegend.mjs.map +1 -1
- package/dist/js/packages/components/src/components/ProgressBar/components/ProgressBarValue.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Rating/components/RatingSegment/RatingSegment.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Section/Section.mjs +2 -2
- package/dist/js/packages/components/src/components/Section/Section.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Section/components/SectionHeader/SectionHeader.mjs +14 -0
- package/dist/js/packages/components/src/components/Section/components/SectionHeader/SectionHeader.mjs.map +1 -1
- package/dist/js/packages/components/src/components/SegmentedControl/SegmentedControl.mjs +2 -2
- package/dist/js/packages/components/src/components/SegmentedControl/SegmentedControl.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Separator/Separator.mjs +0 -1
- package/dist/js/packages/components/src/components/Separator/Separator.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Skeleton/Skeleton.mjs +0 -1
- package/dist/js/packages/components/src/components/Skeleton/Skeleton.mjs.map +1 -1
- package/dist/js/packages/components/src/components/SkeletonText/SkeletonText.mjs +0 -1
- package/dist/js/packages/components/src/components/SkeletonText/SkeletonText.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Switch/Switch.mjs +2 -2
- package/dist/js/packages/components/src/components/Switch/Switch.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Table/components/TableBody/TableBody.mjs +0 -1
- package/dist/js/packages/components/src/components/Table/components/TableBody/TableBody.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Table/components/TableColumn/TableColumn.mjs +0 -1
- package/dist/js/packages/components/src/components/Table/components/TableColumn/TableColumn.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Table/components/TableFooterRow/TableFooterRow.mjs +0 -1
- package/dist/js/packages/components/src/components/Table/components/TableFooterRow/TableFooterRow.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Table/components/TableHeader/TableHeader.mjs +0 -1
- package/dist/js/packages/components/src/components/Table/components/TableHeader/TableHeader.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Table/components/TableRow/TableRow.mjs +0 -1
- package/dist/js/packages/components/src/components/Table/components/TableRow/TableRow.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Text/Text.mjs +0 -1
- package/dist/js/packages/components/src/components/Text/Text.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Tooltip/components/TooltipTrigger/TooltipTrigger.mjs +0 -1
- package/dist/js/packages/components/src/components/Tooltip/components/TooltipTrigger/TooltipTrigger.mjs.map +1 -1
- package/dist/js/packages/components/src/components/TranslationProvider/TranslationProvider.mjs.map +1 -1
- package/dist/js/packages/components/src/lib/react/components/Render/Render.mjs +0 -1
- package/dist/js/packages/components/src/lib/react/components/Render/Render.mjs.map +1 -1
- package/dist/js/packages/components/src/lib/viewComponentContext/ViewComponentContextProvider.mjs.map +1 -1
- package/dist/types/components/AccentBox/index.d.ts +1 -1
- package/dist/types/components/AccentBox/index.d.ts.map +1 -1
- package/dist/types/components/Accordion/index.d.ts +1 -1
- package/dist/types/components/Accordion/index.d.ts.map +1 -1
- package/dist/types/components/Accordion/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/ActionGroup/ActionGroup.d.ts +8 -0
- package/dist/types/components/ActionGroup/ActionGroup.d.ts.map +1 -1
- package/dist/types/components/ActionGroup/stories/Default.stories.d.ts +2 -0
- package/dist/types/components/ActionGroup/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Alert/Alert.d.ts.map +1 -1
- package/dist/types/components/Alert/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/AlertBadge/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Align/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Align/stories/InputButton.stories.d.ts.map +1 -1
- package/dist/types/components/Autocomplete/index.d.ts +1 -1
- package/dist/types/components/Autocomplete/index.d.ts.map +1 -1
- package/dist/types/components/Autocomplete/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Avatar/index.d.ts +1 -1
- package/dist/types/components/Avatar/index.d.ts.map +1 -1
- package/dist/types/components/AvatarStack/index.d.ts +1 -1
- package/dist/types/components/AvatarStack/index.d.ts.map +1 -1
- package/dist/types/components/AvatarStack/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/BigNumber/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Breadcrumb/components/BreadcrumbItem/BreadcrumbItem.d.ts.map +1 -1
- package/dist/types/components/Breadcrumb/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Button/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Button/stories/lib.d.ts.map +1 -1
- package/dist/types/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/types/components/Calendar/components/CalendarHeader/CalendarHeader.d.ts.map +1 -1
- package/dist/types/components/Calendar/components/RangeCalendar/RangeCalendar.d.ts.map +1 -1
- package/dist/types/components/CartesianChart/CartesianChart.d.ts +6 -6
- package/dist/types/components/CartesianChart/CartesianChart.d.ts.map +1 -1
- package/dist/types/components/CartesianChart/components/ChartTooltip/ChartTooltip.d.ts.map +1 -1
- package/dist/types/components/Chat/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Checkbox/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/CheckboxButton/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/CheckboxGroup/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/CodeBlock/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/CodeEditor/index.d.ts +1 -1
- package/dist/types/components/CodeEditor/index.d.ts.map +1 -1
- package/dist/types/components/CodeEditor/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Color/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/ColumnLayout/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/ComboBox/stories/FileComboBox.stories.d.ts.map +1 -1
- package/dist/types/components/Content/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/ContextMenu/stories/EdgeCases.stories.d.ts.map +1 -1
- package/dist/types/components/ContextualHelp/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/CounterBadge/CounterBadge.d.ts +1 -2
- package/dist/types/components/CounterBadge/CounterBadge.d.ts.map +1 -1
- package/dist/types/components/CounterBadge/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/DatePicker/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/DateRangePicker/components/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/types/components/DateRangePicker/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/DonutChart/components/DonutChartLegend.d.ts.map +1 -1
- package/dist/types/components/DonutChart/components/DonutChartValue.d.ts.map +1 -1
- package/dist/types/components/DonutChart/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/EmulatedBoldText/EmulatedBoldText.d.ts.map +1 -1
- package/dist/types/components/EmulatedBoldText/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/FileCard/components/DeleteButton/DeleteButton.d.ts.map +1 -1
- package/dist/types/components/FileCard/components/FileSizeText/FileSizeText.d.ts.map +1 -1
- package/dist/types/components/FileCard/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/FileCardList/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/FileField/index.d.ts +1 -1
- package/dist/types/components/FileField/index.d.ts.map +1 -1
- package/dist/types/components/Flex/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Header/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/HeaderNavigation/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Heading/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Icon/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/IllustratedMessage/IllustratedMessage.d.ts.map +1 -1
- package/dist/types/components/IllustratedMessage/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Image/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Initials/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/InlineCode/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Kbd/Kbd.d.ts +1 -0
- package/dist/types/components/Kbd/Kbd.d.ts.map +1 -1
- package/dist/types/components/Kbd/index.d.ts +2 -1
- package/dist/types/components/Kbd/index.d.ts.map +1 -1
- package/dist/types/components/Kbd/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/LabeledValue/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/LayoutCard/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/LightBox/LightBox.d.ts.map +1 -1
- package/dist/types/components/LightBox/components/LightBoxGalleryItem/LightBoxGalleryItem.d.ts +1 -0
- package/dist/types/components/LightBox/components/LightBoxGalleryItem/LightBoxGalleryItem.d.ts.map +1 -1
- package/dist/types/components/LightBox/components/LightBoxGalleryItem/index.d.ts +1 -0
- package/dist/types/components/LightBox/components/LightBoxGalleryItem/index.d.ts.map +1 -1
- package/dist/types/components/LightBox/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Link/components/LinkIcon/LinkIcon.d.ts.map +1 -1
- package/dist/types/components/Link/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/List/List.d.ts +7 -0
- package/dist/types/components/List/List.d.ts.map +1 -1
- package/dist/types/components/List/components/Footer/Footer.d.ts.map +1 -1
- package/dist/types/components/List/components/Footer/components/PaginationInfos/PaginationInfos.d.ts.map +1 -1
- package/dist/types/components/List/components/Footer/components/ShowNextBatchButton/ShowNextBatchButton.d.ts.map +1 -1
- package/dist/types/components/List/components/Header/components/AllFiltersModal/FilterAccordion.d.ts.map +1 -1
- package/dist/types/components/List/components/Header/components/AllFiltersModal/FilterAccordionCheckboxGroup.d.ts.map +1 -1
- package/dist/types/components/List/components/Header/components/AllFiltersModal/FilterAccordionDateRange.d.ts.map +1 -1
- package/dist/types/components/List/components/Header/components/AllFiltersModal/FilterAccordionRadioGroup.d.ts.map +1 -1
- package/dist/types/components/List/components/Header/components/AllFiltersModal/SortingAccordion.d.ts.map +1 -1
- package/dist/types/components/List/components/Header/components/SortingContextMenu/SortingMenuItem.d.ts.map +1 -1
- package/dist/types/components/List/components/Items/Items.d.ts.map +1 -1
- package/dist/types/components/List/components/Items/components/Item/Item.d.ts +2 -1
- package/dist/types/components/List/components/Items/components/Item/Item.d.ts.map +1 -1
- package/dist/types/components/List/components/Items/hooks/useInfiniteScrollTrigger.d.ts +4 -0
- package/dist/types/components/List/components/Items/hooks/useInfiniteScrollTrigger.d.ts.map +1 -0
- package/dist/types/components/List/components/ListItemView/index.d.ts +1 -1
- package/dist/types/components/List/components/ListItemView/index.d.ts.map +1 -1
- package/dist/types/components/List/components/ListSummary/ListSummary.d.ts +2 -2
- package/dist/types/components/List/components/ListSummary/ListSummary.d.ts.map +1 -1
- package/dist/types/components/List/components/ListSummary/index.d.ts +1 -1
- package/dist/types/components/List/components/ListSummary/index.d.ts.map +1 -1
- package/dist/types/components/List/model/List.d.ts +1 -0
- package/dist/types/components/List/model/List.d.ts.map +1 -1
- package/dist/types/components/List/model/types.d.ts +1 -0
- package/dist/types/components/List/model/types.d.ts.map +1 -1
- package/dist/types/components/List/stories/Default.stories.d.ts +1 -0
- package/dist/types/components/List/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/LoadingSpinner/LoadingSpinner.d.ts.map +1 -1
- package/dist/types/components/LoadingSpinner/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Markdown/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/MarkdownEditor/components/ModeButton.d.ts.map +1 -1
- package/dist/types/components/MarkdownEditor/components/Toolbar.d.ts.map +1 -1
- package/dist/types/components/MarkdownEditor/components/ToolbarButton.d.ts.map +1 -1
- package/dist/types/components/MenuItem/index.d.ts +1 -1
- package/dist/types/components/MenuItem/index.d.ts.map +1 -1
- package/dist/types/components/Message/Message.d.ts.map +1 -1
- package/dist/types/components/MessageThread/components/MessageSeparator/MessageSeparator.d.ts.map +1 -1
- package/dist/types/components/MessageThread/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Modal/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Navigation/components/NavigationGroup/index.d.ts +1 -1
- package/dist/types/components/Navigation/components/NavigationGroup/index.d.ts.map +1 -1
- package/dist/types/components/Navigation/index.d.ts +1 -1
- package/dist/types/components/Navigation/index.d.ts.map +1 -1
- package/dist/types/components/Notification/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/NotificationProvider/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/NumberField/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Option/Option.d.ts +2 -2
- package/dist/types/components/Option/Option.d.ts.map +1 -1
- package/dist/types/components/Option/index.d.ts +1 -1
- package/dist/types/components/Option/index.d.ts.map +1 -1
- package/dist/types/components/Overlay/components/index.d.ts +1 -1
- package/dist/types/components/Overlay/components/index.d.ts.map +1 -1
- package/dist/types/components/PasswordCreationField/components/ValidationResultButton/ValidationResultButton.d.ts.map +1 -1
- package/dist/types/components/Popover/components/PopoverContent/index.d.ts +1 -1
- package/dist/types/components/Popover/components/PopoverContent/index.d.ts.map +1 -1
- package/dist/types/components/Popover/stories/EdgeCases.stories.d.ts.map +1 -1
- package/dist/types/components/ProgressBar/components/ProgressBarBar.d.ts.map +1 -1
- package/dist/types/components/ProgressBar/components/ProgressBarLegend.d.ts.map +1 -1
- package/dist/types/components/ProgressBar/components/ProgressBarValue.d.ts.map +1 -1
- package/dist/types/components/ProgressBar/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/RadioGroup/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Rating/components/RatingSegment/RatingSegment.d.ts.map +1 -1
- package/dist/types/components/SearchField/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Section/components/SectionHeader/SectionHeader.d.ts.map +1 -1
- package/dist/types/components/Section/stories/Default.stories.d.ts +1 -0
- package/dist/types/components/Section/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Section/stories/EdgeCases.stories.d.ts.map +1 -1
- package/dist/types/components/SegmentedControl/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Select/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Select/stories/EdgeCases.stories.d.ts.map +1 -1
- package/dist/types/components/Separator/Separator.d.ts.map +1 -1
- package/dist/types/components/Separator/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/types/components/Skeleton/index.d.ts +1 -1
- package/dist/types/components/Skeleton/index.d.ts.map +1 -1
- package/dist/types/components/Skeleton/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/SkeletonText/SkeletonText.d.ts.map +1 -1
- package/dist/types/components/SkeletonText/index.d.ts +1 -1
- package/dist/types/components/SkeletonText/index.d.ts.map +1 -1
- package/dist/types/components/SkeletonText/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Slider/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Switch/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Table/components/TableBody/TableBody.d.ts.map +1 -1
- package/dist/types/components/Table/components/TableColumn/TableColumn.d.ts.map +1 -1
- package/dist/types/components/Table/components/TableFooterRow/TableFooterRow.d.ts.map +1 -1
- package/dist/types/components/Table/components/TableHeader/TableHeader.d.ts.map +1 -1
- package/dist/types/components/Table/components/TableRow/TableRow.d.ts.map +1 -1
- package/dist/types/components/Table/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Text/Text.d.ts.map +1 -1
- package/dist/types/components/Text/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/TextArea/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/TimeField/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Tooltip/components/TooltipTrigger/TooltipTrigger.d.ts.map +1 -1
- package/dist/types/components/Tooltip/components/TooltipTrigger/index.d.ts +1 -1
- package/dist/types/components/Tooltip/components/TooltipTrigger/index.d.ts.map +1 -1
- package/dist/types/components/Tooltip/index.d.ts +1 -1
- package/dist/types/components/Tooltip/index.d.ts.map +1 -1
- package/dist/types/components/Tooltip/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Tooltip/stories/EdgeCases.stories.d.ts.map +1 -1
- package/dist/types/components/TranslationProvider/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/components/Truncate/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/integrations/react-hook-form/components/Field/stories/Autocomplete.stories.d.ts.map +1 -1
- package/dist/types/lib/childProps/ChildPropsContextProvider.d.ts.map +1 -1
- package/dist/types/lib/dev/StoryBackground.d.ts.map +1 -1
- package/dist/types/lib/react/components/Render/Render.d.ts.map +1 -1
- package/dist/types/lib/viewComponentContext/ViewComponentContextProvider.d.ts.map +1 -1
- package/package.json +6 -6
package/PATTERNS.md
ADDED
|
@@ -0,0 +1,893 @@
|
|
|
1
|
+
# @mittwald/flow-react-components — Pattern Reference
|
|
2
|
+
|
|
3
|
+
A reference catalog of the coding patterns and conventions used in this package,
|
|
4
|
+
each with **when it applies (✓)** and **when it does not (✗ → use instead)**.
|
|
5
|
+
Use it to write a new component that looks native to the package, or to decide
|
|
6
|
+
between two similar approaches.
|
|
7
|
+
|
|
8
|
+
This complements [AGENTS.md](./AGENTS.md) (the authoritative rules) — patterns
|
|
9
|
+
marked `[undocumented]` are observed conventions not spelled out there. Each
|
|
10
|
+
entry cites one canonical `Example:` (path relative to this package); `cf.`
|
|
11
|
+
marks a verified counter-example that clarifies the "✗" branch.
|
|
12
|
+
|
|
13
|
+
Paths and line numbers drift as code changes — treat them as starting points,
|
|
14
|
+
not guarantees. Never edit generated files (`view.ts`, `src/views/`,
|
|
15
|
+
`src/auto-generated/`, `Icon/components/icons/`).
|
|
16
|
+
|
|
17
|
+
> Jump to the [Decision cheat-sheet](#decision-cheat-sheet) for the
|
|
18
|
+
> highest-frequency choices.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 1. Component definition
|
|
23
|
+
|
|
24
|
+
- **Factory registration** — public Flow components via
|
|
25
|
+
`flowComponent("<Name>", impl)`; the registered name matches the component and
|
|
26
|
+
directory. `src/components/Button/Button.tsx:91`
|
|
27
|
+
- ✓ public components needing registry, context, tunnel, or remote behavior.
|
|
28
|
+
- ✗ internal implementation details → plain function/FC
|
|
29
|
+
(`src/components/DonutChart/components/DonutChartFill.tsx:14`).
|
|
30
|
+
- **UI component default** — omit factory options; `"ui"` is the default and
|
|
31
|
+
isolates internals from inherited props contexts.
|
|
32
|
+
`src/lib/componentFactory/flowComponent.tsx:58`
|
|
33
|
+
- ✓ leaf controls and content that must isolate inherited PropsContext.
|
|
34
|
+
- ✗ structural containers or context owners → layout/provider classification.
|
|
35
|
+
- **Layout classification** — `{ type: "layout" }` for transparent
|
|
36
|
+
layout/composition primitives whose descendants stay context-aware.
|
|
37
|
+
`src/components/LayoutCard/LayoutCard.tsx:41`
|
|
38
|
+
- ✓ arranges or wraps descendant UI without isolating contextual props.
|
|
39
|
+
- ✗ leaf UI or context infrastructure → UI/provider.
|
|
40
|
+
- **Provider classification** — `{ type: "provider" }` for trigger/provider
|
|
41
|
+
components.
|
|
42
|
+
`src/components/Popover/components/PopoverTrigger/PopoverTrigger.tsx:22`
|
|
43
|
+
- ✓ primary role is establishing behavior/context around descendants.
|
|
44
|
+
- ✗ visual leaves or structural layout → UI/layout.
|
|
45
|
+
- **Factory memoization** — factory implementations and registered components
|
|
46
|
+
are memoized automatically; components don't add `memo` themselves.
|
|
47
|
+
`src/lib/componentFactory/flowComponent.tsx:60`
|
|
48
|
+
- ✓ factory-registered components.
|
|
49
|
+
- ✗ deliberately outside the factory → manual memo only when profiling
|
|
50
|
+
justifies it.
|
|
51
|
+
- **Ref as a prop** — destructure `ref`, pass to the DOM/Aria primitive; no
|
|
52
|
+
`forwardRef`. `src/components/Button/Button.tsx:104`
|
|
53
|
+
- ✓ exposing the root/Aria element (React 19).
|
|
54
|
+
- ✗ no meaningful public element ref → omit it; never `forwardRef`.
|
|
55
|
+
- **Rest-prop forwarding** — keep `...rest` and forward to the semantic
|
|
56
|
+
root/wrapped primitive. `src/components/Button/Button.tsx:109`
|
|
57
|
+
- ✓ props inherited from the rendered primitive belong on its root.
|
|
58
|
+
- ✗ props consumed by composition or incompatible with the root →
|
|
59
|
+
destructure/translate them.
|
|
60
|
+
- **Defaults in destructuring** — runtime defaults where props are destructured,
|
|
61
|
+
synced with JSDoc `@default`. `src/components/Button/Button.tsx:94`
|
|
62
|
+
- ✓ optional props with a stable default.
|
|
63
|
+
- ✗ controlled values or defaults where absence has distinct semantics →
|
|
64
|
+
preserve `undefined`.
|
|
65
|
+
- **Derived `rootClassName` variable** `[undocumented]` — compute the root class
|
|
66
|
+
expression before JSX rather than inline.
|
|
67
|
+
`src/components/Button/Button.tsx:112`
|
|
68
|
+
- ✓ root styling combines base, variants, state, and consumer classes.
|
|
69
|
+
- ✗ a single invariant class → pass it directly.
|
|
70
|
+
- **Helpers outside the component** `[undocumented]` — hookless pure
|
|
71
|
+
helpers/constants live above the component const.
|
|
72
|
+
`src/components/Button/Button.tsx:45`
|
|
73
|
+
- ✓ pure logic independent of hooks/render state.
|
|
74
|
+
- ✗ needs props/hooks/closures → keep inside or extract a hook.
|
|
75
|
+
- **Remote generation marker** — `/** @flr-generate all */` directly above the
|
|
76
|
+
exported const. `src/components/Button/Button.tsx:90`
|
|
77
|
+
- ✓ public components on the `flr-universal` remote contract.
|
|
78
|
+
- ✗ host-only/internal/non-serializable → omit generation and keep off the
|
|
79
|
+
universal surface.
|
|
80
|
+
- **Conditional structural wrapper (`Wrap`)** `[undocumented]` — optional
|
|
81
|
+
wrapper without duplicating the child subtree.
|
|
82
|
+
`src/components/Button/Button.tsx:187`
|
|
83
|
+
- ✓ existing content needs an optional wrapper.
|
|
84
|
+
- ✗ wrapping every factory instance context-wide → factory-level `wrapWith`.
|
|
85
|
+
- **Factory-level `wrapWith`** — clone a wrapper around the whole registered
|
|
86
|
+
component. `src/lib/componentFactory/flowComponent.tsx:127`
|
|
87
|
+
- ✓ a component type must consistently establish/clear infrastructure.
|
|
88
|
+
- ✗ a wrapper depends on one render's condition → `Wrap` in the body.
|
|
89
|
+
- **Named plus default export** — named const + trailing `export default Name`.
|
|
90
|
+
`src/components/Button/Button.tsx:200`
|
|
91
|
+
- ✓ principal public components (support both conventions).
|
|
92
|
+
- ✗ internal helpers → smallest local export surface.
|
|
93
|
+
- **Plain FC exception** `[undocumented]` — small infra/provider/SSR/structural
|
|
94
|
+
utilities may use `FC`/plain function.
|
|
95
|
+
`src/components/SettingsProvider/SettingsProvider.tsx:21`
|
|
96
|
+
- ✓ internal infra needing none of the factory services.
|
|
97
|
+
- ✗ normal public UI/layout/provider → `flowComponent`.
|
|
98
|
+
|
|
99
|
+
## 2. Props typing
|
|
100
|
+
|
|
101
|
+
- **Public props interface** — exported `<Name>Props` interface.
|
|
102
|
+
`src/components/Button/Button.tsx:17`
|
|
103
|
+
- ✓ a public component owns an extensible named contract.
|
|
104
|
+
- ✗ the contract is chiefly an intersection/transform → type alias.
|
|
105
|
+
- **React Aria inheritance** — extend the wrapped `react-aria-components` props.
|
|
106
|
+
`src/components/Button/Button.tsx:19`
|
|
107
|
+
- ✓ wraps an Aria primitive and preserves its accessible API.
|
|
108
|
+
- ✗ renders a native element w/o Aria analogue → native element props.
|
|
109
|
+
- **Element-typed Flow props** — add `FlowComponentProps<RootElement>` for
|
|
110
|
+
ref/wrapWith/tunnel. `src/components/Button/Button.tsx:20`
|
|
111
|
+
- ✓ consumers may class/slot/tunnel/wrap/ref a specific root element.
|
|
112
|
+
- ✗ no stable public root element → unparameterized helper / narrower
|
|
113
|
+
contract.
|
|
114
|
+
- **Default Flow ref element** `[undocumented]` — omit the generic when the root
|
|
115
|
+
ref is `HTMLDivElement`. `src/components/Badge/Badge.tsx:33`
|
|
116
|
+
- ✓ root uses the helper's default element type.
|
|
117
|
+
- ✗ another root element → provide the actual type.
|
|
118
|
+
- **Children normalization** — `PropsWithChildren`, often `Omit`-ing the Aria
|
|
119
|
+
`children` first. `src/components/FieldError/FieldError.tsx:19`
|
|
120
|
+
- ✓ the inherited `children` type conflicts with plain `ReactNode`
|
|
121
|
+
composition.
|
|
122
|
+
- ✗ render-prop children are intentionally supported → keep the upstream type.
|
|
123
|
+
- **Class-name helper (`PropsWithClassName`)** — for contracts needing
|
|
124
|
+
`className` but not full element props.
|
|
125
|
+
`src/components/Initials/Initials.tsx:12`
|
|
126
|
+
- ✓ needs `className` only.
|
|
127
|
+
- ✗ a factory component already extends `FlowComponentProps` → redundant.
|
|
128
|
+
- **Native element inheritance** `[undocumented]` — non-Aria wrappers extend
|
|
129
|
+
`ComponentProps<"el">`/`HTMLAttributes`.
|
|
130
|
+
`src/components/Navigation/Navigation.tsx:15`
|
|
131
|
+
- ✓ thin semantic HTML wrapper.
|
|
132
|
+
- ✗ an Aria primitive supplies the behavioral contract → inherit its props.
|
|
133
|
+
- **Type alias for composition** `[undocumented]` — use `type` for
|
|
134
|
+
intersection/`Omit`/`Pick`/generic/alias shapes.
|
|
135
|
+
`src/components/FileCardList/FileCardList.tsx:10`
|
|
136
|
+
- ✓ props are chiefly transforms of sibling contracts.
|
|
137
|
+
- ✗ a public component introduces its own extensible fields → interface.
|
|
138
|
+
- **Internal local props (`Props`)** `[undocumented]` — private, unexported
|
|
139
|
+
subcomponent props named `Props`.
|
|
140
|
+
`src/components/DonutChart/components/DonutChartFill.tsx:7`
|
|
141
|
+
- ✓ a private implementation component.
|
|
142
|
+
- ✗ consumer-facing → export `<Name>Props`.
|
|
143
|
+
- **Literal vocabulary from arrays** `[undocumented]` — `as const` array +
|
|
144
|
+
`(typeof x)[number]` union. `src/components/Badge/Badge.tsx:18`
|
|
145
|
+
- ✓ runtime iteration/validation and a compile-time union share one source.
|
|
146
|
+
- ✗ values exist only at type level → literal union.
|
|
147
|
+
- **Generic Aria value types** `[undocumented]` — preserve the wrapped generic
|
|
148
|
+
value type + a sensible default. `src/components/TimeField/TimeField.tsx:12`
|
|
149
|
+
- ✓ the public value/selection type must flow through props/callbacks.
|
|
150
|
+
- ✗ one fixed value type → non-generic contract.
|
|
151
|
+
- **Supported-prop subsets (`Pick`)** `[undocumented]` — expose an unchanged
|
|
152
|
+
subset of a larger API. `src/components/Modal/Modal.tsx:23`
|
|
153
|
+
- ✓ deliberately exposing an unchanged subset.
|
|
154
|
+
- ✗ inherited fields need changed semantics/types → `Omit` + replacements.
|
|
155
|
+
- **Inherited-prop replacement (`Omit`)** `[undocumented]` — retain a prop name
|
|
156
|
+
but change its type/meaning. `src/components/ComboBox/ComboBox.tsx:22`
|
|
157
|
+
- ✓ Flow changes the accepted type/meaning of a wrapped prop.
|
|
158
|
+
- ✗ semantics identical → inherit or `Pick`.
|
|
159
|
+
- **Shared semantic prop helpers** — reuse
|
|
160
|
+
`PropsWithStatus`/`PropsWithElementType`/`AlphaColor`… from
|
|
161
|
+
`src/lib/types/props`. `src/lib/types/props.ts:14`
|
|
162
|
+
- ✓ multiple components share the same public vocabulary.
|
|
163
|
+
- ✗ a concept is component-specific → keep it beside that component.
|
|
164
|
+
- **Polymorphic element helper** `[undocumented]` — `PropsWithElementType` =
|
|
165
|
+
HTML attrs + constrained tag/exotic. `src/lib/types/props.ts:32`
|
|
166
|
+
- ✓ consumers may choose the semantic root with matching native typing.
|
|
167
|
+
- ✗ behavior/a11y needs one fixed element → fixed root.
|
|
168
|
+
- **Internal prop documentation (`@internal`)** — hides exposed-but-internal
|
|
169
|
+
members from generated docs. `src/components/Button/Button.tsx:39`
|
|
170
|
+
- ✓ a technically exposed prop must be hidden from consumer docs.
|
|
171
|
+
- ✗ a consumer should choose it → document normally.
|
|
172
|
+
- **Documented defaults (`@default`)** — in public prop JSDoc, synced with
|
|
173
|
+
runtime. `src/components/Button/Button.tsx:23`
|
|
174
|
+
- ✓ a stable observable default.
|
|
175
|
+
- ✗ meaningful `undefined` or a dynamic/contextual default → describe
|
|
176
|
+
semantics instead.
|
|
177
|
+
- **Remote prop exclusion (`@flr-ignore-props`)** — for
|
|
178
|
+
non-serializable/host-sensitive props.
|
|
179
|
+
`src/components/TunnelEntry/TunnelEntry.tsx:9`
|
|
180
|
+
- ✓ a prop can't safely/meaningfully cross the remote boundary.
|
|
181
|
+
- ✗ serializable + part of the contract → generate it.
|
|
182
|
+
- **Props registry registration** — every `flowComponent` name + props type in
|
|
183
|
+
`FlowComponentPropsTypes`. `src/components/propTypes/index.ts:97`
|
|
184
|
+
- ✓ every factory component.
|
|
185
|
+
- ✗ plain internal FCs → do not register.
|
|
186
|
+
- **Registry-derived component names** `[undocumented]` — derive
|
|
187
|
+
`FlowComponentName`/props from the registry.
|
|
188
|
+
`src/components/propTypes/types.ts:3`
|
|
189
|
+
- ✓ factory/context APIs accept only registered names.
|
|
190
|
+
- ✗ arbitrary DOM/third-party names → type them in their own domain.
|
|
191
|
+
|
|
192
|
+
## 3. PropsContext / composability
|
|
193
|
+
|
|
194
|
+
- **Typed context map** — `const propsContext: PropsContext` keyed by component
|
|
195
|
+
names. `src/components/Button/Button.tsx:140`
|
|
196
|
+
- ✓ a composition supplies defaults/styling to known Flow descendants.
|
|
197
|
+
- ✗ arbitrary DOM/third-party → props or their own context.
|
|
198
|
+
- **Provider around composition slots** — wrap only the descendant region.
|
|
199
|
+
`src/components/Button/Button.tsx:186`
|
|
200
|
+
- ✓ user-supplied descendants must adapt to the parent.
|
|
201
|
+
- ✗ no compositional slot → pass props directly.
|
|
202
|
+
- **Local props win** — context values are contextual defaults; explicit props
|
|
203
|
+
override. `src/lib/hooks/useProps.ts:32`
|
|
204
|
+
- ✓ defaults while preserving explicit consumer intent.
|
|
205
|
+
- ✗ an enforced invariant → render it directly.
|
|
206
|
+
- **Contextual styling** — inject nested components' CSS-module classes via
|
|
207
|
+
context. `src/components/Button/Button.tsx:140`
|
|
208
|
+
- ✓ descendant Flow components need slot-specific classes without cloning.
|
|
209
|
+
- ✗ styling targets ordinary DOM → parent CSS module.
|
|
210
|
+
- **Contextual semantic defaults** `[undocumented]` — context sets icon size,
|
|
211
|
+
heading level, status, etc. `src/components/Button/Button.tsx:141`
|
|
212
|
+
- ✓ a sensible overridable element/level/size/variant.
|
|
213
|
+
- ✗ the value is required for correctness → configure explicitly.
|
|
214
|
+
- **Nested component contexts** — nest keys to configure descendants of a
|
|
215
|
+
composed component. `src/components/Modal/Modal.tsx:107`
|
|
216
|
+
- ✓ a descendant composition must configure components inside itself.
|
|
217
|
+
- ✗ only the immediate descendant changes → flat entry.
|
|
218
|
+
- **Reusable context fragments** `[undocumented]` — extract repeated nested
|
|
219
|
+
structure, spread into entries. `src/components/Modal/Modal.tsx:105`
|
|
220
|
+
- ✓ several branches share an identical policy.
|
|
221
|
+
- ✗ values differ or are used once → inline.
|
|
222
|
+
- **Dynamic contextual props** — `dynamic(localProps => value)`.
|
|
223
|
+
`src/components/Modal/Modal.tsx:131`
|
|
224
|
+
- ✓ a contextual value derives from the descendant's local props.
|
|
225
|
+
- ✗ constant or parent-state-only → static value/closure.
|
|
226
|
+
- **Contextual wrappers** — `wrapWith` inside a context entry wraps every
|
|
227
|
+
matching descendant. `src/components/Modal/Modal.tsx:126`
|
|
228
|
+
- ✓ every matching descendant needs a wrapper.
|
|
229
|
+
- ✗ one explicitly rendered node → wrap it directly.
|
|
230
|
+
- **Targeted context clearing (`ClearPropsContext`)** — for subtrees that must
|
|
231
|
+
not inherit. `src/lib/propsContext/components/ClearPropsContext.tsx:9`
|
|
232
|
+
- ✓ selected descendants must not inherit a parent context while other context
|
|
233
|
+
stays useful.
|
|
234
|
+
- ✗ normal UI isolation → rely on automatic isolation.
|
|
235
|
+
- **Automatic UI isolation** — factory clears inherited context for `"ui"`.
|
|
236
|
+
`src/lib/componentFactory/flowComponent.tsx:94`
|
|
237
|
+
- ✓ UI-classified components.
|
|
238
|
+
- ✗ layout/provider must propagate context → classify accordingly.
|
|
239
|
+
- **Context preservation through factory** `[undocumented]` — re-provides own
|
|
240
|
+
nested context before isolation.
|
|
241
|
+
`src/lib/componentFactory/flowComponent.tsx:88`
|
|
242
|
+
- ✓ layout/provider stay transparent to upstream composability.
|
|
243
|
+
- ✗ UI leaves isolate automatically.
|
|
244
|
+
- **Automatic slot propagation** `[undocumented]` — a string `slot` prop
|
|
245
|
+
installs `SlotContextProvider`.
|
|
246
|
+
`src/lib/componentFactory/flowComponent.tsx:119`
|
|
247
|
+
- ✓ factory components expose `slot` for composition/tunnel routing.
|
|
248
|
+
- ✗ a plain FC → pass any discriminator explicitly.
|
|
249
|
+
- **UI tunnel entry** `[undocumented]` — the `tunnel` prop becomes
|
|
250
|
+
`UiComponentTunnelEntry`. `src/lib/componentFactory/flowComponent.tsx:131`
|
|
251
|
+
- ✓ a UI component may be captured and rendered at a tunnel exit.
|
|
252
|
+
- ✗ ordinary in-place children → render normally.
|
|
253
|
+
- **Tunnel exit in composition slots** `[undocumented]` —
|
|
254
|
+
`UiComponentTunnelExit` at named insertion points.
|
|
255
|
+
`src/components/Select/Select.tsx:98`
|
|
256
|
+
- ✓ a parent owns a named slot whose UI originates deeper in the tree.
|
|
257
|
+
- ✗ simple composition → children/PropsContext.
|
|
258
|
+
- **Tunnel provider around UI/layout** `[undocumented]` — auto tunnel identity
|
|
259
|
+
for `"ui"`/`"layout"`. `src/lib/componentFactory/flowComponent.tsx:80`
|
|
260
|
+
- ✓ factory UI/layout components.
|
|
261
|
+
- ✗ providers/plain FCs without tunnel behavior → don't add manually.
|
|
262
|
+
- **Only remote-capable context targets** — PropsContext keys used for
|
|
263
|
+
composition must have remote counterparts.
|
|
264
|
+
- ✓ generated/remote-capable Flow components.
|
|
265
|
+
- ✗ host-only components → pass props / redesign for views
|
|
266
|
+
(`src/components/Badge/Badge.tsx:13`).
|
|
267
|
+
|
|
268
|
+
## 4. Views / remote
|
|
269
|
+
|
|
270
|
+
- **View imports for universal composition** — in `flr-universal` components
|
|
271
|
+
import from `@/views/*`. `src/components/Modal/Modal.tsx:16`
|
|
272
|
+
- ✓ composing a Flow component that must switch local/remote.
|
|
273
|
+
- ✗ host-only → direct component import.
|
|
274
|
+
- **Host-only direct imports** — `@/components/*` composition.
|
|
275
|
+
`src/components/Badge/Badge.tsx:13`
|
|
276
|
+
- ✓ deliberately host-only / internal host infra.
|
|
277
|
+
- ✗ universal composition → import the view.
|
|
278
|
+
- **Generated view exclusion** — `view.ts`/`src/views/*` are generator output.
|
|
279
|
+
- ✓ consumed and regenerated via tooling.
|
|
280
|
+
- ✗ fixes → edit the source component/generator, never the view.
|
|
281
|
+
- **Remote-safe props contract** — additions over replacement/removal on
|
|
282
|
+
`@flr-generate` props.
|
|
283
|
+
- ✓ generated props are serializable, least-privilege, backward-compatible.
|
|
284
|
+
- ✗ host-only/non-serializable → ignore remotely or stay host-only.
|
|
285
|
+
- **Deprecation warning hook (`useWarnDeprecation`)** — warn on legacy prop
|
|
286
|
+
usage, keep supporting it.
|
|
287
|
+
`src/components/CartesianChart/CartesianChart.tsx:59`
|
|
288
|
+
- ✓ a shipped remote prop/API must keep working while guiding to its
|
|
289
|
+
replacement.
|
|
290
|
+
- ✗ unshipped/internal API → change directly.
|
|
291
|
+
- **Controlled remote adapter** `[undocumented]` — shared hooks bridge
|
|
292
|
+
serialized value/callbacks. `src/lib/remote/useControlledHostValueProps.ts:23`
|
|
293
|
+
- ✓ host and remote sides must synchronize a controlled value/events.
|
|
294
|
+
- ✗ purely local or ordinary controlled props → standard handling.
|
|
295
|
+
- **Remote-safe child text extraction** `[undocumented]` — remote-aware helpers,
|
|
296
|
+
not raw child structure. `src/components/Button/Button.tsx:176`
|
|
297
|
+
- ✓ behavior needs text from possibly-remote children.
|
|
298
|
+
- ✗ guaranteed local strings → ordinary React handling.
|
|
299
|
+
- **Remote isolation distinction** `[undocumented]` — host impls use local+view
|
|
300
|
+
clear wrappers; remote only local.
|
|
301
|
+
`src/lib/componentFactory/flowComponent.tsx:99`
|
|
302
|
+
- ✓ remote render contexts need isolation distinct from local clearing.
|
|
303
|
+
- ✗ host-only rendering → normal factory isolation.
|
|
304
|
+
|
|
305
|
+
## 5. Exports / barrels
|
|
306
|
+
|
|
307
|
+
- **View-first barrel** — generated components export `./view` first.
|
|
308
|
+
`src/components/Button/index.ts:1`
|
|
309
|
+
- ✓ a generated component barrel.
|
|
310
|
+
- ✗ non-generated → omit the view export.
|
|
311
|
+
- **Type-first named export** — `export { type ButtonProps, Button }`.
|
|
312
|
+
`src/components/Button/index.ts:3`
|
|
313
|
+
- ✓ a barrel exposes props + named component.
|
|
314
|
+
- ✗ internal modules → export only what callers need.
|
|
315
|
+
- **Trailing default re-export** — `export { default } from "./Name"`.
|
|
316
|
+
`src/components/Button/index.ts:4`
|
|
317
|
+
- ✓ the principal component (default-import compatibility).
|
|
318
|
+
- ✗ utility-only barrels → no default.
|
|
319
|
+
- **Combined default/named variant** `[undocumented]` — tiny barrels:
|
|
320
|
+
`export { Name, default } from "./Name"`.
|
|
321
|
+
`src/components/BrowserOnly/index.ts:1`
|
|
322
|
+
- ✓ a tiny barrel re-exporting one symbol both ways without types.
|
|
323
|
+
- ✗ components with props/view exports → expanded form.
|
|
324
|
+
- **Manual public surface** — add to `src/components/public.ts` explicitly.
|
|
325
|
+
`src/components/public.ts:18`
|
|
326
|
+
- ✓ intentionally supported from the package root.
|
|
327
|
+
- ✗ internal/experimental → keep out.
|
|
328
|
+
- **Alias-based public exports** `[undocumented]` — surfaces export via
|
|
329
|
+
`@/components/...`. `src/components/public.ts:1`
|
|
330
|
+
- ✓ a compatibility/clearer consumer-facing name.
|
|
331
|
+
- ✗ no conflict/migration → canonical name.
|
|
332
|
+
- **Curated universal surface** — add remote-safe APIs to
|
|
333
|
+
`src/index/flr-universal.ts` separately. `src/index/flr-universal.ts:3`
|
|
334
|
+
- ✓ verified to work local + remote.
|
|
335
|
+
- ✗ merely public → leave out until remote-capable.
|
|
336
|
+
- **Explicit universal type/value pairs** `[undocumented]` — name each
|
|
337
|
+
component + props, no wildcard. `src/index/flr-universal.ts:8`
|
|
338
|
+
- ✓ universal consumers need value + props.
|
|
339
|
+
- ✗ implementation types → don't expose.
|
|
340
|
+
- **Internal surface** — factories/context/helper types via
|
|
341
|
+
`src/index/internal.ts`. `src/index/internal.ts:3`
|
|
342
|
+
- ✓ advanced infra intentionally available but not the ordinary API.
|
|
343
|
+
- ✗ normal components → default public surface.
|
|
344
|
+
- **Subcomponent barrels** `[undocumented]` — composable subcomponents get their
|
|
345
|
+
own `index.ts`.
|
|
346
|
+
- ✓ a reusable/independently imported subcomponent.
|
|
347
|
+
- ✗ a tiny single-use detail → colocated file, no dir barrel
|
|
348
|
+
(`src/components/DonutChart/components/DonutChartFill.tsx:1`).
|
|
349
|
+
- **Separate integration entries** — optional-dep adapters under
|
|
350
|
+
`src/integrations/`. `src/integrations/nextjs/index.ts:1`
|
|
351
|
+
- ✓ brings optional third-party deps or framework-specific behavior.
|
|
352
|
+
- ✗ dependency-free core → normal surface.
|
|
353
|
+
- **Story-only fixture boundary** — `stories/lib.tsx` never imported by
|
|
354
|
+
production code.
|
|
355
|
+
- ✓ helpers solely for constructing stories.
|
|
356
|
+
- ✗ production logic → component/shared library.
|
|
357
|
+
|
|
358
|
+
## 6. Styling
|
|
359
|
+
|
|
360
|
+
- **Colocated CSS module** — `<Name>.module.scss` imported as `styles`.
|
|
361
|
+
`src/components/Button/Button.tsx:2`
|
|
362
|
+
- ✓ a visual component owns scoped styles.
|
|
363
|
+
- ✗ a behavior-only provider/helper → omit.
|
|
364
|
+
- **Lower-camel root class** — root class named after the component.
|
|
365
|
+
`src/components/Button/Button.module.scss:5`
|
|
366
|
+
- ✓ the module's principal root.
|
|
367
|
+
- ✗ nested elements/modifiers → name by role/value.
|
|
368
|
+
- **Semantic modifier classes** — `.solid`, `.primary`, `.isPending`, `.size-s`.
|
|
369
|
+
`src/components/Button/Button.module.scss:76`
|
|
370
|
+
- ✓ a prop/state maps to a reusable semantic variant.
|
|
371
|
+
- ✗ a one-off derived numeric value → CSS custom property/inline.
|
|
372
|
+
- **Consumer class last** — `clsx(root, modifiers…, className)`.
|
|
373
|
+
`src/components/Button/Button.tsx:114`
|
|
374
|
+
- ✓ combines internal + consumer classes on the root.
|
|
375
|
+
- ✗ no public `className` → internal classes only.
|
|
376
|
+
- **Conditional boolean classes** — short-circuit expressions, not ad-hoc
|
|
377
|
+
strings. `src/components/Button/Button.tsx:116`
|
|
378
|
+
- ✓ a boolean state changes styling without structure.
|
|
379
|
+
- ✗ selecting among named variants → variant lookup.
|
|
380
|
+
- **Bracket lookup for hyphenated classes** `[undocumented]` —
|
|
381
|
+
`styles["size-s"]` / `styles[value]`. `src/components/Button/Button.tsx:119`
|
|
382
|
+
- ✓ a generated class key has hyphens or is dynamic.
|
|
383
|
+
- ✗ a valid static identifier → dot notation.
|
|
384
|
+
- **Design-token variables** — global + component-prefixed tokens; no hard-coded
|
|
385
|
+
colors/sizes/radii. `src/components/Button/Button.module.scss:8`
|
|
386
|
+
- ✓ colors/spacing/type/radii/shadow/size.
|
|
387
|
+
- ✗ a structural CSS keyword or genuine calculation → CSS directly.
|
|
388
|
+
- **No invented base values** — compose existing tokens; add component tokens
|
|
389
|
+
only with a design.
|
|
390
|
+
- ✓ values composed from approved tokens.
|
|
391
|
+
- ✗ a missing design decision → ask UX / add an approved component token.
|
|
392
|
+
- **Shared `focus` mixin** — `@use "@/styles/mixins/focus"`.
|
|
393
|
+
`src/components/Button/Button.module.scss:32`
|
|
394
|
+
- ✓ an interactive element needs the system focus ring.
|
|
395
|
+
- ✗ non-interactive → no focus treatment.
|
|
396
|
+
- **Shared `formControl` mixin** — standard field border/color/states.
|
|
397
|
+
`src/components/CodeEditor/CodeEditor.module.scss:1`
|
|
398
|
+
- ✓ a field-like control.
|
|
399
|
+
- ✗ non-form interactive UI → its relevant styling.
|
|
400
|
+
- **Shared `ellipsis` mixin** — single-line truncation.
|
|
401
|
+
`src/components/Badge/Badge.module.scss:2`
|
|
402
|
+
- ✓ single-line truncation with system overflow.
|
|
403
|
+
- ✗ content may wrap / stay fully visible → normal wrapping.
|
|
404
|
+
- **Specialized shared mixins** `[undocumented]` — `menuItem`, `avatarButton`,
|
|
405
|
+
container-breakpoint. `src/components/Navigation/Navigation.module.scss:1`
|
|
406
|
+
- ✓ multiple components repeat a domain pattern.
|
|
407
|
+
- ✗ local to one component → local mixin.
|
|
408
|
+
- **SCSS section comments** — `/* Elements */`, `/* States */`, `/* Size */`,
|
|
409
|
+
`/* Variants */`. `src/components/Button/Button.module.scss:37`
|
|
410
|
+
- ✓ a non-trivial module with distinct sections.
|
|
411
|
+
- ✗ a tiny one-rule module → none.
|
|
412
|
+
- **Local variant mixins** — parameterized mixin for color/variant matrices.
|
|
413
|
+
`src/components/Button/Button.module.scss:132`
|
|
414
|
+
- ✓ several selectors repeat a component-local declaration group.
|
|
415
|
+
- ✗ reused across components → promote to a shared mixin.
|
|
416
|
+
- **Default modifiers via `@extend`** `[undocumented]` — default variant shares
|
|
417
|
+
a full local declaration set. `src/components/Button/Button.module.scss:34`
|
|
418
|
+
- ✓ a default variant intentionally shares another selector's complete set.
|
|
419
|
+
- ✗ only a few overlapping declarations → mixin/explicit.
|
|
420
|
+
- **Low-specificity `:where()`** `[undocumented]` — keep state matching
|
|
421
|
+
overridable. `src/components/Button/Button.module.scss:23`
|
|
422
|
+
- ✓ variants/context styles should easily override state.
|
|
423
|
+
- ✗ specificity intentionally needed to beat an external rule → scoped
|
|
424
|
+
selector.
|
|
425
|
+
- **React Aria data-state styling** `[undocumented]` — `[data-pressed]`,
|
|
426
|
+
`[disabled]`, custom flags. `src/components/Button/Button.module.scss:145`
|
|
427
|
+
- ✓ visual state = a React Aria emitted attribute.
|
|
428
|
+
- ✗ purely app/model state → your own class/data-attr.
|
|
429
|
+
- **Relational `:has()` selectors** `[undocumented]` — structural variants like
|
|
430
|
+
icon-only. `src/components/Button/Button.module.scss:54`
|
|
431
|
+
- ✓ styling genuinely depends on rendered composition.
|
|
432
|
+
- ✗ the condition exists as state/props → apply a class.
|
|
433
|
+
- **Global `:global()` third-party** — target embedded third-party DOM under the
|
|
434
|
+
root. `src/components/CodeEditor/CodeEditor.module.scss:35`
|
|
435
|
+
- ✓ scoped styles must reach third-party widget classes.
|
|
436
|
+
- ✗ Flow-owned elements → module classes/contextual styling.
|
|
437
|
+
- **Global `.flow--…` descendant selectors** `[undocumented]` — coordinate
|
|
438
|
+
independently rendered descendants.
|
|
439
|
+
`src/components/LayoutCard/LayoutCard.module.scss:16`
|
|
440
|
+
- ✓ a layout must style standalone Flow classes unreachable via props/context.
|
|
441
|
+
- ✗ normal composition → PropsContext classes.
|
|
442
|
+
- **Container-query ownership** `[undocumented]` — inline-size container at the
|
|
443
|
+
semantic boundary. `src/components/Section/Section.module.scss:5`
|
|
444
|
+
- ✓ descendants adapt to this component's available space.
|
|
445
|
+
- ✗ viewport-wide adaptation → responsive primitives/media.
|
|
446
|
+
- **Logical CSS properties** `[undocumented]` — `padding-inline`,
|
|
447
|
+
`margin-inline-start`. `src/components/Button/Button.module.scss:13`
|
|
448
|
+
- ✓ direction-safe spacing/border/size.
|
|
449
|
+
- ✗ a genuinely physical effect → physical properties.
|
|
450
|
+
- **`calc()` over tokens** `[undocumented]` — derive geometry from tokens (e.g.
|
|
451
|
+
subtract border). `src/components/Button/Button.module.scss:26`
|
|
452
|
+
- ✓ geometry derives mechanically from approved tokens.
|
|
453
|
+
- ✗ invents a new visual constant → approved component token.
|
|
454
|
+
|
|
455
|
+
## 7. State / behavior
|
|
456
|
+
|
|
457
|
+
- **Overlay controller (`OverlayController` / `useOverlayController`)** —
|
|
458
|
+
coordinated open/close.
|
|
459
|
+
`src/lib/controller/overlay/useOverlayController.ts:10`
|
|
460
|
+
- ✓ multiple participants coordinate imperative overlay behavior.
|
|
461
|
+
- ✗ a single owner → ordinary controlled/uncontrolled state.
|
|
462
|
+
- **Controller prop for imperative coordination** `[undocumented]` — optional
|
|
463
|
+
controller alongside declarative props. `src/components/Modal/Modal.tsx:43`
|
|
464
|
+
- ✓ external actions must coordinate without lifting every event.
|
|
465
|
+
- ✗ normal declarative ownership → controlled state props.
|
|
466
|
+
- **Controlled/uncontrolled state pairs** — preserve Aria
|
|
467
|
+
`value`/`defaultValue`, `isOpen`/`isDefaultOpen`.
|
|
468
|
+
`src/components/Modal/Modal.tsx:23`
|
|
469
|
+
- ✓ consumers may own state or request an initial value.
|
|
470
|
+
- ✗ cross-tree imperative orchestration → controller.
|
|
471
|
+
- **Callback compatibility adapters** `[undocumented]` — call both Flow + legacy
|
|
472
|
+
callback during deprecation. `src/components/Select/Select.tsx:76`
|
|
473
|
+
- ✓ Flow renames/combines upstream callbacks while keeping both contracts.
|
|
474
|
+
- ✗ the upstream callback already matches → forward unchanged.
|
|
475
|
+
- **Object-ref conversion (`useObjectRef`)** — for stable/renamed refs.
|
|
476
|
+
`src/components/Checkbox/Checkbox.tsx:36`
|
|
477
|
+
- ✓ an Aria hook requires an object ref but the public API accepts React's
|
|
478
|
+
form.
|
|
479
|
+
- ✗ downstream accepts the original → pass through.
|
|
480
|
+
- **Behavior hooks beside complex components** `[undocumented]` —
|
|
481
|
+
`<Component>/hooks/`. `src/components/Action/hooks/useActionState.ts:1`
|
|
482
|
+
- ✓ cohesive reusable logic for one component domain.
|
|
483
|
+
- ✗ generic cross-component behavior → `src/lib/hooks`.
|
|
484
|
+
- **Models for stateful domains** `[undocumented]` — `<Component>/models/`.
|
|
485
|
+
`src/components/Action/models/ActionState.ts:1`
|
|
486
|
+
- ✓ state with domain operations/invariants/lifecycle.
|
|
487
|
+
- ✗ simple transient UI state → React state/hooks.
|
|
488
|
+
- **MobX for rich persistent models** `[undocumented]` — `makeAutoObservable`.
|
|
489
|
+
`src/components/SettingsProvider/models/ComponentSettings.ts:14`
|
|
490
|
+
- ✓ long-lived interconnected observable state.
|
|
491
|
+
- ✗ ordinary component-local state → React primitives.
|
|
492
|
+
- **Settings context lookup (`useSettings`)** `[undocumented]` — optionally
|
|
493
|
+
consume the nearest store.
|
|
494
|
+
`src/components/SettingsProvider/SettingsProvider.tsx:19`
|
|
495
|
+
- ✓ a component optionally consumes a settings store.
|
|
496
|
+
- ✗ ordinary input → pass explicitly.
|
|
497
|
+
- **Pluggable settings backend** — constructed from props; localStorage default.
|
|
498
|
+
`src/components/SettingsProvider/SettingsProvider.tsx:23`
|
|
499
|
+
- ✓ persistence must work with localStorage + consumer strategies.
|
|
500
|
+
- ✗ ephemeral session state → in-memory.
|
|
501
|
+
- **Serialized persistence writes** `[undocumented]` — promise-ref chained
|
|
502
|
+
writes. `src/components/SettingsProvider/SettingsProvider.tsx:40`
|
|
503
|
+
- ✓ async writes to the same record must preserve order.
|
|
504
|
+
- ✗ independent idempotent writes → normal async.
|
|
505
|
+
- **Async resource loading** `[undocumented]` — Suspense-compatible, stable
|
|
506
|
+
loader id. `src/components/SettingsProvider/SettingsProvider.tsx:25`
|
|
507
|
+
- ✓ rendering must suspend until settings load + cache.
|
|
508
|
+
- ✗ optional background data → local async state.
|
|
509
|
+
- **Read-only interaction guard** `[undocumented]` — `aria-disabled` +
|
|
510
|
+
`data-readonly`, suppress handlers. `src/components/Button/Button.tsx:183`
|
|
511
|
+
- ✓ keep an element discoverable/focusable while suppressing activation.
|
|
512
|
+
- ✗ native disabling is correct → `disabled`.
|
|
513
|
+
- **Action-state live announcement** `[undocumented]` — pending/success/failure
|
|
514
|
+
via aria-live. `src/components/Button/Button.tsx:130`
|
|
515
|
+
- ✓ transitions need non-visual assistive feedback.
|
|
516
|
+
- ✗ a static visual status already has an accessible name → avoid duplicate.
|
|
517
|
+
|
|
518
|
+
## 8. Forms / accessibility
|
|
519
|
+
|
|
520
|
+
- **Shared field wiring (`useFieldComponent`)** — field context, wrapper props,
|
|
521
|
+
error infra. `src/components/Checkbox/Checkbox.tsx:34`
|
|
522
|
+
- ✓ a form control joins label/description/validation/error composition.
|
|
523
|
+
- ✗ a non-field interactive control → Aria primitive directly.
|
|
524
|
+
- **Generated error description id** — replaces `aria-describedby` while
|
|
525
|
+
invalid. `src/lib/hooks/useFieldComponent.tsx:54`
|
|
526
|
+
- ✓ an error message joins the control relationship.
|
|
527
|
+
- ✗ no error description rendered → omit.
|
|
528
|
+
- **Field label context** — shared form styling + required/disabled semantics.
|
|
529
|
+
`src/lib/hooks/useFieldComponent.tsx:38`
|
|
530
|
+
- ✓ a composed label needs the control relationship + styling.
|
|
531
|
+
- ✗ the primitive owns an inseparable native label → wire directly.
|
|
532
|
+
- **Field description context** — attaches description to the current field.
|
|
533
|
+
`src/lib/hooks/useFieldComponent.tsx:44`
|
|
534
|
+
- ✓ description children auto-attach to the field.
|
|
535
|
+
- ✗ help text unrelated to a control → ordinary text.
|
|
536
|
+
- **Error capture boundary** `[undocumented]` — `FieldErrorCaptureContext` +
|
|
537
|
+
`FieldErrorView`. `src/components/Checkbox/Checkbox.tsx:43`
|
|
538
|
+
- ✓ nested `FieldError` content must associate with the control.
|
|
539
|
+
- ✗ not compositional error children → the primitive's error API.
|
|
540
|
+
- **Semantic root first** — use the native/Aria element that provides the
|
|
541
|
+
behavior. `src/components/Button/Button.tsx:179`
|
|
542
|
+
- ✓ the interactive/landmark root.
|
|
543
|
+
- ✗ styling-only structure → neutral layout primitives around the semantic
|
|
544
|
+
root.
|
|
545
|
+
- **Generated label relationships** `[undocumented]` — `useId` +
|
|
546
|
+
`aria-labelledby`, explicit `aria-label` wins.
|
|
547
|
+
`src/components/Navigation/components/NavigationGroup/NavigationGroup.tsx:63`
|
|
548
|
+
- ✓ separate generated label/content need stable linkage.
|
|
549
|
+
- ✗ visible text already natively associated → no redundant ARIA.
|
|
550
|
+
- **Icon-only accessible names** — localized/caller `aria-label`.
|
|
551
|
+
`src/components/Modal/Modal.tsx:87`
|
|
552
|
+
- ✓ an interactive control has no visible textual name.
|
|
553
|
+
- ✗ visible text already names it → decorative icon.
|
|
554
|
+
- **Decorative visual hiding (`aria-hidden`)** —
|
|
555
|
+
icons/skeletons/separators/duplicated text.
|
|
556
|
+
`src/components/Button/Button.tsx:143`
|
|
557
|
+
- ✓ a visual duplicates text or carries no independent info.
|
|
558
|
+
- ✗ unique meaning → give it an accessible label.
|
|
559
|
+
- **Presentation role for split decorative text** `[undocumented]` — mark
|
|
560
|
+
fragmented visuals presentation. `src/components/Initials/Initials.tsx:38`
|
|
561
|
+
- ✓ fragmented visual text would mislead AT while a complete label exists.
|
|
562
|
+
- ✗ the rendered text is the intended name → normal semantics.
|
|
563
|
+
- **`disabled` vs `aria-disabled` distinction** `[undocumented]`.
|
|
564
|
+
`src/components/Button/Button.tsx:29`
|
|
565
|
+
- ✓ `aria-disabled` when discoverability/focus is intended + manual guard.
|
|
566
|
+
- ✗ remove from interaction/focus → native `disabled`.
|
|
567
|
+
- **Render-prop state consumption** `[undocumented]` — consume Aria state via
|
|
568
|
+
render props. `src/components/Checkbox/Checkbox.tsx:49`
|
|
569
|
+
- ✓ Aria exposes interaction/validation state needed to render descendants.
|
|
570
|
+
- ✗ state only affects CSS + has data-attrs → style those.
|
|
571
|
+
|
|
572
|
+
## 9. Internationalization
|
|
573
|
+
|
|
574
|
+
- **Colocated locale glob import** —
|
|
575
|
+
`import locales from "./locales/*.locale.json"`.
|
|
576
|
+
`src/components/Badge/Badge.tsx:16`
|
|
577
|
+
- ✓ a component owns user-facing/a11y strings.
|
|
578
|
+
- ✗ renders only consumer text → no locale bundle.
|
|
579
|
+
- **Namespaced formatter hook** —
|
|
580
|
+
`useLocalizedStringFormatter(locales, "<Name>")`.
|
|
581
|
+
`src/components/Badge/Badge.tsx:57`
|
|
582
|
+
- ✓ reads its colocated messages under a stable namespace.
|
|
583
|
+
- ✗ shared cross-component copy has an owner → that owner's formatter.
|
|
584
|
+
- **Both base languages** — matching `de-DE` + `en-US`.
|
|
585
|
+
`src/components/Badge/locales/de-DE.locale.json:1`
|
|
586
|
+
- ✓ any new/changed message in German and English.
|
|
587
|
+
- ✗ — except a whole new language, which requires translating every locale
|
|
588
|
+
dir.
|
|
589
|
+
- **Shared parent locale directory** `[undocumented]` — subcomponents import
|
|
590
|
+
`../locales`.
|
|
591
|
+
`src/components/FileCard/components/DeleteButton/DeleteButton.tsx:5`
|
|
592
|
+
- ✓ a subcomponent's strings belong to the parent namespace.
|
|
593
|
+
- ✗ independently public/reusable → own namespace.
|
|
594
|
+
- **Dotted message keys** `[undocumented]` — hierarchical keys, not deep
|
|
595
|
+
nesting. `src/components/PasswordCreationField/locales/en-US.locale.json:9`
|
|
596
|
+
- ✓ related messages need a readable namespace.
|
|
597
|
+
- ✗ one simple message → flat key.
|
|
598
|
+
- **ICU interpolation and `select`** — conditional phrases/categories.
|
|
599
|
+
`src/components/TextField/locales/en-US.locale.json:2`
|
|
600
|
+
- ✓ grammar/copy varies by runtime values.
|
|
601
|
+
- ✗ static message → plain text.
|
|
602
|
+
- **ICU `plural`** — count-based grammar.
|
|
603
|
+
`src/components/PasswordCreationField/locales/en-US.locale.json:12`
|
|
604
|
+
- ✓ wording changes with a count.
|
|
605
|
+
- ✗ a number merely interpolated → simple interpolation.
|
|
606
|
+
- **Localized accessibility strings** — SR-only names from the formatter.
|
|
607
|
+
`src/components/Badge/Badge.tsx:112`
|
|
608
|
+
- ✓ library-authored labels reach assistive technology.
|
|
609
|
+
- ✗ consumers provide the name → accept it as a prop.
|
|
610
|
+
|
|
611
|
+
## 10. Icons
|
|
612
|
+
|
|
613
|
+
- **Generated internal icon components** — import from
|
|
614
|
+
`@/components/Icon/components/icons`. `src/components/Modal/Modal.tsx:14`
|
|
615
|
+
- ✓ production components.
|
|
616
|
+
- ✗ story-only glyph exploration → raw libs there.
|
|
617
|
+
- **Public icon re-export** — publish the generated set.
|
|
618
|
+
`src/components/public.ts:54`
|
|
619
|
+
- ✓ an intentionally supported icon.
|
|
620
|
+
- ✗ an internal glyph → keep out.
|
|
621
|
+
- **Icon wrapper contract (`IconProps`)** — spinners/alert icons reuse it.
|
|
622
|
+
`src/components/LoadingSpinner/LoadingSpinner.tsx:4`
|
|
623
|
+
- ✓ a custom visual icon honoring size/color/a11y.
|
|
624
|
+
- ✗ not an icon / can't honor it → a semantic component.
|
|
625
|
+
- **Contextual icon sizing** — set child icon size via `PropsContext`.
|
|
626
|
+
`src/components/Button/Button.tsx:141`
|
|
627
|
+
- ✓ icons in a composition inherit parent size.
|
|
628
|
+
- ✗ an informative standalone icon → set locally.
|
|
629
|
+
- **Automatic decorative default** — `Icon` self-hides without `aria-label`.
|
|
630
|
+
`src/components/Icon/Icon.tsx:36`
|
|
631
|
+
- ✓ an unlabeled icon is decoration.
|
|
632
|
+
- ✗ conveys unique info → label it.
|
|
633
|
+
- **Explicitly labeled informative icon** — `aria-label` when the icon carries
|
|
634
|
+
info.
|
|
635
|
+
- ✓ the icon alone communicates status/action.
|
|
636
|
+
- ✗ it duplicates visible text → decorative.
|
|
637
|
+
- **State-specific icon selection** `[undocumented]` — pick the icon before JSX,
|
|
638
|
+
single render site. `src/components/Button/Button.tsx:160`
|
|
639
|
+
- ✓ distinct pending/success/failure glyphs.
|
|
640
|
+
- ✗ no icon requirement / a stable icon stays accurate → avoid switching.
|
|
641
|
+
- **Raw icon libraries in icon stories only** `[undocumented]`.
|
|
642
|
+
`src/components/Icon/stories/Default.stories.tsx:3`
|
|
643
|
+
- ✓ icon stories demoing the `Icon` wrapper.
|
|
644
|
+
- ✗ production → generated internal icons.
|
|
645
|
+
|
|
646
|
+
## 11. Testing and stories
|
|
647
|
+
|
|
648
|
+
- **Default story file** — `stories/Default.stories.tsx`.
|
|
649
|
+
`src/components/Button/stories/Default.stories.tsx:1`
|
|
650
|
+
- ✓ every component.
|
|
651
|
+
- ✗ — except non-component utilities and generated code.
|
|
652
|
+
- **Typed Storybook metadata** — `const meta: Meta<typeof Component>`.
|
|
653
|
+
`src/components/Button/stories/Default.stories.tsx:15`
|
|
654
|
+
- ✓ validate metadata/args against the contract.
|
|
655
|
+
- ✗ — except non-Storybook fixtures.
|
|
656
|
+
- **Documentation category title** — e.g. `Actions/Button`.
|
|
657
|
+
`src/components/Button/stories/Default.stories.tsx:16`
|
|
658
|
+
- ✓ matches the docs taxonomy.
|
|
659
|
+
- ✗ internal fixture stories → appropriate internal grouping.
|
|
660
|
+
- **Action handlers in args** — `action("callbackName")`.
|
|
661
|
+
`src/components/Button/stories/Default.stories.tsx:19`
|
|
662
|
+
- ✓ callbacks observable in interactions.
|
|
663
|
+
- ✗ a callback drives essential story state → render/play logic.
|
|
664
|
+
- **Explicit enum controls** `[undocumented]` — inline-radio/select options.
|
|
665
|
+
`src/components/Button/stories/Default.stories.tsx:29`
|
|
666
|
+
- ✓ a finite prop vocabulary.
|
|
667
|
+
- ✗ boolean/numeric/free-form → natural control.
|
|
668
|
+
- **Typed story alias** — `type Story = StoryObj<typeof Component>`.
|
|
669
|
+
`src/components/Button/stories/Default.stories.tsx:70`
|
|
670
|
+
- ✓ repeated story declarations.
|
|
671
|
+
- ✗ no exported stories → none.
|
|
672
|
+
- **Empty canonical default story** `[undocumented]` —
|
|
673
|
+
`export const Default: Story = {}`.
|
|
674
|
+
`src/components/Button/stories/Default.stories.tsx:71`
|
|
675
|
+
- ✓ metadata args/render express the default.
|
|
676
|
+
- ✗ the default needs unique setup → add only that setup.
|
|
677
|
+
- **Variant stories by meaningful composition** —
|
|
678
|
+
icons/states/content/responsive/edge cases.
|
|
679
|
+
`src/components/Button/stories/Default.stories.tsx:73`
|
|
680
|
+
- ✓ a distinct supported use case.
|
|
681
|
+
- ✗ permuting every prop combination → controls.
|
|
682
|
+
- **Per-story `render` override** `[undocumented]`.
|
|
683
|
+
`src/components/Button/stories/Default.stories.tsx:74`
|
|
684
|
+
- ✓ one scenario needs different structure/state.
|
|
685
|
+
- ✗ all stories share structure → render in metadata.
|
|
686
|
+
- **Story environment helper** `[undocumented]` — `StoryBackground`,
|
|
687
|
+
`dummyText`. `src/components/Button/stories/Default.stories.tsx:61`
|
|
688
|
+
- ✓ needs stable layout/dimensions/background/providers.
|
|
689
|
+
- ✗ renders fine in the default canvas → no scaffold.
|
|
690
|
+
- **Story fixture module** — bulky reusable fixtures in `stories/lib.tsx`.
|
|
691
|
+
- ✓ multiple stories share realistic story-only data/components.
|
|
692
|
+
- ✗ production/test logic → source/test helper.
|
|
693
|
+
- **Browser test colocated** — `<Name>.browser.test.tsx`.
|
|
694
|
+
`src/components/TextField/TextField.browser.test.tsx:5`
|
|
695
|
+
- ✓ observable interaction/async/controller/form/controlled behavior.
|
|
696
|
+
- ✗ pure transformations → unit tests.
|
|
697
|
+
- **Browser rendering API** — `vitest-browser-react` + `userEvent`.
|
|
698
|
+
`src/components/TextField/TextField.browser.test.tsx:6`
|
|
699
|
+
- ✓ needs real React rendering + DOM interaction.
|
|
700
|
+
- ✗ pure logic → call directly.
|
|
701
|
+
- **Role-first queries** — `getByRole` + accessible names.
|
|
702
|
+
`src/components/TextField/TextField.browser.test.tsx:7`
|
|
703
|
+
- ✓ an accessible role/name identifies the element.
|
|
704
|
+
- ✗ none exists → fix a11y first, then the narrowest fallback.
|
|
705
|
+
- **User-observable assertions** — displayed values/focus/state/effects.
|
|
706
|
+
`src/components/TextField/TextField.browser.test.tsx:9`
|
|
707
|
+
- ✓ assert what users can observe.
|
|
708
|
+
- ✗ implementation details → don't couple tests to them.
|
|
709
|
+
- **Pure unit test colocation** — `*.test.ts` beside `lib/` helpers.
|
|
710
|
+
`src/components/Initials/lib/getInitialsFromString.test.ts:4`
|
|
711
|
+
- ✓ a pure helper.
|
|
712
|
+
- ✗ DOM behavior → a browser test.
|
|
713
|
+
- **Table-driven unit cases** `[undocumented]` — `test.each`.
|
|
714
|
+
`src/components/Initials/lib/getInitialsFromString.test.ts:9`
|
|
715
|
+
- ✓ many inputs exercise the same rule/assertion shape.
|
|
716
|
+
- ✗ cases need different setup → named tests.
|
|
717
|
+
- **Compile-time contract tests** — `*.test-types.tsx`.
|
|
718
|
+
`src/components/CartesianChart/typedCartesianChart.test-types.tsx:15`
|
|
719
|
+
- ✓ generic/sophisticated public typing.
|
|
720
|
+
- ✗ straightforward non-generic props → ordinary typechecking.
|
|
721
|
+
- **Positive type assertions (`expectTypeOf`)**.
|
|
722
|
+
`src/components/CartesianChart/typedCartesianChart.test-types.tsx:41`
|
|
723
|
+
- ✓ supported inference/assignments are contract.
|
|
724
|
+
- ✗ runtime semantics → runtime test.
|
|
725
|
+
- **Negative type assertions (`@ts-expect-error`)**.
|
|
726
|
+
`src/components/CartesianChart/typedCartesianChart.test-types.tsx:27`
|
|
727
|
+
- ✓ specific invalid usages must fail compilation.
|
|
728
|
+
- ✗ runtime validation → runtime test.
|
|
729
|
+
- **Visual snapshots beside browser tests** `[undocumented]` —
|
|
730
|
+
`__screenshots__/`.
|
|
731
|
+
- ✓ visual regressions materially matter and it renders in browser tests.
|
|
732
|
+
- ✗ pure logic / intentionally unstable visuals → behavioral assertions.
|
|
733
|
+
|
|
734
|
+
## 12. Imports and file conventions
|
|
735
|
+
|
|
736
|
+
- **Absolute alias for package code** — `@/components|lib|styles|views`.
|
|
737
|
+
`src/components/Button/Button.tsx:10`
|
|
738
|
+
- ✓ imports cross component/library boundaries.
|
|
739
|
+
- ✗ colocated within the same anatomy → relative.
|
|
740
|
+
- **Relative imports for colocated files** — own stylesheet/locales/local
|
|
741
|
+
helpers. `src/components/Button/Button.tsx:2`
|
|
742
|
+
- ✓ own stylesheet/locales/nearby module.
|
|
743
|
+
- ✗ reaches another package area/component → alias.
|
|
744
|
+
- **Separate type-only import (`import type`)**.
|
|
745
|
+
`src/components/Button/Button.tsx:1`
|
|
746
|
+
- ✓ a type-only statement.
|
|
747
|
+
- ✗ types + values from the same module → inline `type`.
|
|
748
|
+
- **Inline `type` specifier in mixed imports** `[undocumented]`.
|
|
749
|
+
`src/components/Modal/Modal.tsx:5`
|
|
750
|
+
- ✓ one module supplies values + types.
|
|
751
|
+
- ✗ type-only → `import type`.
|
|
752
|
+
- **Namespace React Aria import (`import * as Aria`)** `[undocumented]`.
|
|
753
|
+
`src/components/Button/Button.tsx:3`
|
|
754
|
+
- ✓ several Aria names / collision avoidance.
|
|
755
|
+
- ✗ one unambiguous symbol → direct import.
|
|
756
|
+
- **PascalCase component directories/files** —
|
|
757
|
+
`src/components/<Name>/<Name>.tsx`.
|
|
758
|
+
- ✓ public/anatomical React components.
|
|
759
|
+
- ✗ hooks/helpers/models/styles/tests → role-specific naming.
|
|
760
|
+
- **One principal component per file** — the registered component in its
|
|
761
|
+
same-named file.
|
|
762
|
+
- ✓ one exported API owner (tiny private helpers OK local).
|
|
763
|
+
- ✗ multiple independently reusable → split.
|
|
764
|
+
- **Subcomponents mirror component anatomy** `[undocumented]`.
|
|
765
|
+
`src/components/Table/components/TableHeader/index.ts:1`
|
|
766
|
+
- ✓ a reusable subcomponent with its own artifacts.
|
|
767
|
+
- ✗ a single-file detail → keep under `components/`
|
|
768
|
+
(`src/components/DonutChart/components/DonutChartFill.tsx:1`).
|
|
769
|
+
- **Behavior folders by role** `[undocumented]` — `components/`, `hooks/`,
|
|
770
|
+
`lib/`, `models/`, `locales/`, `stories/`.
|
|
771
|
+
- ✓ complex component-local code separates concerns.
|
|
772
|
+
- ✗ one/two simple helpers → colocate, no empty taxonomy.
|
|
773
|
+
- **Index as API boundary** — `index.ts` defines the export surface only.
|
|
774
|
+
`src/components/Button/index.ts:3`
|
|
775
|
+
- ✓ external callers import the supported surface.
|
|
776
|
+
- ✗ impl files in the same anatomy → direct relative imports OK.
|
|
777
|
+
- **No generated-file edits** — `view.ts`/`src/views`/generated icons/`dist`.
|
|
778
|
+
- ✓ change via source/generator.
|
|
779
|
+
- ✗ — except the handwritten generator inputs themselves.
|
|
780
|
+
|
|
781
|
+
## 13. Miscellaneous composition and runtime
|
|
782
|
+
|
|
783
|
+
- **Mutable package feature flags** — exported `flags` object + test reset.
|
|
784
|
+
`src/flags.ts:1`
|
|
785
|
+
- ✓ temporary package-wide switches changed at runtime/tests.
|
|
786
|
+
- ✗ integration-specific → the integration's flag.
|
|
787
|
+
- **Integration-local flags** `[undocumented]`.
|
|
788
|
+
`src/integrations/react-hook-form/flags.ts:1`
|
|
789
|
+
- ✓ a switch affecting one optional integration.
|
|
790
|
+
- ✗ core behavior → the package-level flag.
|
|
791
|
+
- **Browser-only mount guard (`useIsMounted`)** — render browser-dependent
|
|
792
|
+
children after mount. `src/components/BrowserOnly/BrowserOnly.tsx:6`
|
|
793
|
+
- ✓ children need a mounted browser (no SSR access).
|
|
794
|
+
- ✗ SSR-safe content → render directly.
|
|
795
|
+
- **Intentional `SuspenseTrigger`** — never-resolving promise activates a
|
|
796
|
+
fallback. `src/components/SuspenseTrigger/SuspenseTrigger.tsx:7`
|
|
797
|
+
- ✓ deliberately suspend for boundary testing/orchestration.
|
|
798
|
+
- ✗ ordinary async → resource/state loading patterns.
|
|
799
|
+
- **Local `Suspense` boundaries for async content** `[undocumented]`.
|
|
800
|
+
`src/components/Modal/Modal.tsx:182`
|
|
801
|
+
- ✓ independently suspending content + a component-specific fallback.
|
|
802
|
+
- ✗ the app coordinates the whole load → let suspension bubble.
|
|
803
|
+
- **Text wrapping for string children** `[undocumented]` — detect raw strings,
|
|
804
|
+
wrap in `Text`. `src/components/Button/Button.tsx:176`
|
|
805
|
+
- ✓ typography is context-driven and children may be raw strings (local +
|
|
806
|
+
remote).
|
|
807
|
+
- ✗ already-structured nodes → preserve them.
|
|
808
|
+
- **Layout primitives over ad-hoc wrappers** `[undocumented]` — `Section`,
|
|
809
|
+
`ColumnLayout`, `Align`, `Flex`, `Content`.
|
|
810
|
+
- ✓ spacing/align/columns/stack expressible via Flow primitives.
|
|
811
|
+
- ✗ a wrapper needed for semantics/third-party/owned styling → the correct
|
|
812
|
+
semantic element.
|
|
813
|
+
- **Context-driven heading hierarchy** `[undocumented]`.
|
|
814
|
+
`src/components/Modal/Modal.tsx:103`
|
|
815
|
+
- ✓ a composition knows the levels for nested headings/sections.
|
|
816
|
+
- ✗ a single fixed heading → set its level explicitly.
|
|
817
|
+
- **Semantic generated ids (`useId`)** `[undocumented]`.
|
|
818
|
+
`src/components/Modal/Modal.tsx:78`
|
|
819
|
+
- ✓ local label/title/content relationships need stable collision-safe ids.
|
|
820
|
+
- ✗ consumers provide the id / no relationship → preserve/omit.
|
|
821
|
+
- **Loading/success/failure as explicit visual states** `[undocumented]`.
|
|
822
|
+
`src/components/Button/Button.tsx:160`
|
|
823
|
+
- ✓ an async action has meaningful pending/terminal feedback.
|
|
824
|
+
- ✗ a synchronous action with no observable lifecycle → normal content.
|
|
825
|
+
- **Status vocabulary reuse (`PropsWithStatus`)** `[undocumented]` —
|
|
826
|
+
`info|success|warning|danger|unavailable`. `src/lib/types/props.ts:4`
|
|
827
|
+
- ✓ expresses an existing cross-component status concept.
|
|
828
|
+
- ✗ a genuinely component-specific state → define locally.
|
|
829
|
+
- **Semantic alpha-color vocabulary (`AlphaColor`)** `[undocumented]`.
|
|
830
|
+
`src/lib/types/props.ts:44`
|
|
831
|
+
- ✓ public color props use the established semantic palette.
|
|
832
|
+
- ✗ a UX-defined specialized palette → component-specific vocabulary.
|
|
833
|
+
- **`Render` helper for conditional values** `[undocumented]`.
|
|
834
|
+
`src/components/public.ts:111`
|
|
835
|
+
- ✓ a declarative child renders a value/function gated by a condition.
|
|
836
|
+
- ✗ inline boolean/ternary JSX is already clear → native JSX.
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
840
|
+
## Notable undocumented conventions
|
|
841
|
+
|
|
842
|
+
The highest-value conventions a newcomer would otherwise miss:
|
|
843
|
+
|
|
844
|
+
- **`PropsContext` is structural, not just styling** — nested entries, `dynamic`
|
|
845
|
+
children, semantic defaults, and contextual `wrapWith` define much of a
|
|
846
|
+
composite's internal API.
|
|
847
|
+
- **The factory supplies hidden infrastructure** — memoization, nested-context
|
|
848
|
+
preservation, slot propagation, UI isolation, and tunnel entry/provider wiring
|
|
849
|
+
are automatic consequences of `flowComponent`.
|
|
850
|
+
- **Raw strings get `Text`-normalized** where typography is context-driven;
|
|
851
|
+
explicit structured content is left intact.
|
|
852
|
+
- **Semantic generated CSS classes are cross-component coordination points** —
|
|
853
|
+
scoped modules still use `:global(.flow--…)` when independently rendered Flow
|
|
854
|
+
descendants must affect layout.
|
|
855
|
+
- **Controllers coexist with declarative props** — overlay-like APIs support
|
|
856
|
+
controlled/uncontrolled props _and_ a controller object.
|
|
857
|
+
- **Complex behavior is split by vocabulary** — `components/` render, `hooks/`
|
|
858
|
+
behavior, `lib/` pure transforms, `models/` durable state.
|
|
859
|
+
- **`SettingsProvider` combines async resources, hierarchical MobX stores, and
|
|
860
|
+
serialized, Suspense-aware writes.**
|
|
861
|
+
- **Story metadata is the canonical default scenario** — the common `Default`
|
|
862
|
+
story is deliberately empty.
|
|
863
|
+
- **CSS leans on modern relational/low-specificity selectors** — `:has`,
|
|
864
|
+
`:where`, logical properties, data attributes, and container boundaries reduce
|
|
865
|
+
runtime styling props.
|
|
866
|
+
- **Universal exports are deliberately explicit** — remote-safe values and their
|
|
867
|
+
types are curated independently of the ordinary public surface.
|
|
868
|
+
|
|
869
|
+
---
|
|
870
|
+
|
|
871
|
+
## Decision cheat-sheet
|
|
872
|
+
|
|
873
|
+
Quick answers to the highest-frequency choices when authoring a component:
|
|
874
|
+
|
|
875
|
+
- **Normal public leaf** → `flowComponent` + UI classification, not a plain FC.
|
|
876
|
+
- **Arranges descendants** → `layout`; **establishes infra/context** →
|
|
877
|
+
`provider`.
|
|
878
|
+
- **Props with owned fields** → `interface`; **props that transform/intersect**
|
|
879
|
+
→ `type` alias.
|
|
880
|
+
- **Internal & single-use** → local `Props`, plain file; no registry/barrel
|
|
881
|
+
prematurely.
|
|
882
|
+
- **Descendants need overridable defaults** → PropsContext — but only if every
|
|
883
|
+
target is remote-capable.
|
|
884
|
+
- **Universal code composing a Flow component** → view import (`@/views/*`);
|
|
885
|
+
direct import only in host-only code.
|
|
886
|
+
- **Consumers own state** → controlled/uncontrolled pairs; **cross-tree
|
|
887
|
+
imperative coordination** → a controller.
|
|
888
|
+
- **Behavior specific to a component** → hook/model/helper beside it; only
|
|
889
|
+
cross-component utilities go to `src/lib`.
|
|
890
|
+
- **Subcomponent with its own reusable API/artifacts** → directory + barrel;
|
|
891
|
+
otherwise one colocated file.
|
|
892
|
+
- **Structure that's only spacing/alignment** → Flow layout primitives; a raw
|
|
893
|
+
wrapper only for semantics or component-owned integration.
|