@arbor-education/design-system.components 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gather/skills/write-stories/SKILL.md +207 -271
- package/.storybook/preview.ts +5 -0
- package/CHANGELOG.md +27 -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/number/NumberInput.d.ts.map +1 -1
- package/dist/components/formField/inputs/number/NumberInput.js +14 -2
- package/dist/components/formField/inputs/number/NumberInput.js.map +1 -1
- package/dist/components/formField/inputs/number/NumberInput.test.js +21 -0
- package/dist/components/formField/inputs/number/NumberInput.test.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 +7 -1
- package/dist/components/table/Table.d.ts.map +1 -1
- package/dist/components/table/Table.js +12 -5
- 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 +445 -3
- package/dist/components/table/Table.stories.js.map +1 -1
- package/dist/components/table/Table.test.js +184 -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/cellEditors/NumberCellEditor.d.ts +13 -0
- package/dist/components/table/cellEditors/NumberCellEditor.d.ts.map +1 -0
- package/dist/components/table/cellEditors/NumberCellEditor.js +35 -0
- package/dist/components/table/cellEditors/NumberCellEditor.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/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 +27 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.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/number/NumberInput.test.tsx +28 -0
- package/src/components/formField/inputs/number/NumberInput.tsx +15 -0
- 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 +504 -3
- package/src/components/table/Table.test.tsx +255 -0
- package/src/components/table/Table.tsx +15 -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/cellEditors/NumberCellEditor.tsx +83 -0
- package/src/components/table/cellEditors/numberCellEditor.scss +11 -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/table.scss +11 -0
- 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/index.scss +1 -0
- package/src/index.ts +3 -2
- 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,29 +1,201 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import {
|
|
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 { useEffect, useState } from 'react';
|
|
12
|
+
|
|
13
|
+
import { Button } from 'Components/button/Button';
|
|
14
|
+
import { EditableText } from 'Components/editableText/EditableText';
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Content strings
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
const DESCRIPTION_INTRO = `
|
|
21
|
+
EditableText is an inline text element that can be edited in place. Clicking the text (or the
|
|
22
|
+
pencil icon beside it) switches to an input or textarea, letting users rename records, update
|
|
23
|
+
titles, and correct short pieces of text without navigating away to a separate form.
|
|
24
|
+
`.trim();
|
|
25
|
+
|
|
26
|
+
const USAGE_GUIDANCE = `
|
|
27
|
+
### When to use
|
|
28
|
+
|
|
29
|
+
- **Renaming a record title in-context** — group names, report titles, curriculum plan headings
|
|
30
|
+
- **Correcting a short piece of editable text inline** — without navigating to a separate form
|
|
31
|
+
- **Updating a longer freeform description** — use with \`multiline\` for textarea behaviour
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### When NOT to use
|
|
36
|
+
|
|
37
|
+
| Situation | Use instead |
|
|
38
|
+
|---|---|
|
|
39
|
+
| Collecting new data in a form | [\`FormField\`](?path=/docs/components-formfield--docs) — labelled inputs with validation |
|
|
40
|
+
| Editing content that requires explicit confirmation before saving | \`FormField\` with a submit button — \`onEditSave\` fires on blur |
|
|
41
|
+
| Displaying text the user should never change | A plain text element — EditableText always shows an edit affordance |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### Always update \`text\` in \`onEditSave\`
|
|
46
|
+
|
|
47
|
+
EditableText is a **controlled-ish** component — it holds its own internal state but
|
|
48
|
+
initialises from the \`text\` prop. If you don't feed the saved value back as the new \`text\`
|
|
49
|
+
prop, the component will snap back to the original value on the next render cycle.
|
|
50
|
+
|
|
51
|
+
\`\`\`tsx
|
|
52
|
+
const [title, setTitle] = useState('Year 10 Science');
|
|
53
|
+
|
|
54
|
+
<EditableText text={title} onEditSave={setTitle} />
|
|
55
|
+
\`\`\`
|
|
56
|
+
|
|
57
|
+
### Multiline mode (\`multiline\`)
|
|
58
|
+
|
|
59
|
+
When \`multiline={true}\` the underlying input switches to a \`<textarea>\`.
|
|
60
|
+
The keyboard contract changes:
|
|
61
|
+
|
|
62
|
+
- **Enter** inserts a newline (does **not** save)
|
|
63
|
+
- **Escape** reverts to the pre-edit value
|
|
64
|
+
- **Blur** (clicking away) saves
|
|
65
|
+
|
|
66
|
+
> In single-line mode **Enter** saves immediately. Forgetting this difference is the most
|
|
67
|
+
> common source of unexpected behaviour — document it clearly when you expose this prop to end users.
|
|
68
|
+
|
|
69
|
+
### Programmatic edit mode (\`isEditing\`)
|
|
70
|
+
|
|
71
|
+
\`isEditing\` is a **one-way trigger**. Setting it to \`true\` tells the component to open the
|
|
72
|
+
input, but the component then takes back ownership of that state. You **cannot** force the
|
|
73
|
+
component closed by setting \`isEditing={false}\` after editing has started — only user
|
|
74
|
+
interaction (blur or Escape) can close it.
|
|
75
|
+
|
|
76
|
+
\`\`\`tsx
|
|
77
|
+
<EditableText
|
|
78
|
+
text={name}
|
|
79
|
+
isEditing={shouldEdit} // opens the input once; component owns state after that
|
|
80
|
+
onEditSave={setName}
|
|
81
|
+
/>
|
|
82
|
+
\`\`\`
|
|
83
|
+
|
|
84
|
+
### Blur saves immediately
|
|
85
|
+
|
|
86
|
+
\`onEditSave\` fires on blur, including accidental focus loss (e.g. the user clicks elsewhere
|
|
87
|
+
on the page). If the user must explicitly confirm a change before it is persisted, use a
|
|
88
|
+
\`<FormField>\` with a dedicated submit button instead.
|
|
89
|
+
|
|
90
|
+
### Typography is fully inherited
|
|
91
|
+
|
|
92
|
+
EditableText applies **no font styles of its own**. Size, weight, colour, and line-height all
|
|
93
|
+
come from the parent element. Wrap it in an \`<h1>\`, \`<p>\`, or any container and the input
|
|
94
|
+
will match the surrounding text automatically — no extra CSS needed.
|
|
95
|
+
`.trim();
|
|
96
|
+
|
|
97
|
+
const DEVELOPER_NOTES = `
|
|
98
|
+
### Accessibility & keyboard contract
|
|
99
|
+
|
|
100
|
+
| Key | Single-line | Multiline |
|
|
101
|
+
|---|---|---|
|
|
102
|
+
| Enter | Saves and closes the input | Inserts a newline |
|
|
103
|
+
| Escape | Reverts to the pre-edit value and closes | Reverts to the pre-edit value and closes |
|
|
104
|
+
| Tab / click away (blur) | Saves and closes the input | Saves and closes the input |
|
|
105
|
+
|
|
106
|
+
The display-mode button carries \`aria-label="Edit text"\` so screen-reader users understand
|
|
107
|
+
its purpose. The input carries \`aria-label="Text"\`. Both labels are applied automatically —
|
|
108
|
+
you do not need to pass anything extra.
|
|
109
|
+
`.trim();
|
|
110
|
+
|
|
111
|
+
const RELATED_COMPONENTS = `
|
|
112
|
+
## Related components
|
|
113
|
+
- [FormField](?path=/docs/components-formfield--docs) — full form inputs with labels, validation, and helper text
|
|
114
|
+
- [Table](?path=/docs/components-table--docs) — data grid that can use EditableText in inline-edit cells
|
|
115
|
+
- [TextInput](?path=/docs/components-formfield-inputs-textinput--docs) — the underlying single-line input used by EditableText
|
|
116
|
+
`.trim();
|
|
117
|
+
|
|
118
|
+
const PROPS_INTRO
|
|
119
|
+
= 'The preview below is wired to the **Controls** panel — tweak any prop to see the story update in real time.';
|
|
120
|
+
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// Docs page
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
function EditableTextDocsPage() {
|
|
126
|
+
return (
|
|
127
|
+
<>
|
|
128
|
+
<Title />
|
|
129
|
+
<Subtitle />
|
|
130
|
+
<Markdown>{DESCRIPTION_INTRO}</Markdown>
|
|
131
|
+
<DocHeading>Interactive example</DocHeading>
|
|
132
|
+
<Markdown>{PROPS_INTRO}</Markdown>
|
|
133
|
+
<DocPrimary />
|
|
134
|
+
<Controls />
|
|
135
|
+
<DocHeading>Usage guidance</DocHeading>
|
|
136
|
+
<Markdown>{USAGE_GUIDANCE}</Markdown>
|
|
137
|
+
<DocHeading>Developer notes</DocHeading>
|
|
138
|
+
<Markdown>{DEVELOPER_NOTES}</Markdown>
|
|
139
|
+
<DocHeading>Examples</DocHeading>
|
|
140
|
+
<Stories title="" />
|
|
141
|
+
<Markdown>{RELATED_COMPONENTS}</Markdown>
|
|
142
|
+
</>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
// Meta
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
3
149
|
|
|
4
150
|
const meta = {
|
|
5
151
|
title: 'Components/EditableText',
|
|
6
152
|
component: EditableText,
|
|
153
|
+
tags: ['autodocs'],
|
|
7
154
|
parameters: {
|
|
8
|
-
|
|
155
|
+
docs: {
|
|
156
|
+
page: EditableTextDocsPage,
|
|
157
|
+
},
|
|
9
158
|
},
|
|
10
|
-
tags: ['autodocs'],
|
|
11
159
|
argTypes: {
|
|
12
160
|
text: {
|
|
13
161
|
control: 'text',
|
|
14
|
-
description: 'The text to
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
description: 'Optional CSS class name',
|
|
162
|
+
description: 'The current text value. **Always** update this prop inside `onEditSave` to keep the component in sync.',
|
|
163
|
+
table: {
|
|
164
|
+
type: { summary: 'string' },
|
|
165
|
+
},
|
|
19
166
|
},
|
|
20
167
|
onEditSave: {
|
|
21
|
-
|
|
22
|
-
description: 'Callback fired when the text
|
|
168
|
+
control: false,
|
|
169
|
+
description: 'Callback fired when the user saves a change (on blur or Enter in single-line mode). Receives the new text string.',
|
|
170
|
+
table: {
|
|
171
|
+
type: { summary: '(newText: string) => void' },
|
|
172
|
+
},
|
|
23
173
|
},
|
|
24
174
|
isEditing: {
|
|
25
175
|
control: 'boolean',
|
|
26
|
-
description:
|
|
176
|
+
description:
|
|
177
|
+
'One-way trigger that forces the component into edit mode when set to `true`. The component takes back ownership of this state once editing begins — setting it back to `false` from outside will not close the input.',
|
|
178
|
+
table: {
|
|
179
|
+
type: { summary: 'boolean' },
|
|
180
|
+
defaultValue: { summary: 'false' },
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
multiline: {
|
|
184
|
+
control: 'boolean',
|
|
185
|
+
description:
|
|
186
|
+
'When `true`, switches the input to a `<textarea>`. In multiline mode **Enter inserts a newline** — it does NOT save. Only blur saves.',
|
|
187
|
+
table: {
|
|
188
|
+
type: { summary: 'boolean' },
|
|
189
|
+
defaultValue: { summary: 'false' },
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
className: {
|
|
193
|
+
control: 'text',
|
|
194
|
+
description: 'Additional CSS class names applied to the root `<span>` element.',
|
|
195
|
+
table: {
|
|
196
|
+
type: { summary: 'string' },
|
|
197
|
+
defaultValue: { summary: "''" },
|
|
198
|
+
},
|
|
27
199
|
},
|
|
28
200
|
},
|
|
29
201
|
} satisfies Meta<typeof EditableText>;
|
|
@@ -31,106 +203,410 @@ const meta = {
|
|
|
31
203
|
export default meta;
|
|
32
204
|
type Story = StoryObj<typeof meta>;
|
|
33
205
|
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
// Helper
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
|
|
210
|
+
const withDescription = (story: StoryObj<typeof meta>, description: string): StoryObj<typeof meta> => ({
|
|
211
|
+
...story,
|
|
212
|
+
parameters: {
|
|
213
|
+
...story.parameters,
|
|
214
|
+
docs: {
|
|
215
|
+
...story.parameters?.docs,
|
|
216
|
+
description: {
|
|
217
|
+
story: description,
|
|
218
|
+
},
|
|
219
|
+
},
|
|
44
220
|
},
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
// Named template components
|
|
225
|
+
// (All use useState so onEditSave keeps the component in sync — this is the
|
|
226
|
+
// pattern every consumer MUST follow to avoid text snapping back on re-render)
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
|
|
229
|
+
const DefaultTemplate = (args: React.ComponentProps<typeof EditableText>) => {
|
|
230
|
+
const [text, setText] = useState(args.text);
|
|
231
|
+
const [lastSaved, setLastSaved] = useState(args.text);
|
|
232
|
+
|
|
233
|
+
useEffect(() => {
|
|
234
|
+
setText(args.text);
|
|
235
|
+
setLastSaved(args.text);
|
|
236
|
+
}, [args.text]);
|
|
237
|
+
|
|
238
|
+
return (
|
|
239
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', maxWidth: '480px' }}>
|
|
240
|
+
<EditableText
|
|
241
|
+
{...args}
|
|
242
|
+
text={text}
|
|
243
|
+
onEditSave={(val) => {
|
|
244
|
+
setText(val);
|
|
245
|
+
setLastSaved(val);
|
|
246
|
+
}}
|
|
247
|
+
/>
|
|
248
|
+
<p className="ds-text" style={{ margin: 0, color: 'var(--color-grey-600)', fontSize: '0.875rem' }}>
|
|
249
|
+
Last saved: "
|
|
250
|
+
{lastSaved}
|
|
251
|
+
"
|
|
252
|
+
</p>
|
|
253
|
+
</div>
|
|
254
|
+
);
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const MultilineTemplate = () => {
|
|
258
|
+
const [text, setText] = useState(
|
|
259
|
+
'Attendance requirements and absence notification procedures for all pupils enrolled in Year 10.',
|
|
260
|
+
);
|
|
261
|
+
const [lastSaved, setLastSaved] = useState(text);
|
|
262
|
+
|
|
263
|
+
return (
|
|
264
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', maxWidth: '560px' }}>
|
|
265
|
+
<EditableText
|
|
266
|
+
text={text}
|
|
267
|
+
multiline
|
|
268
|
+
onEditSave={(val) => {
|
|
269
|
+
setText(val);
|
|
270
|
+
setLastSaved(val);
|
|
271
|
+
}}
|
|
272
|
+
/>
|
|
273
|
+
<p className="ds-text" style={{ margin: 0, color: 'var(--color-grey-600)', fontSize: '0.875rem' }}>
|
|
274
|
+
Last saved: "
|
|
275
|
+
{lastSaved}
|
|
276
|
+
"
|
|
277
|
+
</p>
|
|
278
|
+
</div>
|
|
279
|
+
);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const ProgrammaticControlTemplate = () => {
|
|
283
|
+
const [text, setText] = useState('Spring Term Assessment Schedule');
|
|
284
|
+
const [triggerEdit, setTriggerEdit] = useState(false);
|
|
285
|
+
|
|
286
|
+
const handleEditSave = (val: string) => {
|
|
287
|
+
setText(val);
|
|
288
|
+
setTriggerEdit(false);
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', maxWidth: '480px' }}>
|
|
293
|
+
<EditableText text={text} isEditing={triggerEdit} onEditSave={handleEditSave} />
|
|
294
|
+
<Button variant="secondary" onClick={() => setTriggerEdit(true)}>
|
|
295
|
+
Edit title
|
|
296
|
+
</Button>
|
|
297
|
+
</div>
|
|
298
|
+
);
|
|
45
299
|
};
|
|
46
300
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
301
|
+
const InHeading1Template = () => {
|
|
302
|
+
const [text, setText] = useState('Year 10 Science Curriculum Plan');
|
|
303
|
+
return (
|
|
50
304
|
<h1>
|
|
51
|
-
<EditableText {
|
|
305
|
+
<EditableText text={text} onEditSave={setText} />
|
|
52
306
|
</h1>
|
|
53
|
-
)
|
|
54
|
-
args: {
|
|
55
|
-
text: 'Editable Heading Level 1',
|
|
56
|
-
onEditSave: () => {},
|
|
57
|
-
},
|
|
307
|
+
);
|
|
58
308
|
};
|
|
59
309
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
310
|
+
const InHeading2Template = () => {
|
|
311
|
+
const [text, setText] = useState('Spring Term Assessment Schedule');
|
|
312
|
+
return (
|
|
63
313
|
<h2>
|
|
64
|
-
<EditableText {
|
|
314
|
+
<EditableText text={text} onEditSave={setText} />
|
|
65
315
|
</h2>
|
|
66
|
-
)
|
|
67
|
-
args: {
|
|
68
|
-
text: 'Editable Heading Level 2',
|
|
69
|
-
onEditSave: () => {},
|
|
70
|
-
},
|
|
316
|
+
);
|
|
71
317
|
};
|
|
72
318
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
onEditSave: () => {},
|
|
83
|
-
},
|
|
319
|
+
const InParagraphTemplate = () => {
|
|
320
|
+
const [text, setText] = useState('Emily Johnson');
|
|
321
|
+
return (
|
|
322
|
+
<p className="ds-text">
|
|
323
|
+
Class teacher:
|
|
324
|
+
{' '}
|
|
325
|
+
<EditableText text={text} onEditSave={setText} />
|
|
326
|
+
</p>
|
|
327
|
+
);
|
|
84
328
|
};
|
|
85
329
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
onEditSave: () => {},
|
|
96
|
-
},
|
|
330
|
+
const LongTextTemplate = () => {
|
|
331
|
+
const [text, setText] = useState(
|
|
332
|
+
'Behaviour policy and expectations for all students during lesson time, including mobile phone usage and dress code requirements',
|
|
333
|
+
);
|
|
334
|
+
return (
|
|
335
|
+
<div style={{ maxWidth: '480px' }}>
|
|
336
|
+
<EditableText text={text} onEditSave={setText} />
|
|
337
|
+
</div>
|
|
338
|
+
);
|
|
97
339
|
};
|
|
98
340
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<EditableText {...args} />
|
|
104
|
-
</p>
|
|
105
|
-
),
|
|
106
|
-
args: {
|
|
107
|
-
text: 'Editable paragraph text',
|
|
108
|
-
onEditSave: () => {},
|
|
109
|
-
},
|
|
110
|
-
};
|
|
341
|
+
const EscapeToCancelTemplate = () => {
|
|
342
|
+
const [text, setText] = useState('Mr. David Chen');
|
|
343
|
+
const [savedText, setSavedText] = useState('Mr. David Chen');
|
|
344
|
+
const [cancelCount, setCancelCount] = useState(0);
|
|
111
345
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
346
|
+
return (
|
|
347
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', maxWidth: '480px' }}>
|
|
348
|
+
<EditableText
|
|
349
|
+
text={text}
|
|
350
|
+
onEditSave={(val) => {
|
|
351
|
+
setText(val);
|
|
352
|
+
setSavedText(val);
|
|
353
|
+
}}
|
|
354
|
+
/>
|
|
355
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.25rem' }}>
|
|
356
|
+
<p className="ds-text" style={{ margin: 0, color: 'var(--color-grey-600)', fontSize: '0.875rem' }}>
|
|
357
|
+
Saved value: "
|
|
358
|
+
{savedText}
|
|
359
|
+
"
|
|
360
|
+
</p>
|
|
361
|
+
<p className="ds-text" style={{ margin: 0, color: 'var(--color-grey-600)', fontSize: '0.875rem' }}>
|
|
362
|
+
Escapes pressed:
|
|
363
|
+
{' '}
|
|
364
|
+
{cancelCount}
|
|
365
|
+
</p>
|
|
366
|
+
</div>
|
|
367
|
+
<p className="ds-text" style={{ margin: 0, fontSize: '0.875rem' }}>
|
|
368
|
+
Try editing the text above, type something new, then press
|
|
369
|
+
{' '}
|
|
370
|
+
<kbd>Escape</kbd>
|
|
371
|
+
{' '}
|
|
372
|
+
— the
|
|
373
|
+
original value is restored without calling
|
|
374
|
+
{' '}
|
|
375
|
+
<code>onEditSave</code>
|
|
376
|
+
.
|
|
377
|
+
</p>
|
|
378
|
+
{/*
|
|
379
|
+
We track cancels by wrapping the component and watching for text changes
|
|
380
|
+
that don't match what we'd expect from a save — but EditableText does not
|
|
381
|
+
expose an onCancel callback. The counter below is illustrative only.
|
|
382
|
+
Reset the page to see the true saved state.
|
|
383
|
+
*/}
|
|
384
|
+
<Button variant="secondary" onClick={() => setCancelCount(c => c + 1)}>
|
|
385
|
+
Simulate cancel count (manual)
|
|
386
|
+
</Button>
|
|
117
387
|
</div>
|
|
118
|
-
)
|
|
119
|
-
args: {
|
|
120
|
-
text: 'Custom styled editable text',
|
|
121
|
-
onEditSave: () => {},
|
|
122
|
-
},
|
|
388
|
+
);
|
|
123
389
|
};
|
|
124
390
|
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
</h2>
|
|
131
|
-
),
|
|
391
|
+
// ---------------------------------------------------------------------------
|
|
392
|
+
// Stories
|
|
393
|
+
// ---------------------------------------------------------------------------
|
|
394
|
+
|
|
395
|
+
export const Default: Story = {
|
|
132
396
|
args: {
|
|
133
|
-
text: '
|
|
397
|
+
text: 'Year 10 Science Curriculum Plan',
|
|
134
398
|
onEditSave: () => {},
|
|
399
|
+
isEditing: false,
|
|
400
|
+
multiline: false,
|
|
401
|
+
className: '',
|
|
402
|
+
},
|
|
403
|
+
render: args => <DefaultTemplate {...args} />,
|
|
404
|
+
parameters: {
|
|
405
|
+
docs: {
|
|
406
|
+
description: {
|
|
407
|
+
story: PROPS_INTRO,
|
|
408
|
+
},
|
|
409
|
+
},
|
|
135
410
|
},
|
|
136
411
|
};
|
|
412
|
+
|
|
413
|
+
export const MultilineEditing: Story = withDescription(
|
|
414
|
+
{
|
|
415
|
+
args: { text: '', onEditSave: () => {} },
|
|
416
|
+
render: () => <MultilineTemplate />,
|
|
417
|
+
parameters: {
|
|
418
|
+
docs: {
|
|
419
|
+
source: {
|
|
420
|
+
code: `
|
|
421
|
+
import { EditableText } from '@arbor-education/design-system.components';
|
|
422
|
+
import { useState } from 'react';
|
|
423
|
+
|
|
424
|
+
const [text, setText] = useState(
|
|
425
|
+
'Attendance requirements and absence notification procedures for all pupils enrolled in Year 10.',
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
<EditableText
|
|
429
|
+
text={text}
|
|
430
|
+
multiline
|
|
431
|
+
onEditSave={setText}
|
|
432
|
+
/>
|
|
433
|
+
`.trim(),
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
`When \`multiline={true}\` the component renders a \`<textarea>\` instead of a text input.
|
|
439
|
+
|
|
440
|
+
> **Key difference:** In multiline mode **Enter inserts a newline** — it does **not** save.
|
|
441
|
+
> Only blur (clicking away) or Escape will close the editor.
|
|
442
|
+
> In single-line mode, Enter saves immediately.
|
|
443
|
+
|
|
444
|
+
Use multiline for longer freeform text such as descriptions, notes, or policy summaries.`,
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
export const ProgrammaticControl: Story = withDescription(
|
|
448
|
+
{
|
|
449
|
+
args: { text: '', onEditSave: () => {} },
|
|
450
|
+
render: () => <ProgrammaticControlTemplate />,
|
|
451
|
+
parameters: {
|
|
452
|
+
docs: {
|
|
453
|
+
source: {
|
|
454
|
+
code: `
|
|
455
|
+
import { EditableText } from '@arbor-education/design-system.components';
|
|
456
|
+
import { Button } from '@arbor-education/design-system.components';
|
|
457
|
+
import { useState } from 'react';
|
|
458
|
+
|
|
459
|
+
const [text, setText] = useState('Spring Term Assessment Schedule');
|
|
460
|
+
const [triggerEdit, setTriggerEdit] = useState(false);
|
|
461
|
+
|
|
462
|
+
<EditableText
|
|
463
|
+
text={text}
|
|
464
|
+
isEditing={triggerEdit}
|
|
465
|
+
onEditSave={(val) => {
|
|
466
|
+
setText(val);
|
|
467
|
+
setTriggerEdit(false);
|
|
468
|
+
}}
|
|
469
|
+
/>
|
|
470
|
+
<Button variant="secondary" onClick={() => setTriggerEdit(true)}>
|
|
471
|
+
Edit title
|
|
472
|
+
</Button>
|
|
473
|
+
`.trim(),
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
`Use \`isEditing\` to open the input programmatically — for example, from a toolbar button or a keyboard shortcut.
|
|
479
|
+
|
|
480
|
+
> **Important:** \`isEditing\` is a one-way trigger. Once the component receives \`true\` it takes back
|
|
481
|
+
> ownership of edit state. Setting \`isEditing={false}\` from the outside will **not** close
|
|
482
|
+
> the input after editing has begun — only blur or Escape can do that.`,
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
export const InHeading1: Story = withDescription(
|
|
486
|
+
{
|
|
487
|
+
args: { text: '', onEditSave: () => {} },
|
|
488
|
+
render: () => <InHeading1Template />,
|
|
489
|
+
parameters: {
|
|
490
|
+
docs: {
|
|
491
|
+
source: {
|
|
492
|
+
code: `
|
|
493
|
+
import { EditableText } from '@arbor-education/design-system.components';
|
|
494
|
+
import { useState } from 'react';
|
|
495
|
+
|
|
496
|
+
const [text, setText] = useState('Year 10 Science Curriculum Plan');
|
|
497
|
+
|
|
498
|
+
<h1>
|
|
499
|
+
<EditableText text={text} onEditSave={setText} />
|
|
500
|
+
</h1>
|
|
501
|
+
`.trim(),
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
},
|
|
505
|
+
},
|
|
506
|
+
`EditableText inherits all typography from its parent. Wrapping it in an \`<h1>\` gives the
|
|
507
|
+
input the same font size, weight, and line-height as the surrounding heading — no extra CSS needed.`,
|
|
508
|
+
);
|
|
509
|
+
|
|
510
|
+
export const InHeading2: Story = withDescription(
|
|
511
|
+
{
|
|
512
|
+
args: { text: '', onEditSave: () => {} },
|
|
513
|
+
render: () => <InHeading2Template />,
|
|
514
|
+
parameters: {
|
|
515
|
+
docs: {
|
|
516
|
+
source: {
|
|
517
|
+
code: `
|
|
518
|
+
import { EditableText } from '@arbor-education/design-system.components';
|
|
519
|
+
import { useState } from 'react';
|
|
520
|
+
|
|
521
|
+
const [text, setText] = useState('Spring Term Assessment Schedule');
|
|
522
|
+
|
|
523
|
+
<h2>
|
|
524
|
+
<EditableText text={text} onEditSave={setText} />
|
|
525
|
+
</h2>
|
|
526
|
+
`.trim(),
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
},
|
|
531
|
+
`Same inheritance pattern as \`InHeading1\` but at \`<h2>\` size — useful for section titles and
|
|
532
|
+
panel headers inside a page that already has an \`<h1>\`.`,
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
export const InParagraph: Story = withDescription(
|
|
536
|
+
{
|
|
537
|
+
args: { text: '', onEditSave: () => {} },
|
|
538
|
+
render: () => <InParagraphTemplate />,
|
|
539
|
+
parameters: {
|
|
540
|
+
docs: {
|
|
541
|
+
source: {
|
|
542
|
+
code: `
|
|
543
|
+
import { EditableText } from '@arbor-education/design-system.components';
|
|
544
|
+
import { useState } from 'react';
|
|
545
|
+
|
|
546
|
+
const [text, setText] = useState('Emily Johnson');
|
|
547
|
+
|
|
548
|
+
<p className="ds-text">
|
|
549
|
+
Class teacher: <EditableText text={text} onEditSave={setText} />
|
|
550
|
+
</p>
|
|
551
|
+
`.trim(),
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
},
|
|
556
|
+
`EditableText can sit inline within a paragraph. The input inherits body-text styles automatically,
|
|
557
|
+
so it blends seamlessly with surrounding copy. Use \`className="ds-text"\` on the wrapping \`<p>\`
|
|
558
|
+
to apply design-system base font styles.`,
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
export const LongText: Story = withDescription(
|
|
562
|
+
{
|
|
563
|
+
args: { text: '', onEditSave: () => {} },
|
|
564
|
+
render: () => <LongTextTemplate />,
|
|
565
|
+
parameters: {
|
|
566
|
+
docs: {
|
|
567
|
+
source: {
|
|
568
|
+
code: `
|
|
569
|
+
import { EditableText } from '@arbor-education/design-system.components';
|
|
570
|
+
import { useState } from 'react';
|
|
571
|
+
|
|
572
|
+
const [text, setText] = useState(
|
|
573
|
+
'Behaviour policy and expectations for all students during lesson time, including mobile phone usage and dress code requirements',
|
|
574
|
+
);
|
|
575
|
+
|
|
576
|
+
<EditableText text={text} onEditSave={setText} />
|
|
577
|
+
`.trim(),
|
|
578
|
+
},
|
|
579
|
+
},
|
|
580
|
+
},
|
|
581
|
+
},
|
|
582
|
+
`Long text strings wrap naturally inside the component button. The input expands to fill the
|
|
583
|
+
available width when the user enters edit mode. Constrain the parent container's width if you
|
|
584
|
+
need to limit how wide the input can grow.`,
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
export const EscapeToCancel: Story = withDescription(
|
|
588
|
+
{
|
|
589
|
+
args: { text: '', onEditSave: () => {} },
|
|
590
|
+
render: () => <EscapeToCancelTemplate />,
|
|
591
|
+
parameters: {
|
|
592
|
+
docs: {
|
|
593
|
+
source: {
|
|
594
|
+
code: `
|
|
595
|
+
import { EditableText } from '@arbor-education/design-system.components';
|
|
596
|
+
import { useState } from 'react';
|
|
597
|
+
|
|
598
|
+
const [text, setText] = useState('Mr. David Chen');
|
|
599
|
+
|
|
600
|
+
// Pressing Escape while editing restores the pre-edit value
|
|
601
|
+
// and does NOT call onEditSave — no network request is made.
|
|
602
|
+
<EditableText text={text} onEditSave={setText} />
|
|
603
|
+
`.trim(),
|
|
604
|
+
},
|
|
605
|
+
},
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
`Press **Escape** while editing to revert the input to its pre-edit value without calling
|
|
609
|
+
\`onEditSave\`. This means no data is persisted — a safe exit for users who change their minds.
|
|
610
|
+
|
|
611
|
+
The component handles this internally. No special setup is needed in the consumer.`,
|
|
612
|
+
);
|