@arbor-education/design-system.components 0.15.0 → 0.16.1
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/.gather/skills/write-stories/SKILL.md +207 -271
- package/.storybook/preview.ts +5 -0
- package/CHANGELOG.md +23 -0
- package/README.md +8 -0
- package/component-library.md +144 -13
- package/dist/components/articleCard/ArticleCard.stories.d.ts +137 -11
- package/dist/components/articleCard/ArticleCard.stories.d.ts.map +1 -1
- package/dist/components/articleCard/ArticleCard.stories.js +358 -91
- package/dist/components/articleCard/ArticleCard.stories.js.map +1 -1
- package/dist/components/avatar/Avatar.stories.d.ts +6 -6
- package/dist/components/avatar/Avatar.stories.d.ts.map +1 -1
- package/dist/components/avatar/Avatar.stories.js +393 -49
- package/dist/components/avatar/Avatar.stories.js.map +1 -1
- package/dist/components/avatarGroup/AvatarGroup.stories.d.ts +9 -7
- package/dist/components/avatarGroup/AvatarGroup.stories.d.ts.map +1 -1
- package/dist/components/avatarGroup/AvatarGroup.stories.js +688 -65
- package/dist/components/avatarGroup/AvatarGroup.stories.js.map +1 -1
- package/dist/components/banner/Banner.stories.d.ts.map +1 -1
- package/dist/components/banner/Banner.stories.js +7 -3
- package/dist/components/banner/Banner.stories.js.map +1 -1
- package/dist/components/card/Card.stories.d.ts +105 -4
- package/dist/components/card/Card.stories.d.ts.map +1 -1
- package/dist/components/card/Card.stories.js +336 -18
- package/dist/components/card/Card.stories.js.map +1 -1
- package/dist/components/combobox/Combobox.stories.d.ts +134 -21
- package/dist/components/combobox/Combobox.stories.d.ts.map +1 -1
- package/dist/components/combobox/Combobox.stories.js +676 -175
- package/dist/components/combobox/Combobox.stories.js.map +1 -1
- package/dist/components/datePicker/DatePicker.stories.d.ts +119 -27
- package/dist/components/datePicker/DatePicker.stories.d.ts.map +1 -1
- package/dist/components/datePicker/DatePicker.stories.js +575 -47
- package/dist/components/datePicker/DatePicker.stories.js.map +1 -1
- package/dist/components/dateTimePicker/DateTimePicker.stories.d.ts +155 -39
- package/dist/components/dateTimePicker/DateTimePicker.stories.d.ts.map +1 -1
- package/dist/components/dateTimePicker/DateTimePicker.stories.js +674 -103
- package/dist/components/dateTimePicker/DateTimePicker.stories.js.map +1 -1
- package/dist/components/editableText/EditableText.stories.d.ts +53 -12
- package/dist/components/editableText/EditableText.stories.d.ts.map +1 -1
- package/dist/components/editableText/EditableText.stories.js +401 -64
- package/dist/components/editableText/EditableText.stories.js.map +1 -1
- package/dist/components/formField/FormField.d.ts +4 -0
- package/dist/components/formField/FormField.d.ts.map +1 -1
- package/dist/components/formField/FormField.js +2 -1
- package/dist/components/formField/FormField.js.map +1 -1
- package/dist/components/formField/FormField.test.js +5 -0
- package/dist/components/formField/FormField.test.js.map +1 -1
- package/dist/components/formField/fieldset/Fieldset.stories.d.ts +56 -4
- package/dist/components/formField/fieldset/Fieldset.stories.d.ts.map +1 -1
- package/dist/components/formField/fieldset/Fieldset.stories.js +534 -28
- package/dist/components/formField/fieldset/Fieldset.stories.js.map +1 -1
- package/dist/components/formField/inputs/checkbox/CheckboxGroup.d.ts +3 -1
- package/dist/components/formField/inputs/checkbox/CheckboxGroup.d.ts.map +1 -1
- package/dist/components/formField/inputs/checkbox/CheckboxInput.js +1 -1
- package/dist/components/formField/inputs/checkbox/CheckboxInput.js.map +1 -1
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.d.ts +95 -1
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.d.ts.map +1 -1
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.js +386 -9
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.js.map +1 -1
- package/dist/components/formField/inputs/radio/RadioButtonGroup.d.ts +6 -2
- package/dist/components/formField/inputs/radio/RadioButtonGroup.d.ts.map +1 -1
- package/dist/components/formField/inputs/radio/RadioButtonGroup.js.map +1 -1
- package/dist/components/formField/inputs/radio/RadioButtonInput.stories.d.ts.map +1 -1
- package/dist/components/formField/inputs/radio/RadioButtonInput.stories.js +61 -49
- package/dist/components/formField/inputs/radio/RadioButtonInput.stories.js.map +1 -1
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.d.ts +188 -166
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.d.ts.map +1 -1
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.js +821 -160
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.js.map +1 -1
- package/dist/components/formField/inputs/time/TimeInput.stories.d.ts +176 -22
- package/dist/components/formField/inputs/time/TimeInput.stories.d.ts.map +1 -1
- package/dist/components/formField/inputs/time/TimeInput.stories.js +851 -92
- package/dist/components/formField/inputs/time/TimeInput.stories.js.map +1 -1
- package/dist/components/formField/label/Label.stories.d.ts +54 -5
- package/dist/components/formField/label/Label.stories.d.ts.map +1 -1
- package/dist/components/formField/label/Label.stories.js +238 -4
- package/dist/components/formField/label/Label.stories.js.map +1 -1
- package/dist/components/icoText/IcoText.stories.d.ts +32 -6
- package/dist/components/icoText/IcoText.stories.d.ts.map +1 -1
- package/dist/components/icoText/IcoText.stories.js +309 -14
- package/dist/components/icoText/IcoText.stories.js.map +1 -1
- package/dist/components/kpiCard/KPICard.stories.d.ts +100 -2
- package/dist/components/kpiCard/KPICard.stories.d.ts.map +1 -1
- package/dist/components/kpiCard/KPICard.stories.js +354 -10
- package/dist/components/kpiCard/KPICard.stories.js.map +1 -1
- package/dist/components/kvpList/KVPList.stories.d.ts +57 -4
- package/dist/components/kvpList/KVPList.stories.d.ts.map +1 -1
- package/dist/components/kvpList/KVPList.stories.js +403 -10
- package/dist/components/kvpList/KVPList.stories.js.map +1 -1
- package/dist/components/modal/Modal.stories.d.ts +113 -9
- package/dist/components/modal/Modal.stories.d.ts.map +1 -1
- package/dist/components/modal/Modal.stories.js +633 -13
- package/dist/components/modal/Modal.stories.js.map +1 -1
- package/dist/components/modal/modalManager/ModalManager.stories.d.ts +34 -10
- package/dist/components/modal/modalManager/ModalManager.stories.d.ts.map +1 -1
- package/dist/components/modal/modalManager/ModalManager.stories.js +463 -85
- package/dist/components/modal/modalManager/ModalManager.stories.js.map +1 -1
- package/dist/components/pill/Pill.d.ts.map +1 -1
- package/dist/components/pill/Pill.js +1 -1
- package/dist/components/pill/Pill.js.map +1 -1
- package/dist/components/pill/Pill.stories.d.ts.map +1 -1
- package/dist/components/pill/Pill.stories.js +11 -13
- package/dist/components/pill/Pill.stories.js.map +1 -1
- package/dist/components/row/Row.stories.d.ts +1 -2
- package/dist/components/row/Row.stories.d.ts.map +1 -1
- package/dist/components/row/Row.stories.js +360 -50
- package/dist/components/row/Row.stories.js.map +1 -1
- package/dist/components/searchBar/SearchBar.stories.d.ts +52 -4
- package/dist/components/searchBar/SearchBar.stories.d.ts.map +1 -1
- package/dist/components/searchBar/SearchBar.stories.js +428 -36
- package/dist/components/searchBar/SearchBar.stories.js.map +1 -1
- package/dist/components/section/Section.stories.d.ts +11 -41
- package/dist/components/section/Section.stories.d.ts.map +1 -1
- package/dist/components/section/Section.stories.js +494 -56
- package/dist/components/section/Section.stories.js.map +1 -1
- package/dist/components/singleUser/SingleUser.stories.d.ts +5 -4
- package/dist/components/singleUser/SingleUser.stories.d.ts.map +1 -1
- package/dist/components/singleUser/SingleUser.stories.js +303 -31
- package/dist/components/singleUser/SingleUser.stories.js.map +1 -1
- package/dist/components/slideoverManager/SlideoverManager.stories.d.ts +32 -11
- package/dist/components/slideoverManager/SlideoverManager.stories.d.ts.map +1 -1
- package/dist/components/slideoverManager/SlideoverManager.stories.js +380 -84
- package/dist/components/slideoverManager/SlideoverManager.stories.js.map +1 -1
- package/dist/components/table/DSDefaultColDef.d.ts.map +1 -1
- package/dist/components/table/DSDefaultColDef.js +4 -3
- package/dist/components/table/DSDefaultColDef.js.map +1 -1
- package/dist/components/table/Table.d.ts +6 -1
- package/dist/components/table/Table.d.ts.map +1 -1
- package/dist/components/table/Table.js +8 -3
- package/dist/components/table/Table.js.map +1 -1
- package/dist/components/table/Table.stories.d.ts +3 -0
- package/dist/components/table/Table.stories.d.ts.map +1 -1
- package/dist/components/table/Table.stories.js +384 -5
- package/dist/components/table/Table.stories.js.map +1 -1
- package/dist/components/table/Table.test.js +30 -0
- package/dist/components/table/Table.test.js.map +1 -1
- package/dist/components/table/TableFooter.stories.d.ts +49 -0
- package/dist/components/table/TableFooter.stories.d.ts.map +1 -0
- package/dist/components/table/TableFooter.stories.js +137 -0
- package/dist/components/table/TableFooter.stories.js.map +1 -0
- package/dist/components/table/TableHeader.stories.d.ts +93 -0
- package/dist/components/table/TableHeader.stories.d.ts.map +1 -0
- package/dist/components/table/TableHeader.stories.js +176 -0
- package/dist/components/table/TableHeader.stories.js.map +1 -0
- package/dist/components/table/cellEditors/DateCellEditor.stories.d.ts +44 -0
- package/dist/components/table/cellEditors/DateCellEditor.stories.d.ts.map +1 -0
- package/dist/components/table/cellEditors/DateCellEditor.stories.js +186 -0
- package/dist/components/table/cellEditors/DateCellEditor.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.d.ts +40 -0
- package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.js +209 -0
- package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.d.ts +48 -0
- package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.js +244 -0
- package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.d.ts.map +1 -1
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.js +3 -1
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.js.map +1 -1
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.d.ts +64 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.js +241 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.d.ts +55 -0
- package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.js +245 -0
- package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.d.ts +67 -0
- package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.js +221 -0
- package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.d.ts +75 -0
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.js +270 -0
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.js.map +1 -0
- package/dist/components/table/columnFilters/BooleanFilter.stories.d.ts +57 -0
- package/dist/components/table/columnFilters/BooleanFilter.stories.d.ts.map +1 -0
- package/dist/components/table/columnFilters/BooleanFilter.stories.js +198 -0
- package/dist/components/table/columnFilters/BooleanFilter.stories.js.map +1 -0
- package/dist/components/table/columnFilters/TimeFilter.stories.d.ts +58 -0
- package/dist/components/table/columnFilters/TimeFilter.stories.d.ts.map +1 -0
- package/dist/components/table/columnFilters/TimeFilter.stories.js +207 -0
- package/dist/components/table/columnFilters/TimeFilter.stories.js.map +1 -0
- package/dist/components/table/pagination/PaginationPanel.stories.d.ts +113 -0
- package/dist/components/table/pagination/PaginationPanel.stories.d.ts.map +1 -0
- package/dist/components/table/pagination/PaginationPanel.stories.js +272 -0
- package/dist/components/table/pagination/PaginationPanel.stories.js.map +1 -0
- package/dist/components/table/tableControls/HideColumnsDropdown.d.ts.map +1 -1
- package/dist/components/table/tableControls/HideColumnsDropdown.js +9 -3
- package/dist/components/table/tableControls/HideColumnsDropdown.js.map +1 -1
- package/dist/components/table/tableControls/TableControls.stories.d.ts +151 -0
- package/dist/components/table/tableControls/TableControls.stories.d.ts.map +1 -0
- package/dist/components/table/tableControls/TableControls.stories.js +356 -0
- package/dist/components/table/tableControls/TableControls.stories.js.map +1 -0
- package/dist/components/table/tableControls/TableSettingsDropdown.d.ts +27 -1
- package/dist/components/table/tableControls/TableSettingsDropdown.d.ts.map +1 -1
- package/dist/components/table/tableControls/TableSettingsDropdown.js +53 -26
- package/dist/components/table/tableControls/TableSettingsDropdown.js.map +1 -1
- package/dist/components/table/tableControls/TableSettingsDropdown.test.d.ts +2 -0
- package/dist/components/table/tableControls/TableSettingsDropdown.test.d.ts.map +1 -0
- package/dist/components/table/tableControls/TableSettingsDropdown.test.js +178 -0
- package/dist/components/table/tableControls/TableSettingsDropdown.test.js.map +1 -0
- package/dist/components/tabs/Tabs.stories.d.ts +22 -4
- package/dist/components/tabs/Tabs.stories.d.ts.map +1 -1
- package/dist/components/tabs/Tabs.stories.js +398 -22
- package/dist/components/tabs/Tabs.stories.js.map +1 -1
- package/dist/components/tabs/TabsItem.stories.d.ts +54 -1
- package/dist/components/tabs/TabsItem.stories.d.ts.map +1 -1
- package/dist/components/tabs/TabsItem.stories.js +61 -9
- package/dist/components/tabs/TabsItem.stories.js.map +1 -1
- package/dist/components/toast/Toast.stories.d.ts +103 -10
- package/dist/components/toast/Toast.stories.d.ts.map +1 -1
- package/dist/components/toast/Toast.stories.js +409 -47
- package/dist/components/toast/Toast.stories.js.map +1 -1
- package/dist/components/toggle/Toggle.stories.d.ts +61 -46
- package/dist/components/toggle/Toggle.stories.d.ts.map +1 -1
- package/dist/components/toggle/Toggle.stories.js +311 -122
- package/dist/components/toggle/Toggle.stories.js.map +1 -1
- package/dist/components/tooltip/Tooltip.stories.d.ts +78 -6
- package/dist/components/tooltip/Tooltip.stories.d.ts.map +1 -1
- package/dist/components/tooltip/Tooltip.stories.js +413 -7
- package/dist/components/tooltip/Tooltip.stories.js.map +1 -1
- package/dist/components/tooltip/TooltipWrapper.stories.d.ts +71 -7
- package/dist/components/tooltip/TooltipWrapper.stories.d.ts.map +1 -1
- package/dist/components/tooltip/TooltipWrapper.stories.js +238 -10
- package/dist/components/tooltip/TooltipWrapper.stories.js.map +1 -1
- package/dist/index.css +8 -0
- package/dist/index.css.map +1 -1
- package/dist/utils/PopupParentContext.stories.d.ts +17 -0
- package/dist/utils/PopupParentContext.stories.d.ts.map +1 -0
- package/dist/utils/PopupParentContext.stories.js +266 -0
- package/dist/utils/PopupParentContext.stories.js.map +1 -0
- package/dist/utils/getDefaultPopupParent.d.ts.map +1 -1
- package/dist/utils/getDefaultPopupParent.js +6 -0
- package/dist/utils/getDefaultPopupParent.js.map +1 -1
- package/package.json +1 -1
- package/src/components/articleCard/ArticleCard.stories.tsx +524 -111
- package/src/components/avatar/Avatar.stories.tsx +504 -59
- package/src/components/avatarGroup/AvatarGroup.stories.tsx +977 -175
- package/src/components/banner/Banner.stories.tsx +7 -3
- package/src/components/card/Card.stories.tsx +466 -36
- package/src/components/combobox/Combobox.stories.tsx +867 -260
- package/src/components/datePicker/DatePicker.stories.tsx +777 -60
- package/src/components/dateTimePicker/DateTimePicker.stories.tsx +910 -132
- package/src/components/editableText/EditableText.stories.tsx +567 -91
- package/src/components/formField/FormField.test.tsx +6 -0
- package/src/components/formField/FormField.tsx +5 -0
- package/src/components/formField/fieldset/Fieldset.stories.tsx +761 -51
- package/src/components/formField/inputs/checkbox/CheckboxGroup.tsx +1 -1
- package/src/components/formField/inputs/checkbox/CheckboxInput.tsx +1 -1
- package/src/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.tsx +504 -11
- package/src/components/formField/inputs/radio/RadioButtonGroup.tsx +17 -4
- package/src/components/formField/inputs/radio/RadioButtonInput.stories.tsx +71 -59
- package/src/components/formField/inputs/selectDropdown/SelectDropdown.stories.tsx +1079 -168
- package/src/components/formField/inputs/time/TimeInput.stories.tsx +1140 -104
- package/src/components/formField/label/Label.stories.tsx +317 -8
- package/src/components/icoText/IcoText.stories.tsx +442 -31
- package/src/components/kpiCard/KPICard.stories.tsx +475 -30
- package/src/components/kvpList/KVPList.stories.tsx +593 -26
- package/src/components/modal/Modal.stories.tsx +963 -26
- package/src/components/modal/modalManager/ModalManager.stories.tsx +612 -454
- package/src/components/pill/Pill.stories.tsx +11 -13
- package/src/components/pill/Pill.tsx +1 -0
- package/src/components/row/Row.stories.tsx +474 -58
- package/src/components/searchBar/SearchBar.stories.tsx +570 -38
- package/src/components/section/Section.stories.tsx +723 -70
- package/src/components/singleUser/SingleUser.stories.tsx +393 -34
- package/src/components/slideoverManager/SlideoverManager.stories.tsx +572 -342
- package/src/components/table/DSDefaultColDef.ts +25 -5
- package/src/components/table/Table.stories.tsx +460 -5
- package/src/components/table/Table.test.tsx +53 -0
- package/src/components/table/Table.tsx +9 -2
- package/src/components/table/TableFooter.stories.tsx +196 -0
- package/src/components/table/TableHeader.stories.tsx +251 -0
- package/src/components/table/cellEditors/DateCellEditor.stories.tsx +245 -0
- package/src/components/table/cellRenderers/BooleanCellRenderer.stories.tsx +278 -0
- package/src/components/table/cellRenderers/ButtonCellRenderer.stories.tsx +333 -0
- package/src/components/table/cellRenderers/CheckboxCellRenderer.stories.tsx +337 -0
- package/src/components/table/cellRenderers/CheckboxCellRenderer.tsx +5 -1
- package/src/components/table/cellRenderers/DefaultCellRenderer.stories.tsx +342 -0
- package/src/components/table/cellRenderers/InlineTextCellRenderer.stories.tsx +292 -0
- package/src/components/table/cellRenderers/SelectDropdownCellRenderer.stories.tsx +369 -0
- package/src/components/table/columnFilters/BooleanFilter.stories.tsx +268 -0
- package/src/components/table/columnFilters/TimeFilter.stories.tsx +281 -0
- package/src/components/table/pagination/PaginationPanel.stories.tsx +327 -0
- package/src/components/table/tableControls/HideColumnsDropdown.tsx +11 -2
- package/src/components/table/tableControls/TableControls.stories.tsx +415 -0
- package/src/components/table/tableControls/TableSettingsDropdown.test.tsx +207 -0
- package/src/components/table/tableControls/TableSettingsDropdown.tsx +103 -39
- package/src/components/tabs/Tabs.stories.tsx +540 -60
- package/src/components/tabs/TabsItem.stories.tsx +82 -8
- package/src/components/toast/Toast.stories.tsx +539 -77
- package/src/components/toggle/Toggle.stories.tsx +371 -135
- package/src/components/tooltip/Tooltip.stories.tsx +606 -15
- package/src/components/tooltip/TooltipWrapper.stories.tsx +348 -12
- package/src/docs/Contributing.mdx +241 -0
- package/src/docs/UsingComponents.mdx +93 -0
- package/src/docs/Welcome.mdx +68 -0
- package/src/global.scss +7 -0
- package/src/utils/PopupParentContext.stories.tsx +367 -0
- package/src/utils/getDefaultPopupParent.ts +6 -0
- package/.ralph/storybook-upgrade/knowledge.md +0 -308
- package/.ralph/storybook-upgrade/prd.json +0 -777
- package/.ralph/storybook-upgrade/progress.md +0 -342
- package/src/components/table/TableWIP.mdx +0 -3
|
@@ -1,24 +1,360 @@
|
|
|
1
|
-
import type { Meta } from '@storybook/react-vite';
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import {
|
|
3
|
+
Controls,
|
|
4
|
+
Heading as DocHeading,
|
|
5
|
+
Markdown,
|
|
6
|
+
Primary as DocPrimary,
|
|
7
|
+
Stories,
|
|
8
|
+
Subtitle,
|
|
9
|
+
Title,
|
|
10
|
+
} from '@storybook/addon-docs/blocks';
|
|
11
|
+
import { TooltipWrapper } from './TooltipWrapper';
|
|
2
12
|
import { Button } from 'Components/button/Button';
|
|
3
|
-
import {
|
|
13
|
+
import { Icon } from 'Components/icon/Icon';
|
|
4
14
|
|
|
5
|
-
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Docs page content
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
const DESCRIPTION_INTRO = [
|
|
20
|
+
'`TooltipWrapper` is a convenience wrapper around the `Tooltip` compound component.',
|
|
21
|
+
'Pass your trigger as `children` and your tooltip text as `tooltipContent` — the wiring is done for you.',
|
|
22
|
+
'For full control over placement, arrow, or portal behaviour, use',
|
|
23
|
+
'[`Tooltip`](?path=/docs/components-tooltip--docs) directly.',
|
|
24
|
+
].join(' ');
|
|
25
|
+
|
|
26
|
+
const USAGE_GUIDANCE = [
|
|
27
|
+
'### When to use',
|
|
28
|
+
'',
|
|
29
|
+
'- Drop-in tooltip for **any focusable element** — no composition required',
|
|
30
|
+
'- When you just need a simple label string or short phrase above the trigger',
|
|
31
|
+
'- Preferred over raw `Tooltip` when no custom content or placement tweaking is needed',
|
|
32
|
+
'',
|
|
33
|
+
'---',
|
|
34
|
+
'',
|
|
35
|
+
'### When NOT to use',
|
|
36
|
+
'',
|
|
37
|
+
'| Situation | Use instead |',
|
|
38
|
+
'|---|---|',
|
|
39
|
+
'| Custom placement, alignment, or sideOffset | [`Tooltip`](?path=/docs/components-tooltip--docs) directly |',
|
|
40
|
+
'| Rich structured tooltip content (headings, lists) | [`Tooltip`](?path=/docs/components-tooltip--docs) directly |',
|
|
41
|
+
'| No arrow needed | [`Tooltip`](?path=/docs/components-tooltip--docs) with `shouldShowArrow={false}` |',
|
|
42
|
+
'',
|
|
43
|
+
'---',
|
|
44
|
+
'',
|
|
45
|
+
'### Props',
|
|
46
|
+
'',
|
|
47
|
+
'| Prop | Type | Default | Description |',
|
|
48
|
+
'|---|---|---|---|',
|
|
49
|
+
'| `children` | `ReactNode` | — | The trigger element. Must be focusable. |',
|
|
50
|
+
'| `tooltipContent` | `ReactNode` | — | Content rendered inside the tooltip bubble |',
|
|
51
|
+
'| `delayDuration` | `number` | `400` | Milliseconds before the tooltip appears on hover |',
|
|
52
|
+
'| `triggerProps` | `TooltipTriggerProps` | — | Extra props forwarded to `Tooltip.Trigger` |',
|
|
53
|
+
'| `contentProps` | `Omit<ContentProps, "children">` | — | Extra props forwarded to `Tooltip.Content` (e.g. `side`, `sideOffset`, `shouldShowArrow`) |',
|
|
54
|
+
].join('\n');
|
|
55
|
+
|
|
56
|
+
const DEVELOPER_NOTES = [
|
|
57
|
+
'### Forwarding content props',
|
|
58
|
+
'',
|
|
59
|
+
'Pass any `Tooltip.Content` prop (such as `side`, `sideOffset`, `shouldShowArrow`) through `contentProps`:',
|
|
60
|
+
'',
|
|
61
|
+
'```tsx',
|
|
62
|
+
'<TooltipWrapper',
|
|
63
|
+
' tooltipContent="Filter by term"',
|
|
64
|
+
' contentProps={{ side: "right", shouldShowArrow: false }}',
|
|
65
|
+
'>',
|
|
66
|
+
' <button type="button">Filter</button>',
|
|
67
|
+
'</TooltipWrapper>',
|
|
68
|
+
'```',
|
|
69
|
+
'',
|
|
70
|
+
'---',
|
|
71
|
+
'',
|
|
72
|
+
'### Accessibility',
|
|
73
|
+
'',
|
|
74
|
+
'- The trigger child must be focusable — keyboard users navigate by Tab and expect the tooltip to appear on focus.',
|
|
75
|
+
'- Both `aria-label` on the trigger **and** `tooltipContent` serve the same purpose for accessible icon buttons.',
|
|
76
|
+
' Provide both for the best experience across input methods.',
|
|
77
|
+
'- Keep `tooltipContent` short — one line is ideal.',
|
|
78
|
+
'',
|
|
79
|
+
'---',
|
|
80
|
+
'',
|
|
81
|
+
'### TypeScript types',
|
|
82
|
+
'',
|
|
83
|
+
'```ts',
|
|
84
|
+
"import type { TooltipWrapper } from '@arbor-education/design-system.components';",
|
|
85
|
+
'',
|
|
86
|
+
'type Props = TooltipWrapper.Props;',
|
|
87
|
+
'```',
|
|
88
|
+
].join('\n');
|
|
89
|
+
|
|
90
|
+
const RELATED_COMPONENTS = [
|
|
91
|
+
'## Related components',
|
|
92
|
+
'',
|
|
93
|
+
'[Tooltip](?path=/docs/components-tooltip--docs) · [Button](?path=/docs/components-button--docs) · [Icon](?path=/docs/components-icon--docs)',
|
|
94
|
+
].join('\n');
|
|
95
|
+
|
|
96
|
+
const PROPS_INTRO = 'The preview below is wired to the **Controls** panel — tweak any prop to see the story update in real time.';
|
|
97
|
+
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Docs page
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
|
|
102
|
+
function TooltipWrapperDocsPage() {
|
|
103
|
+
return (
|
|
104
|
+
<>
|
|
105
|
+
<Title />
|
|
106
|
+
<Subtitle />
|
|
107
|
+
<Markdown>{DESCRIPTION_INTRO}</Markdown>
|
|
108
|
+
<DocHeading>Interactive example</DocHeading>
|
|
109
|
+
<Markdown>{PROPS_INTRO}</Markdown>
|
|
110
|
+
<DocPrimary />
|
|
111
|
+
<Controls />
|
|
112
|
+
<DocHeading>Usage guidance</DocHeading>
|
|
113
|
+
<Markdown>{USAGE_GUIDANCE}</Markdown>
|
|
114
|
+
<DocHeading>Developer notes</DocHeading>
|
|
115
|
+
<Markdown>{DEVELOPER_NOTES}</Markdown>
|
|
116
|
+
<DocHeading>Examples</DocHeading>
|
|
117
|
+
<Stories title="" />
|
|
118
|
+
<Markdown>{RELATED_COMPONENTS}</Markdown>
|
|
119
|
+
</>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Meta
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
const meta = {
|
|
6
128
|
title: 'Components/Tooltip/TooltipWrapper',
|
|
7
|
-
component:
|
|
129
|
+
component: TooltipWrapper,
|
|
130
|
+
tags: ['autodocs'],
|
|
131
|
+
parameters: {
|
|
132
|
+
layout: 'centered',
|
|
133
|
+
docs: {
|
|
134
|
+
page: TooltipWrapperDocsPage,
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
argTypes: {
|
|
138
|
+
tooltipContent: {
|
|
139
|
+
control: 'text',
|
|
140
|
+
description: 'Content rendered inside the tooltip bubble. Typically a short string.',
|
|
141
|
+
table: {
|
|
142
|
+
type: { summary: 'ReactNode' },
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
children: {
|
|
146
|
+
control: false,
|
|
147
|
+
description: 'The trigger element. Must be a focusable element or a component that forwards its ref.',
|
|
148
|
+
table: {
|
|
149
|
+
type: { summary: 'ReactNode' },
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
delayDuration: {
|
|
153
|
+
control: 'number',
|
|
154
|
+
description: 'Milliseconds to wait before the tooltip appears on hover.',
|
|
155
|
+
table: {
|
|
156
|
+
type: { summary: 'number' },
|
|
157
|
+
defaultValue: { summary: '400' },
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
triggerProps: {
|
|
161
|
+
control: false,
|
|
162
|
+
description: 'Extra props forwarded to `Tooltip.Trigger`.',
|
|
163
|
+
table: {
|
|
164
|
+
type: { summary: 'TooltipTriggerProps' },
|
|
165
|
+
defaultValue: { summary: 'undefined' },
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
contentProps: {
|
|
169
|
+
control: false,
|
|
170
|
+
description: [
|
|
171
|
+
'Extra props forwarded to `Tooltip.Content`.',
|
|
172
|
+
'Use this to control `side`, `sideOffset`, `shouldShowArrow`, etc.',
|
|
173
|
+
].join(' '),
|
|
174
|
+
table: {
|
|
175
|
+
type: { summary: "Omit<ContentProps, 'children'>" },
|
|
176
|
+
defaultValue: { summary: 'undefined' },
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
} satisfies Meta<typeof TooltipWrapper>;
|
|
181
|
+
|
|
182
|
+
export default meta;
|
|
183
|
+
type Story = StoryObj<typeof meta>;
|
|
184
|
+
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
// Helper
|
|
187
|
+
// ---------------------------------------------------------------------------
|
|
188
|
+
|
|
189
|
+
const withDescription = (story: Omit<Story, 'args'>, description: string): Story => ({
|
|
190
|
+
...(story as Story),
|
|
8
191
|
parameters: {
|
|
192
|
+
...story.parameters,
|
|
9
193
|
docs: {
|
|
194
|
+
...story.parameters?.docs,
|
|
10
195
|
description: {
|
|
11
|
-
|
|
196
|
+
story: description,
|
|
12
197
|
},
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
};
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
// Templates
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
|
|
206
|
+
const WithIconTriggerTemplate = () => (
|
|
207
|
+
<div style={{ display: 'flex', gap: 'var(--spacing-small)' }}>
|
|
208
|
+
<TooltipWrapper tooltipContent="Download report" delayDuration={0}>
|
|
209
|
+
<button
|
|
210
|
+
type="button"
|
|
211
|
+
aria-label="Download report"
|
|
212
|
+
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 'var(--spacing-xsmall)', display: 'flex' }}
|
|
213
|
+
>
|
|
214
|
+
<Icon name="download" size={24} />
|
|
215
|
+
</button>
|
|
216
|
+
</TooltipWrapper>
|
|
217
|
+
|
|
218
|
+
<TooltipWrapper tooltipContent="Share" delayDuration={0}>
|
|
219
|
+
<button
|
|
220
|
+
type="button"
|
|
221
|
+
aria-label="Share"
|
|
222
|
+
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 'var(--spacing-xsmall)', display: 'flex' }}
|
|
223
|
+
>
|
|
224
|
+
<Icon name="share" size={24} />
|
|
225
|
+
</button>
|
|
226
|
+
</TooltipWrapper>
|
|
227
|
+
|
|
228
|
+
<TooltipWrapper tooltipContent="Settings" delayDuration={0}>
|
|
229
|
+
<button
|
|
230
|
+
type="button"
|
|
231
|
+
aria-label="Settings"
|
|
232
|
+
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 'var(--spacing-xsmall)', display: 'flex' }}
|
|
233
|
+
>
|
|
234
|
+
<Icon name="settings" size={24} />
|
|
235
|
+
</button>
|
|
236
|
+
</TooltipWrapper>
|
|
237
|
+
</div>
|
|
238
|
+
);
|
|
16
239
|
|
|
17
|
-
|
|
240
|
+
const WithContentPropsTemplate = () => (
|
|
241
|
+
<div style={{ display: 'flex', gap: 'var(--spacing-large)', padding: 'var(--spacing-xxlarge)' }}>
|
|
242
|
+
<TooltipWrapper
|
|
243
|
+
tooltipContent="Appears on the right"
|
|
244
|
+
contentProps={{ side: 'right' }}
|
|
245
|
+
delayDuration={0}
|
|
246
|
+
>
|
|
247
|
+
<Button type="secondary">Side: right</Button>
|
|
248
|
+
</TooltipWrapper>
|
|
249
|
+
|
|
250
|
+
<TooltipWrapper
|
|
251
|
+
tooltipContent="No arrow here"
|
|
252
|
+
contentProps={{ shouldShowArrow: false }}
|
|
253
|
+
delayDuration={0}
|
|
254
|
+
>
|
|
255
|
+
<Button type="secondary">No arrow</Button>
|
|
256
|
+
</TooltipWrapper>
|
|
257
|
+
|
|
258
|
+
<TooltipWrapper
|
|
259
|
+
tooltipContent="Extra offset"
|
|
260
|
+
contentProps={{ sideOffset: 16 }}
|
|
261
|
+
delayDuration={0}
|
|
262
|
+
>
|
|
263
|
+
<Button type="secondary">sideOffset=16</Button>
|
|
264
|
+
</TooltipWrapper>
|
|
265
|
+
</div>
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
// ---------------------------------------------------------------------------
|
|
269
|
+
// Stories
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
|
|
272
|
+
export const Default: Story = {
|
|
18
273
|
args: {
|
|
19
|
-
tooltipContent: '
|
|
20
|
-
|
|
274
|
+
tooltipContent: 'This is the tooltip content',
|
|
275
|
+
delayDuration: 400,
|
|
276
|
+
children: <Button type="primary">Hover or focus me</Button>,
|
|
277
|
+
},
|
|
278
|
+
parameters: {
|
|
279
|
+
docs: {
|
|
280
|
+
description: {
|
|
281
|
+
story: [
|
|
282
|
+
'Pass the trigger as `children` and the label as `tooltipContent`.',
|
|
283
|
+
'`TooltipWrapper` handles all the `Tooltip.Trigger` / `Tooltip.Content` wiring.',
|
|
284
|
+
'Adjust `delayDuration` and `tooltipContent` in the **Controls** panel.',
|
|
285
|
+
].join(' '),
|
|
286
|
+
},
|
|
287
|
+
},
|
|
21
288
|
},
|
|
22
289
|
};
|
|
23
290
|
|
|
24
|
-
export
|
|
291
|
+
export const WithIconTrigger: Story = withDescription(
|
|
292
|
+
{
|
|
293
|
+
render: WithIconTriggerTemplate,
|
|
294
|
+
parameters: {
|
|
295
|
+
controls: { disable: true },
|
|
296
|
+
docs: {
|
|
297
|
+
source: {
|
|
298
|
+
language: 'tsx',
|
|
299
|
+
code: `
|
|
300
|
+
import { Icon, TooltipWrapper } from '@arbor-education/design-system.components';
|
|
301
|
+
|
|
302
|
+
// The most common pattern: icon-only toolbar buttons with accessible labels.
|
|
303
|
+
function TooltipWrapperWithIconTriggerExample() {
|
|
304
|
+
return (
|
|
305
|
+
<TooltipWrapper tooltipContent="Download report" delayDuration={0}>
|
|
306
|
+
<button
|
|
307
|
+
type="button"
|
|
308
|
+
aria-label="Download report"
|
|
309
|
+
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 'var(--spacing-xsmall)', display: 'flex' }}
|
|
310
|
+
>
|
|
311
|
+
<Icon name="download" size={24} />
|
|
312
|
+
</button>
|
|
313
|
+
</TooltipWrapper>
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
export default TooltipWrapperWithIconTriggerExample;
|
|
317
|
+
`.trim(),
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
[
|
|
323
|
+
'The most common pattern: icon-only toolbar buttons with accessible labels.',
|
|
324
|
+
'Provide both `aria-label` on the button (screen readers) and `tooltipContent` (sighted mouse users).',
|
|
325
|
+
].join(' '),
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
export const WithContentProps: Story = withDescription(
|
|
329
|
+
{
|
|
330
|
+
render: WithContentPropsTemplate,
|
|
331
|
+
parameters: {
|
|
332
|
+
controls: { disable: true },
|
|
333
|
+
docs: {
|
|
334
|
+
source: {
|
|
335
|
+
language: 'tsx',
|
|
336
|
+
code: `
|
|
337
|
+
import { TooltipWrapper } from '@arbor-education/design-system.components';
|
|
338
|
+
|
|
339
|
+
function TooltipWrapperWithContentPropsExample() {
|
|
340
|
+
return (
|
|
341
|
+
<TooltipWrapper
|
|
342
|
+
tooltipContent="Appears on the right"
|
|
343
|
+
contentProps={{ side: 'right', shouldShowArrow: false }}
|
|
344
|
+
delayDuration={0}
|
|
345
|
+
>
|
|
346
|
+
<button type="button">Hover me</button>
|
|
347
|
+
</TooltipWrapper>
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
export default TooltipWrapperWithContentPropsExample;
|
|
351
|
+
`.trim(),
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
[
|
|
357
|
+
'Forward any `Tooltip.Content` prop via `contentProps` — including `side`, `sideOffset`, and `shouldShowArrow`.',
|
|
358
|
+
'This keeps the convenience of `TooltipWrapper` while allowing placement control.',
|
|
359
|
+
].join(' '),
|
|
360
|
+
);
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { Meta } from '@storybook/addon-docs/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title="Getting Started/Contributing" />
|
|
4
|
+
|
|
5
|
+
# Contributing to the Design System
|
|
6
|
+
|
|
7
|
+
← [Back to Welcome](/?path=/docs/getting-started-welcome--docs)
|
|
8
|
+
|
|
9
|
+
This guide is for developers working on the design system itself — adding new components, fixing bugs, or improving docs. If you're just looking to use components in a product, see [Using the Components](/?path=/docs/getting-started-using-the-components--docs).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Local setup
|
|
14
|
+
|
|
15
|
+
**Prerequisites:** [nvm](https://github.com/nvm-sh/nvm) and [yarn](https://classic.yarnpkg.com/lang/en/docs/install/)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
nvm use
|
|
19
|
+
yarn install
|
|
20
|
+
yarn storybook
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Storybook starts on port 6006 with hot reloading. Make a change to a component or story file and it'll update immediately in the browser.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Creating a new component
|
|
28
|
+
|
|
29
|
+
Use the scaffolding script to generate all the necessary files at once:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
yarn create-component <ComponentName>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
This creates four files inside `src/components/<componentName>/`:
|
|
36
|
+
|
|
37
|
+
<table>
|
|
38
|
+
<thead>
|
|
39
|
+
<tr><th>File</th><th>Purpose</th></tr>
|
|
40
|
+
</thead>
|
|
41
|
+
<tbody>
|
|
42
|
+
<tr><td><code>Component.tsx</code></td><td>The component itself</td></tr>
|
|
43
|
+
<tr><td><code>Component.test.tsx</code></td><td>Unit tests</td></tr>
|
|
44
|
+
<tr><td><code>Component.stories.tsx</code></td><td>Storybook stories and docs</td></tr>
|
|
45
|
+
<tr><td><code>component.scss</code></td><td>Styles</td></tr>
|
|
46
|
+
</tbody>
|
|
47
|
+
</table>
|
|
48
|
+
|
|
49
|
+
It also automatically adds the component's exports to `src/index.ts` and `src/index.scss` — no manual wiring needed.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Key conventions
|
|
54
|
+
|
|
55
|
+
### File and directory naming
|
|
56
|
+
|
|
57
|
+
<table>
|
|
58
|
+
<thead>
|
|
59
|
+
<tr><th>Thing</th><th>Convention</th><th>Example</th></tr>
|
|
60
|
+
</thead>
|
|
61
|
+
<tbody>
|
|
62
|
+
<tr><td>Component file</td><td>PascalCase</td><td><code>Button.tsx</code></td></tr>
|
|
63
|
+
<tr><td>Test file</td><td>PascalCase + <code>.test.tsx</code></td><td><code>Button.test.tsx</code></td></tr>
|
|
64
|
+
<tr><td>Story file</td><td>PascalCase + <code>.stories.tsx</code></td><td><code>Button.stories.tsx</code></td></tr>
|
|
65
|
+
<tr><td>Stylesheet</td><td>camelCase matching directory</td><td><code>button.scss</code></td></tr>
|
|
66
|
+
<tr><td>Directory</td><td>camelCase</td><td><code>button/</code></td></tr>
|
|
67
|
+
</tbody>
|
|
68
|
+
</table>
|
|
69
|
+
|
|
70
|
+
### CSS class naming
|
|
71
|
+
|
|
72
|
+
All classes use the `ds-` prefix with BEM-style modifiers:
|
|
73
|
+
|
|
74
|
+
```scss
|
|
75
|
+
.ds-button { } // base class
|
|
76
|
+
.ds-button--primary { } // modifier
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Use the `classnames` library for conditional classes.
|
|
80
|
+
|
|
81
|
+
### Path aliases
|
|
82
|
+
|
|
83
|
+
Always use these aliases in imports — not relative paths:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import { Button } from 'Components/button/Button'; // ✓
|
|
87
|
+
import { Button } from '../../components/button/Button'; // ✗
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
<table>
|
|
91
|
+
<thead>
|
|
92
|
+
<tr><th>Alias</th><th>Resolves to</th></tr>
|
|
93
|
+
</thead>
|
|
94
|
+
<tbody>
|
|
95
|
+
<tr><td><code>{'Components/*'}</code></td><td><code>{'./src/components/*'}</code></td></tr>
|
|
96
|
+
<tr><td><code>{'Utils/*'}</code></td><td><code>{'./src/utils/*'}</code></td></tr>
|
|
97
|
+
</tbody>
|
|
98
|
+
</table>
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Design principles
|
|
103
|
+
|
|
104
|
+
Before writing any component logic, it's worth internalising how we think about components here. These principles should shape every decision.
|
|
105
|
+
|
|
106
|
+
### Dumb components
|
|
107
|
+
|
|
108
|
+
Components must have **no business logic** and **no knowledge of the data layer**. A component should render what it receives via props and emit events back to the consumer — that's it. If you find yourself fetching data, transforming API responses, or encoding product-specific rules inside a component, stop and move that logic to the consumer.
|
|
109
|
+
|
|
110
|
+
### Brand agnostic
|
|
111
|
+
|
|
112
|
+
Components shouldn't know they're in an Arbor product. They should be general enough that they could — in theory — be dropped into any React app. This keeps them reusable, testable in isolation, and free from product churn.
|
|
113
|
+
|
|
114
|
+
### Delegate to the consumer (DTC)
|
|
115
|
+
|
|
116
|
+
This is the most important principle. **Empower consumers, don't constrain them.**
|
|
117
|
+
|
|
118
|
+
Rather than encoding every possible use case into a component's internals, expose the right props and hooks to let the consumer drive behaviour. When you're unsure whether to handle something inside the component or leave it to the consumer, default to leaving it to the consumer.
|
|
119
|
+
|
|
120
|
+
The Table component is the clearest example of this in practice. Rather than building a full data-grid from scratch, Table is a thin wrapper over [AG Grid](https://www.ag-grid.com/) — it applies Arbor's defaults and design tokens, then gets out of the way. Consumers get the full power of AG Grid's API directly. We don't abstract it away.
|
|
121
|
+
|
|
122
|
+
Ask yourself: *"Am I solving a problem that every consumer will always have, or am I solving one specific consumer's problem?"* Only the former belongs in the component.
|
|
123
|
+
|
|
124
|
+
### Compound components
|
|
125
|
+
|
|
126
|
+
Where a component has meaningful sub-parts, we favour the **compound component pattern** over a single monolithic component with a pile of props.
|
|
127
|
+
|
|
128
|
+
Rather than:
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
<Dropdown
|
|
132
|
+
trigger="Open"
|
|
133
|
+
items={[{ label: 'Edit', onClick: handleEdit }]}
|
|
134
|
+
header="Options"
|
|
135
|
+
/>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
We prefer:
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<Dropdown>
|
|
142
|
+
<Dropdown.Trigger>Open</Dropdown.Trigger>
|
|
143
|
+
<Dropdown.Content>
|
|
144
|
+
<Dropdown.Label>Options</Dropdown.Label>
|
|
145
|
+
<Dropdown.Item onClick={handleEdit}>Edit</Dropdown.Item>
|
|
146
|
+
</Dropdown.Content>
|
|
147
|
+
</Dropdown>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
This keeps each sub-part simple and independently composable. Consumers can mix, omit, or extend parts without needing the parent component to support every combination via props. Dropdown and Table are the clearest examples of this in the codebase — both expose sub-components that consumers assemble themselves.
|
|
151
|
+
|
|
152
|
+
When building a new component that has headers, footers, items, triggers, or other distinct sections, reach for this pattern first.
|
|
153
|
+
|
|
154
|
+
### Prop passthrough
|
|
155
|
+
|
|
156
|
+
For wrapper components — anything that wraps AG Grid, a Radix UI primitive, or another third-party library — always spread `...rest` onto the underlying element or component. This ensures consumers are never cut off from the full API of whatever we're wrapping.
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
function Table({ className, ...rest }: TableProps) {
|
|
160
|
+
return <AgGridReact className={cx('ds-table', className)} {...rest} />;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The rule is simple: **never let our wrapper be the reason a consumer can't do something the underlying library supports.** If they need an AG Grid prop we haven't explicitly typed, `...rest` means it still works. The same applies to any Radix primitive we build on top of (Dropdown, Tooltip, etc.).
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Quality gates
|
|
169
|
+
|
|
170
|
+
All three must pass before opening a PR:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
yarn check-types # zero TypeScript errors
|
|
174
|
+
yarn test:coverage # 100% of tests passing
|
|
175
|
+
yarn style-lint # zero SCSS linting errors
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Run lint with `--fix` to auto-correct issues:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
yarn eslint --fix src/
|
|
182
|
+
yarn style-lint --fix
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Branch and commit conventions
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Branch format
|
|
191
|
+
feature/MIS-12345-short-description
|
|
192
|
+
bugfix/MIS-12345-fix-the-thing
|
|
193
|
+
|
|
194
|
+
# Commit format (no colon after ticket ID)
|
|
195
|
+
MIS-12345 Add disabled state to Button
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Never push directly to `main` — all work goes through a branch and PR.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## PR rules (the important bit)
|
|
203
|
+
|
|
204
|
+
- **One PR = one Jira ticket.** No bundling unrelated changes.
|
|
205
|
+
- **Under 400 lines** of meaningful code change — if it's bigger, split it.
|
|
206
|
+
- **Fill in the PR template** — every section, no placeholders.
|
|
207
|
+
|
|
208
|
+
For the full details and the reasoning behind these rules, see [CONTRIBUTING.md](https://github.com/arbor-education/design-system.components/blob/main/CONTRIBUTING.md) on GitHub.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Local development with a consumer project
|
|
213
|
+
|
|
214
|
+
The library uses [Yalc](https://github.com/wclr/yalc) for local linking to consumer projects.
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Install Yalc globally (first time only)
|
|
218
|
+
npm i yalc -g
|
|
219
|
+
|
|
220
|
+
# In this repo — build and publish to the local Yalc store
|
|
221
|
+
yarn build
|
|
222
|
+
yalc publish
|
|
223
|
+
|
|
224
|
+
# In the consumer project — add the local package
|
|
225
|
+
yalc add @arbor-education/design-system.components
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
For active development with automatic updates on file save, use watch mode instead:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# Rebuilds and pushes to Yalc automatically on every change
|
|
232
|
+
yarn watch
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Useful links
|
|
238
|
+
|
|
239
|
+
- [GitHub repository](https://github.com/arbor-education/design-system.components)
|
|
240
|
+
- [CONTRIBUTING.md](https://github.com/arbor-education/design-system.components/blob/main/CONTRIBUTING.md) — the full contribution guide
|
|
241
|
+
- [NPM package](https://www.npmjs.com/package/@arbor-education/design-system.components)
|