From d715e768a02bbd51e5241e8fb80a0527f2a7c5aa Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 27 Jun 2025 14:07:26 -0600 Subject: [PATCH 01/35] feat(#2302): popover - add table/filter contextual example --- src/examples/popover/PopoverPageExamples.tsx | 461 ++++++++++++++++++ .../popover/popover-page-examples.css | 5 + src/routes/components/Popover.tsx | 11 +- 3 files changed, 473 insertions(+), 4 deletions(-) create mode 100644 src/examples/popover/PopoverPageExamples.tsx create mode 100644 src/examples/popover/popover-page-examples.css diff --git a/src/examples/popover/PopoverPageExamples.tsx b/src/examples/popover/PopoverPageExamples.tsx new file mode 100644 index 000000000..d8c759043 --- /dev/null +++ b/src/examples/popover/PopoverPageExamples.tsx @@ -0,0 +1,461 @@ +import { useContext } from "react"; +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabBadge, + GoabFormItem, + GoabRadioGroup, + GoabRadioItem, + GoabButton, + GoabPopover, + GoabTable +} from "@abgov/react-components"; +import "./popover-page-examples.css"; +import { GoabBadgeType } from "@abgov/ui-components-common"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; + +export const PopoverPageExamples = () => { + const noop = () => {} + const { version } = useContext(LanguageVersionContext); + const target = ( + + Filter + + ); + const popoverValues = [ + { + key: 1, + type: "success", + status: "Open", + }, + { + key: 2, + type: "midtone", + status: "Closed", + }, + { + key: 3, + type: "midtone", + status: "Closed", + }, + { + key: 4, + type: "midtone", + status: "Closed", + }, + { + key: 5, + type: "success", + status: "Open", + }, + { + key: 6, + type: "midtone", + status: "Closed", + }, + ]; + return ( + <> + + + + {/*============= React code ==============*/} + {version === "old" && ( + + Filter + + ); + + const popoverValues = [ + { + key: 1, + type: "success", + status: "Open", + }, + { + key: 2, + type: "midtone", + status: "Closed", + }, + { + key: 3, + type: "midtone", + status: "Closed", + }, + { + key: 4, + type: "midtone", + status: "Closed", + }, + { + key: 5, + type: "success", + status: "Open", + }, + { + key: 6, + type: "midtone", + status: "Closed", + }, + ]; + `} + /> + )} + + {version === "new" && ( + + Filter + + ); + + const popoverValues = [ + { + key: 1, + type: "success", + status: "Open", + }, + { + key: 2, + type: "midtone", + status: "Closed", + }, + { + key: 3, + type: "midtone", + status: "Closed", + }, + { + key: 4, + type: "midtone", + status: "Closed", + }, + { + key: 5, + type: "success", + status: "Open", + }, + { + key: 6, + type: "midtone", + status: "Closed", + }, + ]; + `} + /> + )} + + {version === "old" && ( + +

Table with a filter

+ +
+ + + + + + + Remove filter +
+
+ + + + + Status + Text + Number + Action + + + + {popoverValues.map(u => ( + + + Lorem ipsum + 1234567890 + Action + + ))} + + + `} + /> + )} + + {version === "new" && ( + +

Table with a filter

+ +
+ + + + + + + Remove filter +
+
+ + + + + Status + Text + Number + Action + + + + {popoverValues.map(u => ( + + + Lorem ipsum + 1234567890 + Action + + ))} + + + `} + /> + )} + + {/*================ Angular code ==================*/} + {version === "old" && ( + + )} + + {version === "new" && ( + + )} + + {version === "old" && ( + +

Table with a filter

+ +
+ + + + + + + Remove filter +
+
+ Filter +
+
+ + + + + Status + Text + Number + Action + + + + + Lorem ipsum + 1234567890 + Action + + + + `} + /> + )} + + {version === "new" && ( + +

Table with a filter

+ +
+ + + + + + + Remove filter +
+
+ Filter +
+
+ + + + + Status + Text + Number + Action + + + + + Lorem ipsum + 1234567890 + Action + + + + `} + /> + )} +
+

Table with a filter

+ +
+ + + + + + + Remove filter +
+
+
+ + + + Status + Text + Number + Action + + + + {popoverValues.map(u => ( + + + Lorem ipsum + 1234567890 + Action + + ))} + + +
+ + ); +} diff --git a/src/examples/popover/popover-page-examples.css b/src/examples/popover/popover-page-examples.css new file mode 100644 index 000000000..7d441361f --- /dev/null +++ b/src/examples/popover/popover-page-examples.css @@ -0,0 +1,5 @@ +.goa-table-heading-container { + display: flex; + justify-content: space-between; + align-items: center; +} \ No newline at end of file diff --git a/src/routes/components/Popover.tsx b/src/routes/components/Popover.tsx index f2e254328..c92e0f1f9 100644 --- a/src/routes/components/Popover.tsx +++ b/src/routes/components/Popover.tsx @@ -1,11 +1,12 @@ import { useContext, useState } from "react"; import { ComponentBinding, Sandbox } from "@components/sandbox"; +import { Link } from "react-router-dom"; import { ComponentProperties, ComponentProperty, } from "@components/component-properties/ComponentProperties.tsx"; import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; -import { GoabBadge, GoabButton, GoabPopover, GoabTab, GoabTabs } from "@abgov/react-components"; +import { GoabBadge, GoabButton, GoabCallout, GoabPopover, GoabSpacer, GoabTab, GoabTabs } from "@abgov/react-components"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; import { propsToString } from "@components/sandbox/BaseSerializer.ts"; import { ComponentContent } from "@components/component-content/ComponentContent"; @@ -16,8 +17,8 @@ import { TestIdProperty } from "@components/component-properties/common-properties.ts"; import { DesignEmpty } from "@components/empty-states/design-empty/DesignEmpty.tsx"; +import { PopoverPageExamples } from "@examples/popover/PopoverPageExamples.tsx"; import { AccessibilityEmpty } from "@components/empty-states/accessibility-empty/AccessibilityEmpty.tsx"; -import { ExamplesEmpty } from "@components/empty-states/examples-empty/ExamplesEmpty.tsx"; const FIGMA_LINK = "https://www.figma.com/design/3pb2IK8s2QUqWieH79KdN7/%E2%9D%96-Component-library-%7C-DDD?node-id=27301-302109"; @@ -283,6 +284,8 @@ export default function PopoverPage() { It can be used for a number of different contexts. + + Popovers are used as a base layer in other components like tooltips, and dropdown menus. @@ -290,11 +293,11 @@ export default function PopoverPage() { heading={ <> Examples - + } > - + From c69d41c20f3a54366e6d26492b5aeb0919536a31 Mon Sep 17 00:00:00 2001 From: Miguel Date: Mon, 7 Jul 2025 15:32:40 -0600 Subject: [PATCH 02/35] Adjusted Popover imports. --- src/routes/components/Popover.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/components/Popover.tsx b/src/routes/components/Popover.tsx index ed5129a6e..dd4364312 100644 --- a/src/routes/components/Popover.tsx +++ b/src/routes/components/Popover.tsx @@ -18,7 +18,6 @@ import { TestIdProperty, } from "@components/component-properties/common-properties.ts"; import { DesignEmpty } from "@components/empty-states/design-empty/DesignEmpty.tsx"; -import { PopoverPageExamples } from "@examples/popover/PopoverPageExamples.tsx"; import { AccessibilityEmpty } from "@components/empty-states/accessibility-empty/AccessibilityEmpty.tsx"; //import { ExamplesEmpty } from "@components/empty-states/examples-empty/ExamplesEmpty.tsx"; import { PopoverExamples } from "@examples/popover/PopoverExamples"; From d514554cbf553e83d69183189376c0edce68e5f3 Mon Sep 17 00:00:00 2001 From: Miguel Date: Mon, 7 Jul 2025 15:34:42 -0600 Subject: [PATCH 03/35] Adjust TablePopover import. --- src/examples/popover/TablePopover.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/examples/popover/TablePopover.tsx b/src/examples/popover/TablePopover.tsx index 85aebf0bd..a8cdc0c76 100644 --- a/src/examples/popover/TablePopover.tsx +++ b/src/examples/popover/TablePopover.tsx @@ -13,7 +13,6 @@ import { import "./popover-page-examples.css"; import { GoabBadgeType } from "@abgov/ui-components-common"; import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; -import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; export const TablePopover = () => { const noop = () => {} From 5d5bfc526483768c76488e7907214258bd5bb489 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 25 Jul 2025 14:04:32 -0600 Subject: [PATCH 04/35] feat(#2302): popover - adding in filter option for table example (IN PROGESS) --- src/examples/popover/TablePopover.tsx | 87 +++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/src/examples/popover/TablePopover.tsx b/src/examples/popover/TablePopover.tsx index a8cdc0c76..d0d8725db 100644 --- a/src/examples/popover/TablePopover.tsx +++ b/src/examples/popover/TablePopover.tsx @@ -1,27 +1,26 @@ -import { useContext } from "react"; +import { useContext, useState, useEffect, useCallback } from "react"; import { Sandbox } from "@components/sandbox"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; import { GoabBadge, + GoabFilterChip, GoabFormItem, GoabRadioGroup, GoabRadioItem, GoabButton, GoabPopover, - GoabTable + GoabTable, + GoabText } from "@abgov/react-components"; import "./popover-page-examples.css"; import { GoabBadgeType } from "@abgov/ui-components-common"; import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { GoabRadioGroupOnChangeDetail } from "@abgov/ui-components-common"; export const TablePopover = () => { - const noop = () => {} const { version } = useContext(LanguageVersionContext); - const target = ( - - Filter - - ); + const [selectedChips, setSelectedChips] = useState([]); + const [filter, setFilter] = useState('All'); const popoverValues = [ { key: 1, @@ -54,6 +53,49 @@ export const TablePopover = () => { status: "Closed", }, ]; + + const [dataFiltered, setDataFiltered] = useState(popoverValues); + + const target = ( + + Filter + + ); + + function radioGroupOnChange(event: GoabRadioGroupOnChangeDetail) { + setSelectedChips([...selectedChips, event.value]); + return; + }; + + const checkNested = useCallback((obj: object, chip: string): boolean => { + return Object.values(obj).some(value => + typeof value === "object" && value !== null + ? checkNested(value, chip) + : typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase()) + ); + }, []); + + const removeFilter = (chip: string) => { + setSelectedChips(selectedChips.filter(c => c !== chip)); + }; + + const getFilteredData = useCallback ((selectedChips: string[]) => { + if (selectedChips.length === 0) { + return popoverValues; + } + const filteredData = popoverValues.filter((item: object) => + selectedChips.every(chip => checkNested(item, chip)) + ); + + return filteredData; + }, + [checkNested, popoverValues] + ); + + useEffect(() => { + setDataFiltered(getFilteredData(selectedChips)); + }, [getFilteredData, selectedChips]); + return ( <> @@ -421,15 +463,34 @@ export const TablePopover = () => {
- - - + + + - Remove filter
+ {selectedChips.length > 0 && ( +
+ + Filter: + + {selectedChips.length > 0 && + selectedChips.map((selectedChip, index) => ( + removeFilter(selectedChip)} + /> + ))} + setSelectedChips([])}> + Clear all + +
+ )} @@ -440,7 +501,7 @@ export const TablePopover = () => { - {popoverValues.map(u => ( + {dataFiltered.map(u => ( Lorem ipsum From 0473b17ca52763bae04f93d60c161eca5faa63e4 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 25 Jul 2025 14:12:56 -0600 Subject: [PATCH 05/35] feat(#2302): popover - adding in filter option for table example (IN PROGESS) --- src/examples/popover/TablePopover.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/examples/popover/TablePopover.tsx b/src/examples/popover/TablePopover.tsx index d0d8725db..5aa3c3f5e 100644 --- a/src/examples/popover/TablePopover.tsx +++ b/src/examples/popover/TablePopover.tsx @@ -20,7 +20,7 @@ import { GoabRadioGroupOnChangeDetail } from "@abgov/ui-components-common"; export const TablePopover = () => { const { version } = useContext(LanguageVersionContext); const [selectedChips, setSelectedChips] = useState([]); - const [filter, setFilter] = useState('All'); + const [filter] = useState('All'); const popoverValues = [ { key: 1, @@ -77,6 +77,7 @@ export const TablePopover = () => { const removeFilter = (chip: string) => { setSelectedChips(selectedChips.filter(c => c !== chip)); + return; }; const getFilteredData = useCallback ((selectedChips: string[]) => { From 5f53322eec3e70331c26596378ad8e43607d6d92 Mon Sep 17 00:00:00 2001 From: Thomas Jeffery Date: Tue, 29 Jul 2025 10:57:45 -0600 Subject: [PATCH 06/35] chore: reorganize and rename example files for GitHub integration --- .../communicate-a-future-service-outage.png | Bin 0 -> 17516 bytes .../filter-data-in-a-table.png | Bin 0 -> 28454 bytes .../reveal-input-based-on-a-selection.png | Bin 0 -> 13253 bytes .../show-a-user-progress.png | Bin 7205 -> 7075 bytes ...information-to-help-answer-a-question.png} | Bin src/examples/checkbox/CheckboxExamples.tsx | 4 ++-- src/examples/details/DetailsExamples.tsx | 6 ++--- src/examples/popover/PopoverExamples.tsx | 8 +++---- .../question-page/QuestionPageExamples.tsx | 4 ++-- src/examples/radio/RadioExamples.tsx | 4 ++-- ...eal-checkbox-input-based-on-selection.tsx} | 2 +- .../reveal-input-based-on-a-selection.tsx | 22 ++++++++++++++++++ ...reveal-radio-input-based-on-selection.tsx} | 2 +- ...information-to-help-answer-a-question.tsx} | 2 +- .../components/TemporaryNotification.tsx | 2 +- 15 files changed, 38 insertions(+), 18 deletions(-) create mode 100644 public/images/example-thumbnails/communicate-a-future-service-outage.png create mode 100644 public/images/example-thumbnails/filter-data-in-a-table.png create mode 100644 public/images/example-thumbnails/reveal-input-based-on-a-selection.png rename public/images/example-thumbnails/{reveal-more-information-to-help-answer-a-question.png => show-more-information-to-help-answer-a-question.png} (100%) rename src/examples/{checkbox/CheckboxRevealSlotExample.tsx => reveal-checkbox-input-based-on-selection.tsx} (99%) create mode 100644 src/examples/reveal-input-based-on-a-selection.tsx rename src/examples/{radio/RadioRevealSlotExample.tsx => reveal-radio-input-based-on-selection.tsx} (99%) rename src/examples/{reveal-more-information-to-help-answer-a-question.tsx => show-more-information-to-help-answer-a-question.tsx} (97%) diff --git a/public/images/example-thumbnails/communicate-a-future-service-outage.png b/public/images/example-thumbnails/communicate-a-future-service-outage.png new file mode 100644 index 0000000000000000000000000000000000000000..77d2ef92713bb7fa054502cc72a1e937b8c76b24 GIT binary patch literal 17516 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 E00=ELrvLx| literal 0 HcmV?d00001 diff --git a/public/images/example-thumbnails/filter-data-in-a-table.png b/public/images/example-thumbnails/filter-data-in-a-table.png new file mode 100644 index 0000000000000000000000000000000000000000..9e24c6743f1d9cc992e47ccd95290cf3917a6359 GIT binary patch literal 28454 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

A^ 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 x3DuO-fD8n>*&XkRoE4l7c#=W;2ybDsC(_ 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 U#*xV8R+STlh^P42f7&8A^-pY literal 7205 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 ZpJmdFtwTI7V{ukAkSFHd5 diff --git a/public/images/example-thumbnails/reveal-more-information-to-help-answer-a-question.png b/public/images/example-thumbnails/show-more-information-to-help-answer-a-question.png similarity index 100% rename from public/images/example-thumbnails/reveal-more-information-to-help-answer-a-question.png rename to public/images/example-thumbnails/show-more-information-to-help-answer-a-question.png diff --git a/src/examples/checkbox/CheckboxExamples.tsx b/src/examples/checkbox/CheckboxExamples.tsx index 925016662..ef34c68d3 100644 --- a/src/examples/checkbox/CheckboxExamples.tsx +++ b/src/examples/checkbox/CheckboxExamples.tsx @@ -1,7 +1,7 @@ import IncludeDescriptionsForItemsInACheckboxList from "@examples/include-descriptions-for-items-in-a-checkbox-list.tsx"; import SelectOneOrMoreFromAListOfOptions from "@examples/select-one-or-more-from-a-list-of-options.tsx"; -import { CheckboxRevealSlotExample } from "@examples/checkbox/CheckboxRevealSlotExample.tsx"; +import { RevealCheckboxInputBasedOnSelection } from "@examples/reveal-checkbox-input-based-on-selection.tsx"; import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; export const CheckboxExamples = () => { @@ -25,6 +25,6 @@ export const CheckboxExamples = () => { exampleTitle="Reveal input based on selection" figmaExample="https://www.figma.com/design/aIRjvBzpIUH0GbkffjbL04/%E2%9D%96-Patterns-library-%7C-DDD?node-id=6307-131069&m=dev"> - + ; } \ No newline at end of file diff --git a/src/examples/details/DetailsExamples.tsx b/src/examples/details/DetailsExamples.tsx index ed1a125dd..e8e270c43 100644 --- a/src/examples/details/DetailsExamples.tsx +++ b/src/examples/details/DetailsExamples.tsx @@ -5,8 +5,8 @@ import { AskAUserForDirectDepositInformation } from "@examples/ask-a-user-for-direct-deposit-information.tsx"; import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; -import RevealMoreInformationToHelpAnswerAQuestion - from "@examples/reveal-more-information-to-help-answer-a-question.tsx"; +import ShowMoreInformationToHelpAnswerAQuestion + from "@examples/show-more-information-to-help-answer-a-question.tsx"; export const DetailsExamples = () => { return ( @@ -15,7 +15,7 @@ export const DetailsExamples = () => { exampleTitle="Show more information to help answer a question" figmaExample="https://www.figma.com/design/aIRjvBzpIUH0GbkffjbL04/%E2%9D%96-Patterns-library-%7C-DDD?node-id=6307-197360&t=X0IQW5flDDaj8Vyg-4"> - + { const { version, language } = useContext(LanguageVersionContext); return ( <> + {version === "old" && ( + + )} {/*Popover Example - close using a button*/} @@ -25,10 +27,6 @@ export const PopoverExamples = () => { figmaExample=""> - - {version === "old" && ( - - )} ); }; diff --git a/src/examples/question-page/QuestionPageExamples.tsx b/src/examples/question-page/QuestionPageExamples.tsx index 6a06bbbcb..e38eb6264 100644 --- a/src/examples/question-page/QuestionPageExamples.tsx +++ b/src/examples/question-page/QuestionPageExamples.tsx @@ -2,7 +2,7 @@ import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader. import AskAUserOneQuestionAtATime from "@examples/ask-a-user-one-question-at-a-time.tsx"; import GiveBackgroundInformationBeforeAskingAQuestion from "../give-background-information-before-asking-a-question.tsx"; -import RevealMoreInformationToHelpAnswerAQuestion from "../reveal-more-information-to-help-answer-a-question.tsx"; +import ShowMoreInformationToHelpAnswerAQuestion from "../show-more-information-to-help-answer-a-question.tsx"; import ShowASectionTitleOnAQuestionPage from "../show-a-section-title-on-a-question-page.tsx"; import ShowASimpleProgressIndicatorOnAQuestionPage from "../show-a-simple-progress-indicator-on-a-question-page.tsx"; import GroupRelatedQuestionsTogetherOnAQuestionPage from "../group-related-questions-together-on-a-question-page.tsx"; @@ -28,7 +28,7 @@ export default function QuestionPageExamples() { exampleTitle="Reveal more information to help answer a question" figmaExample="https://www.figma.com/file/aIRjvBzpIUH0GbkffjbL04/%E2%9D%96-Patterns-library-%7C-DDD?type=design&node-id=101-4108&mode=design"> - + - + ); } \ No newline at end of file diff --git a/src/examples/checkbox/CheckboxRevealSlotExample.tsx b/src/examples/reveal-checkbox-input-based-on-selection.tsx similarity index 99% rename from src/examples/checkbox/CheckboxRevealSlotExample.tsx rename to src/examples/reveal-checkbox-input-based-on-selection.tsx index f8b4c1e69..d341e0863 100644 --- a/src/examples/checkbox/CheckboxRevealSlotExample.tsx +++ b/src/examples/reveal-checkbox-input-based-on-selection.tsx @@ -5,7 +5,7 @@ import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; import { OldComponentBanner } from "@components/old-component-banner/OldComponentBanner.tsx"; -export const CheckboxRevealSlotExample = () => { +export const RevealCheckboxInputBasedOnSelection = () => { const { version, language } = useContext(LanguageVersionContext); return ( <> diff --git a/src/examples/reveal-input-based-on-a-selection.tsx b/src/examples/reveal-input-based-on-a-selection.tsx new file mode 100644 index 000000000..42c0d09b3 --- /dev/null +++ b/src/examples/reveal-input-based-on-a-selection.tsx @@ -0,0 +1,22 @@ +import { RevealRadioInputBasedOnSelection } from "@examples/reveal-radio-input-based-on-selection.tsx"; +import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; +import { RevealCheckboxInputBasedOnSelection } from "@examples/reveal-checkbox-input-based-on-selection.tsx"; + +export default function RevealInputBasedOnASelection() { + + return ( + <> + + + + + + + + + ); +} \ No newline at end of file diff --git a/src/examples/radio/RadioRevealSlotExample.tsx b/src/examples/reveal-radio-input-based-on-selection.tsx similarity index 99% rename from src/examples/radio/RadioRevealSlotExample.tsx rename to src/examples/reveal-radio-input-based-on-selection.tsx index 4e0d4847c..af7069f76 100644 --- a/src/examples/radio/RadioRevealSlotExample.tsx +++ b/src/examples/reveal-radio-input-based-on-selection.tsx @@ -5,7 +5,7 @@ import { GoabFormItem, GoabInput, GoabRadioGroup, GoabRadioItem, GoabSpacer } fr import { OldComponentBanner } from "@components/old-component-banner/OldComponentBanner.tsx"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; -export const RadioRevealSlotExample = () => { +export const RevealRadioInputBasedOnSelection = () => { const { version, language } = useContext(LanguageVersionContext); const noop = () => {} return ( diff --git a/src/examples/reveal-more-information-to-help-answer-a-question.tsx b/src/examples/show-more-information-to-help-answer-a-question.tsx similarity index 97% rename from src/examples/reveal-more-information-to-help-answer-a-question.tsx rename to src/examples/show-more-information-to-help-answer-a-question.tsx index cd6d2cec8..e957e40d2 100644 --- a/src/examples/reveal-more-information-to-help-answer-a-question.tsx +++ b/src/examples/show-more-information-to-help-answer-a-question.tsx @@ -10,7 +10,7 @@ import { import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; import { useContext } from "react"; -export default function RevealMoreInformationToHelpAnswerAQuestion() { +export default function ShowMoreInformationToHelpAnswerAQuestion() { useContext(LanguageVersionContext); return (
diff --git a/src/routes/components/TemporaryNotification.tsx b/src/routes/components/TemporaryNotification.tsx index 8f4237181..f1a2c9c44 100644 --- a/src/routes/components/TemporaryNotification.tsx +++ b/src/routes/components/TemporaryNotification.tsx @@ -477,7 +477,7 @@ export default function TemporaryNotificationPage() { Examples - + }> From afb9ee97517f81f546e2aa318b33f251c5584b93 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 1 Aug 2025 16:24:31 -0600 Subject: [PATCH 07/35] feat(#2140): microsite header - added angular and react sample code --- ...e-user-to-give-feedback-to-the-service.tsx | 124 +++++++++++++++++- src/examples/show-version-number.tsx | 71 ++++++++++ 2 files changed, 194 insertions(+), 1 deletion(-) diff --git a/src/examples/link-the-user-to-give-feedback-to-the-service.tsx b/src/examples/link-the-user-to-give-feedback-to-the-service.tsx index 5684c2e74..cf4682fdf 100644 --- a/src/examples/link-the-user-to-give-feedback-to-the-service.tsx +++ b/src/examples/link-the-user-to-give-feedback-to-the-service.tsx @@ -1,15 +1,137 @@ import { GoabMicrositeHeader } from "@abgov/react-components"; import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; export default function GiveFeedbackLinkExample() { + const {version} = useContext(LanguageVersionContext); const onClick = () => { console.log("Feedback clicked"); alert("Thank you for your feedback!"); }; + return ( <> - + + + {/*Angular code*/} + {version === "old" && } + + {/*Angular code*/} + {version === "old" && + `} + />} + + {/*Angular code*/} + {version === "new" && } + + {/*Angular code*/} + {version === "new" && + `} + />} + + {/*React code*/} + {version === "old" && { + console.log("Feedback clicked"); + alert("Thank you for your feedback!"); + }; + `} + />} + + {/*React code*/} + {version === "old" && + `} + />} + + {/*React code*/} + {version === "new" && { + console.log("Feedback clicked"); + alert("Thank you for your feedback!"); + }; + `} + />} + + {/*React code*/} + {version === "new" && + `} + />} + {/* ...React + Angular code snippets here (same as original)... */} diff --git a/src/examples/show-version-number.tsx b/src/examples/show-version-number.tsx index 2c16a9e97..354a01deb 100644 --- a/src/examples/show-version-number.tsx +++ b/src/examples/show-version-number.tsx @@ -1,11 +1,82 @@ import { GoabMicrositeHeader } from "@abgov/react-components"; import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; export default function ShowVersionNumberExample() { + const {version} = useContext(LanguageVersionContext); return ( <> + + {/*Angular code*/} + {version === "old" && +
+ Slotted version text. + v1.23 +
+ + `} + />} + + {/*Angular code*/} + {version === "new" && +
+ Slotted version text. + v1.23 +
+ + `} + />} + + {/*React code*/} + {version === "old" && + Slotted version text. + v1.23 + + } + > + `} + />} + + {/*React code*/} + {version === "new" && + Slotted version text. + v1.23 + + } + > + `} + />} + {/* ...React + Angular code snippets here (same as original)... */} Date: Fri, 8 Aug 2025 12:44:36 -0600 Subject: [PATCH 08/35] feat(#2140): microsite header - removed the "slot" text from Version example --- src/examples/show-version-number.tsx | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/src/examples/show-version-number.tsx b/src/examples/show-version-number.tsx index 354a01deb..a494e5c12 100644 --- a/src/examples/show-version-number.tsx +++ b/src/examples/show-version-number.tsx @@ -19,7 +19,6 @@ export default function ShowVersionNumberExample() { code={`
- Slotted version text. v1.23
@@ -34,7 +33,6 @@ export default function ShowVersionNumberExample() { code={`
- Slotted version text. v1.23
@@ -49,12 +47,7 @@ export default function ShowVersionNumberExample() { code={` - Slotted version text. - v1.23 - - } + version={v1.23} > `} />} @@ -67,12 +60,7 @@ export default function ShowVersionNumberExample() { code={` - Slotted version text. - v1.23 - - } + version={v1.23} > `} />} @@ -80,12 +68,7 @@ export default function ShowVersionNumberExample() { {/* ...React + Angular code snippets here (same as original)... */} - Slotted version text. - v1.23 - - } + version={v1.23} />
From 3a2e2c1f94bf289b535c7d28ef5ba9594957d76a Mon Sep 17 00:00:00 2001 From: Thomas Jeffery Date: Mon, 11 Aug 2025 15:49:24 -0600 Subject: [PATCH 09/35] fix spacing inconsistencies across foundation and design token pages --- .../accessibility-empty/AccessibilityEmpty.tsx | 2 +- .../design-tokens/border-radius/BorderRadius.tsx | 4 ++-- .../design-tokens/border-width/BorderWidth.tsx | 4 ++-- src/routes/design-tokens/color/Color.tsx | 2 +- src/routes/design-tokens/icon-size/IconSize.tsx | 4 ++-- src/routes/design-tokens/opacity/Opacity.tsx | 4 ++-- src/routes/design-tokens/shadow/Shadow.tsx | 4 ++-- src/routes/design-tokens/spacing/Spacing.tsx | 4 ++-- src/routes/design-tokens/typography/Typography.tsx | 4 ++-- src/routes/foundations/Accessibility.tsx | 2 +- src/routes/foundations/BrandGuidelines.tsx | 2 +- src/routes/foundations/Capitalization.tsx | 5 +++-- src/routes/foundations/Color.tsx | 5 +++-- src/routes/foundations/DateFormat.tsx | 5 +++-- src/routes/foundations/DesignAtGoA.tsx | 2 +- src/routes/foundations/ErrorMessages.tsx | 7 ++++--- src/routes/foundations/HelperText.tsx | 5 +++-- src/routes/foundations/Iconography.tsx | 5 +++-- src/routes/foundations/Layout.tsx | 5 +++-- src/routes/foundations/Logo.tsx | 5 +++-- src/routes/foundations/Photography.tsx | 5 +++-- src/routes/foundations/Typography.tsx | 5 +++-- src/routes/get-started/ComponentLifecycle.tsx | 2 +- src/routes/get-started/GetStartedOverview.tsx | 4 ++-- src/routes/get-started/LtsPolicyPage.tsx | 2 +- src/routes/get-started/ReportBug.tsx | 2 +- src/routes/get-started/RequestFeature.tsx | 2 +- src/routes/get-started/Roadmap.tsx | 2 +- src/routes/get-started/Support.tsx | 2 +- .../get-started/UserExperienceGuidelines.tsx | 4 ++-- src/routes/get-started/designers/UxDesigner.tsx | 6 +++--- .../get-started/developers/BugVerification.tsx | 4 ++-- .../get-started/developers/DevelopersOverview.tsx | 4 ++-- .../get-started/developers/DevelopersSetup.tsx | 4 ++-- .../developers/DevelopersTechnologies.tsx | 4 ++-- .../get-started/developers/DevelopersVSCode.tsx | 4 ++-- .../get-started/developers/SupportedBrowsers.tsx | 10 +++++----- .../developers/upgrade-guide/DevelopersUpgrade.tsx | 8 ++++---- .../get-started/qa-testing/QATestingOverview.tsx | 2 +- src/routes/home.tsx | 14 +++++++------- 40 files changed, 90 insertions(+), 80 deletions(-) diff --git a/src/components/empty-states/accessibility-empty/AccessibilityEmpty.tsx b/src/components/empty-states/accessibility-empty/AccessibilityEmpty.tsx index 73d3af5a0..d3b2061c9 100644 --- a/src/components/empty-states/accessibility-empty/AccessibilityEmpty.tsx +++ b/src/components/empty-states/accessibility-empty/AccessibilityEmpty.tsx @@ -13,7 +13,7 @@ export function AccessibilityEmpty(props: Props) { component page in Figma. {" "} - + More accessibility guidance for design and development is coming soon. diff --git a/src/routes/design-tokens/border-radius/BorderRadius.tsx b/src/routes/design-tokens/border-radius/BorderRadius.tsx index ebff7fd56..22d85b867 100644 --- a/src/routes/design-tokens/border-radius/BorderRadius.tsx +++ b/src/routes/design-tokens/border-radius/BorderRadius.tsx @@ -1,5 +1,5 @@ import { useContext } from "react"; -import { GoabContainer, GoabGrid, GoabTable } from "@abgov/react-components"; +import { GoabContainer, GoabGrid, GoabTable, GoabText } from "@abgov/react-components"; import { TokenSnippet } from "@components/token-snippet/TokenSnippet"; import "./BorderRadius.css"; import { Token } from "../token"; @@ -120,7 +120,7 @@ export default function BorderRadiusPage() { return ( -

Border Radius

+ Border Radius {isDesktop ? renderDesktop() : renderMobile()}
); diff --git a/src/routes/design-tokens/border-width/BorderWidth.tsx b/src/routes/design-tokens/border-width/BorderWidth.tsx index 3299e4f3b..7c7ec9bb5 100644 --- a/src/routes/design-tokens/border-width/BorderWidth.tsx +++ b/src/routes/design-tokens/border-width/BorderWidth.tsx @@ -1,5 +1,5 @@ import { useContext } from "react"; -import { GoabContainer, GoabGrid, GoabTable } from "@abgov/react-components"; +import { GoabContainer, GoabGrid, GoabTable, GoabText } from "@abgov/react-components"; import { TokenSnippet } from "@components/token-snippet/TokenSnippet"; import "./BorderWidth.css"; import { Token } from "../token"; @@ -118,7 +118,7 @@ export default function BorderWidthPage() { return ( -

Border Width

+ Border Width {isDesktop ? renderDesktop() : renderMobile()}
); diff --git a/src/routes/design-tokens/color/Color.tsx b/src/routes/design-tokens/color/Color.tsx index eab8cd91f..a9d82362a 100644 --- a/src/routes/design-tokens/color/Color.tsx +++ b/src/routes/design-tokens/color/Color.tsx @@ -110,7 +110,7 @@ export default function ColorPage() { return ( -

Color

+ Color {isDesktop ? renderDesktop() : renderTablet()}
); diff --git a/src/routes/design-tokens/icon-size/IconSize.tsx b/src/routes/design-tokens/icon-size/IconSize.tsx index 871af740a..37982c6b6 100644 --- a/src/routes/design-tokens/icon-size/IconSize.tsx +++ b/src/routes/design-tokens/icon-size/IconSize.tsx @@ -1,4 +1,4 @@ -import { GoabContainer, GoabGrid, GoabIcon, GoabTable } from "@abgov/react-components"; +import { GoabContainer, GoabGrid, GoabIcon, GoabTable, GoabText } from "@abgov/react-components"; import { TokenSnippet } from "@components/token-snippet/TokenSnippet"; import "./IconSize.css"; import { getTokenGroups } from "../getTokenGroups"; @@ -138,7 +138,7 @@ export default function IconSizePage() { return ( -

Icon size

+ Icon size {isDesktop ? renderDesktop() : renderMobile()}
); diff --git a/src/routes/design-tokens/opacity/Opacity.tsx b/src/routes/design-tokens/opacity/Opacity.tsx index 373ebb416..46b1dace0 100644 --- a/src/routes/design-tokens/opacity/Opacity.tsx +++ b/src/routes/design-tokens/opacity/Opacity.tsx @@ -1,4 +1,4 @@ -import { GoabContainer, GoabGrid, GoabTable } from "@abgov/react-components"; +import { GoabContainer, GoabGrid, GoabTable, GoabText } from "@abgov/react-components"; import { TokenSnippet } from "@components/token-snippet/TokenSnippet"; import "./Opacity.css"; import { getTokenGroups } from "../getTokenGroups"; @@ -94,7 +94,7 @@ export default function OpacityPage() { return ( -

Opacity

+ Opacity {isDesktop ? renderDesktop() : renderMobile()}
); diff --git a/src/routes/design-tokens/shadow/Shadow.tsx b/src/routes/design-tokens/shadow/Shadow.tsx index 15c7dab36..e4db48116 100644 --- a/src/routes/design-tokens/shadow/Shadow.tsx +++ b/src/routes/design-tokens/shadow/Shadow.tsx @@ -1,4 +1,4 @@ -import { GoabContainer, GoabGrid, GoabTable } from "@abgov/react-components"; +import { GoabContainer, GoabGrid, GoabTable, GoabText } from "@abgov/react-components"; import { TokenSnippet } from "@components/token-snippet/TokenSnippet"; import "./Shadow.css"; import { getTokenGroups } from "../getTokenGroups"; @@ -110,7 +110,7 @@ export default function ShadowPage() { return ( -

Shadow

+ Shadow {isDesktop ? renderDesktop() : renderMobile()}
); diff --git a/src/routes/design-tokens/spacing/Spacing.tsx b/src/routes/design-tokens/spacing/Spacing.tsx index b942561d2..d5a54c8cc 100644 --- a/src/routes/design-tokens/spacing/Spacing.tsx +++ b/src/routes/design-tokens/spacing/Spacing.tsx @@ -1,4 +1,4 @@ -import { GoabContainer, GoabGrid, GoabTable } from "@abgov/react-components"; +import { GoabContainer, GoabGrid, GoabTable, GoabText } from "@abgov/react-components"; import { TokenSnippet } from "@components/token-snippet/TokenSnippet"; import "./Spacing.css"; import SPACING_TOKENS from "./spacing.json"; @@ -90,7 +90,7 @@ export default function SpacingPage() { return ( -

Spacing

+ Spacing {isDesktop ? renderDesktop() : renderMobile()}
); diff --git a/src/routes/design-tokens/typography/Typography.tsx b/src/routes/design-tokens/typography/Typography.tsx index 1814e2ad7..fd0df2628 100644 --- a/src/routes/design-tokens/typography/Typography.tsx +++ b/src/routes/design-tokens/typography/Typography.tsx @@ -1,4 +1,4 @@ -import { GoabContainer, GoabGrid, GoabTable } from "@abgov/react-components"; +import { GoabContainer, GoabGrid, GoabTable, GoabText } from "@abgov/react-components"; import { TokenSnippet } from "@components/token-snippet/TokenSnippet"; import TYPO_TOKENS from "./typography.json"; import { getTokenGroups } from "../getTokenGroups"; @@ -81,7 +81,7 @@ export default function TypographyPage() { return (
-

Typography

+ Typography {isDesktop ? renderDesktop() : renderMobile()}
diff --git a/src/routes/foundations/Accessibility.tsx b/src/routes/foundations/Accessibility.tsx index c033c8e47..f208ff8ff 100644 --- a/src/routes/foundations/Accessibility.tsx +++ b/src/routes/foundations/Accessibility.tsx @@ -8,7 +8,7 @@ export default function AccessibilityPage() { Accessibility - + We aim to create digital products that everyone can use, no matter their abilities or situation. This guide outlines key principles, design tips, and tools to help create accessible and inclusive experiences. diff --git a/src/routes/foundations/BrandGuidelines.tsx b/src/routes/foundations/BrandGuidelines.tsx index 9b593436c..221c6a9b6 100644 --- a/src/routes/foundations/BrandGuidelines.tsx +++ b/src/routes/foundations/BrandGuidelines.tsx @@ -7,7 +7,7 @@ export default function BrandGuidelinesPage() { Brand guidelines - + Communications and Public Engagement (CPE) plays an important role in providing and maintaining brand identity guidelines across the Government of Alberta. These guidelines ensure all digital products are consistent and easily recognizable, building trust with users. diff --git a/src/routes/foundations/Capitalization.tsx b/src/routes/foundations/Capitalization.tsx index a159e7d1d..afb6ebbd4 100644 --- a/src/routes/foundations/Capitalization.tsx +++ b/src/routes/foundations/Capitalization.tsx @@ -8,10 +8,11 @@ export default function CapitalizationPage() { return ( - + Content guidelines + Capitalization - + Use sentence case for all headings, labels, and content. diff --git a/src/routes/foundations/Color.tsx b/src/routes/foundations/Color.tsx index 0cf00f8a0..6a917b957 100644 --- a/src/routes/foundations/Color.tsx +++ b/src/routes/foundations/Color.tsx @@ -5,10 +5,11 @@ export default function FoundationsColorPage() { return ( - + Style guide + Color - + Colors play a major role in how the Government of Alberta communicates. They serve as a tool to convey clarity, express emotions, and promote inclusivity. diff --git a/src/routes/foundations/DateFormat.tsx b/src/routes/foundations/DateFormat.tsx index 03623321b..9133f84d7 100644 --- a/src/routes/foundations/DateFormat.tsx +++ b/src/routes/foundations/DateFormat.tsx @@ -7,10 +7,11 @@ const minGridWidth = "36ch"; export default function DateFormatPage() { return ( - + Content guidelines + Date format - + Configuration which contains date information that includes the specification of the form and structure of the date data within the date format in different scenarios. diff --git a/src/routes/foundations/DesignAtGoA.tsx b/src/routes/foundations/DesignAtGoA.tsx index b6a74b8b3..9c6236562 100644 --- a/src/routes/foundations/DesignAtGoA.tsx +++ b/src/routes/foundations/DesignAtGoA.tsx @@ -7,7 +7,7 @@ export default function DesignAtGoAPage() { Design at the Government of Alberta - + Citizens expect digital products that are modern, easy to use, and consistent. To meet these needs, our digital products must follow our user experience guidelines and should be tested frequently to make continuous improvement and stay relevant. diff --git a/src/routes/foundations/ErrorMessages.tsx b/src/routes/foundations/ErrorMessages.tsx index 2e9c7da85..52b6cc38d 100644 --- a/src/routes/foundations/ErrorMessages.tsx +++ b/src/routes/foundations/ErrorMessages.tsx @@ -18,11 +18,12 @@ export default function ErrorMessagesPage() { const noop = () => { }; return ( - + Content guidelines + Error messages - - Error messages appear when the user’s proposed action fails. + + Error messages appear when the user's proposed action fails. diff --git a/src/routes/foundations/HelperText.tsx b/src/routes/foundations/HelperText.tsx index 62fd5c909..f3cbd0010 100644 --- a/src/routes/foundations/HelperText.tsx +++ b/src/routes/foundations/HelperText.tsx @@ -19,10 +19,11 @@ export default function HelperTextPage() { return ( - + Content guidelines + Helper text - + Additional context and guidance that is always visible below an input. The text instructs a user on what needs to be completed to move to the next question in the form or process. diff --git a/src/routes/foundations/Iconography.tsx b/src/routes/foundations/Iconography.tsx index 6241a75be..94a916e59 100644 --- a/src/routes/foundations/Iconography.tsx +++ b/src/routes/foundations/Iconography.tsx @@ -75,10 +75,11 @@ export default function IconographyPage() { return ( - + Style guide + Iconography - + Icons are simple and universal graphic symbols that communicate and enhance both the aesthetic and functional aspects of our products. While they can be used with descriptors, they can also be self-expressive and convey meaning diff --git a/src/routes/foundations/Layout.tsx b/src/routes/foundations/Layout.tsx index 86c9e8156..238b83da8 100644 --- a/src/routes/foundations/Layout.tsx +++ b/src/routes/foundations/Layout.tsx @@ -6,10 +6,11 @@ export default function FoundationsLayoutPage() { return ( - + Style guide + Layout - + We use the layout as a structural template to support consistency across our products. By defining visual grids, spacing, and sections, we create intuitive products for our users. diff --git a/src/routes/foundations/Logo.tsx b/src/routes/foundations/Logo.tsx index 1c187745f..75f46d4d5 100644 --- a/src/routes/foundations/Logo.tsx +++ b/src/routes/foundations/Logo.tsx @@ -4,10 +4,11 @@ import { ComponentContent } from "@components/component-content/ComponentContent export default function LogoPage() { return ( - + Style guide + Logo - + Our logo is an important part of our brand identity and serves as a symbol that distinguishes our digital products from others. To keep our brand consistent and recognizable, we encourage following the guidelines for proper diff --git a/src/routes/foundations/Photography.tsx b/src/routes/foundations/Photography.tsx index 3871d9a62..51a2bbf99 100644 --- a/src/routes/foundations/Photography.tsx +++ b/src/routes/foundations/Photography.tsx @@ -4,10 +4,11 @@ import { ComponentContent } from "@components/component-content/ComponentContent export default function ImagesPage() { return ( - + Style guide + Photography - + The Government of Alberta maintains a library of photos specifically taken for government use, ensuring they are relevant to our citizens. This collection meets our established criteria for quality and accessibility. diff --git a/src/routes/foundations/Typography.tsx b/src/routes/foundations/Typography.tsx index 75ea5f563..3c114c13f 100644 --- a/src/routes/foundations/Typography.tsx +++ b/src/routes/foundations/Typography.tsx @@ -6,10 +6,11 @@ export default function FoundationsTypographyPage() { return ( - + Style guide + Typography - + Our typography system is designed to create a consistent and accessible experience across all Government of Alberta digital products. When paired with an effective content strategy, it enhances accessibility and makes content diff --git a/src/routes/get-started/ComponentLifecycle.tsx b/src/routes/get-started/ComponentLifecycle.tsx index 318bc667f..cdd5f3e5d 100644 --- a/src/routes/get-started/ComponentLifecycle.tsx +++ b/src/routes/get-started/ComponentLifecycle.tsx @@ -7,7 +7,7 @@ export default function ComponentLifecyclePage() { Component lifecycle - + This lifecycle defines the stages every component in the Design System undergoes, from Alpha to Production to Legacy. Each stage describes the component's maturity, adoption level, and support status.

diff --git a/src/routes/get-started/GetStartedOverview.tsx b/src/routes/get-started/GetStartedOverview.tsx index 6481bb6fa..46c837928 100644 --- a/src/routes/get-started/GetStartedOverview.tsx +++ b/src/routes/get-started/GetStartedOverview.tsx @@ -13,13 +13,13 @@ export default function GetStartedOverviewPage() { Starting with the design system - + Start with the design system to build on the research and experience of other service teams and avoid repeating work that's already been done. - + Design system by role: diff --git a/src/routes/get-started/LtsPolicyPage.tsx b/src/routes/get-started/LtsPolicyPage.tsx index d17a77ad4..460922e72 100644 --- a/src/routes/get-started/LtsPolicyPage.tsx +++ b/src/routes/get-started/LtsPolicyPage.tsx @@ -6,7 +6,7 @@ export const LtsPolicyPage = () => { <> Long Term Support (LTS) - + The Long Term Support (LTS) version will continue to be supported until September 30, 2025. Learn more about what you can expect. diff --git a/src/routes/get-started/ReportBug.tsx b/src/routes/get-started/ReportBug.tsx index be995c888..b4eed0b99 100644 --- a/src/routes/get-started/ReportBug.tsx +++ b/src/routes/get-started/ReportBug.tsx @@ -233,7 +233,7 @@ export default function ReportBugPage() { Report a bug - + Let us know if you find a problem or inconsistency in the design system. Providing complete details in your bug report helps our team understand, prioritize, and fix the issue faster. diff --git a/src/routes/get-started/RequestFeature.tsx b/src/routes/get-started/RequestFeature.tsx index 12ea72335..b15a07f56 100644 --- a/src/routes/get-started/RequestFeature.tsx +++ b/src/routes/get-started/RequestFeature.tsx @@ -10,7 +10,7 @@ export default function RequestFeaturePage() { Request a new feature - + Anyone can propose a new component or pattern for the design system. diff --git a/src/routes/get-started/Roadmap.tsx b/src/routes/get-started/Roadmap.tsx index 4524f230c..1ff0426bb 100644 --- a/src/routes/get-started/Roadmap.tsx +++ b/src/routes/get-started/Roadmap.tsx @@ -6,7 +6,7 @@ export default function RoadmapPage() { Roadmap - + A high-level summary of the work the design system team plans to focus on in 2025. Some initiatives span multiple phases, meaning they will be continuously worked on across the year. diff --git a/src/routes/get-started/Support.tsx b/src/routes/get-started/Support.tsx index 127d7d197..8e804de24 100644 --- a/src/routes/get-started/Support.tsx +++ b/src/routes/get-started/Support.tsx @@ -32,7 +32,7 @@ export default function SupportPage() { Get support - + Get help from our team with using the design system, including components, guidelines, best practices, and accessibility. diff --git a/src/routes/get-started/UserExperienceGuidelines.tsx b/src/routes/get-started/UserExperienceGuidelines.tsx index 484c0736f..28f0ecf41 100644 --- a/src/routes/get-started/UserExperienceGuidelines.tsx +++ b/src/routes/get-started/UserExperienceGuidelines.tsx @@ -4,8 +4,8 @@ export default function UserExperienceGuidelinesPage() { return ( <> Designers - User experience guidelines - Digital products built for the Government of Alberta should comply with these + User experience guidelines + Digital products built for the Government of Alberta should comply with these guidelines to ensure a quality user experience for Albertans. diff --git a/src/routes/get-started/designers/UxDesigner.tsx b/src/routes/get-started/designers/UxDesigner.tsx index 09d11c774..2d7e77452 100644 --- a/src/routes/get-started/designers/UxDesigner.tsx +++ b/src/routes/get-started/designers/UxDesigner.tsx @@ -6,8 +6,8 @@ export default function UxDesignerPage() { return ( Designers - Overview - As a designer, you can consume the design system through Figma. Through Figma you + Overview + As a designer, you can consume the design system through Figma. Through Figma you can use tokens, components, and page templates. @@ -65,7 +65,7 @@ export default function UxDesignerPage() { - + For example, you can communicate to your developer:
The colour is: --goa-color-info-default
diff --git a/src/routes/get-started/developers/BugVerification.tsx b/src/routes/get-started/developers/BugVerification.tsx index cbb3ba26a..7e431c6d1 100644 --- a/src/routes/get-started/developers/BugVerification.tsx +++ b/src/routes/get-started/developers/BugVerification.tsx @@ -5,8 +5,8 @@ export default function BugVerificationPage() { return ( Developers - Verify a bug - + Verify a bug + How to resolve issues with design system components diff --git a/src/routes/get-started/developers/DevelopersOverview.tsx b/src/routes/get-started/developers/DevelopersOverview.tsx index 9ea7b2032..ed0102f31 100644 --- a/src/routes/get-started/developers/DevelopersOverview.tsx +++ b/src/routes/get-started/developers/DevelopersOverview.tsx @@ -7,8 +7,8 @@ export default function DevelopersOverviewPage() { return ( Developers - Overview - As a developer, you can consume the design system using tokens, components, + Overview + As a developer, you can consume the design system using tokens, components, templates, and the demo application. diff --git a/src/routes/get-started/developers/DevelopersSetup.tsx b/src/routes/get-started/developers/DevelopersSetup.tsx index 71616c4f6..52107e30d 100644 --- a/src/routes/get-started/developers/DevelopersSetup.tsx +++ b/src/routes/get-started/developers/DevelopersSetup.tsx @@ -8,8 +8,8 @@ export default function DevelopersSetupPage() {
Developers - Setup - Once you are setup, you can use the project template to quickly get + Setup + Once you are setup, you can use the project template to quickly get started. View project templates diff --git a/src/routes/get-started/developers/DevelopersTechnologies.tsx b/src/routes/get-started/developers/DevelopersTechnologies.tsx index b667b2df7..33f854e2f 100644 --- a/src/routes/get-started/developers/DevelopersTechnologies.tsx +++ b/src/routes/get-started/developers/DevelopersTechnologies.tsx @@ -5,8 +5,8 @@ export default function DevelopersTechnologiesPage() { return ( Developers - Technologies - An overview of the technologies that make up the design system. + Technologies + An overview of the technologies that make up the design system.
diff --git a/src/routes/get-started/developers/DevelopersVSCode.tsx b/src/routes/get-started/developers/DevelopersVSCode.tsx index e9bc7b727..de4d9b84b 100644 --- a/src/routes/get-started/developers/DevelopersVSCode.tsx +++ b/src/routes/get-started/developers/DevelopersVSCode.tsx @@ -6,8 +6,8 @@ export default function DevelopersVSCodePage() { return ( Developers - VS Code - + VS Code + You can use VS Code's autocomplete suggestions for design system components and design tokens. diff --git a/src/routes/get-started/developers/SupportedBrowsers.tsx b/src/routes/get-started/developers/SupportedBrowsers.tsx index a1d66debd..ab25ea1a1 100644 --- a/src/routes/get-started/developers/SupportedBrowsers.tsx +++ b/src/routes/get-started/developers/SupportedBrowsers.tsx @@ -6,8 +6,8 @@ export default function SupportedBrowsersPage() { return ( Developers - Supported browsers - The design system components are tested on the following browsers and devices: + Supported browsers + The design system components are tested on the following browsers and devices: @@ -82,13 +82,13 @@ export default function SupportedBrowsersPage() {
- + Representative mobile OS used in testing - + Android OS: 10+ - + iOS: 15+ diff --git a/src/routes/get-started/developers/upgrade-guide/DevelopersUpgrade.tsx b/src/routes/get-started/developers/upgrade-guide/DevelopersUpgrade.tsx index c4fc903c3..2c59375c3 100644 --- a/src/routes/get-started/developers/upgrade-guide/DevelopersUpgrade.tsx +++ b/src/routes/get-started/developers/upgrade-guide/DevelopersUpgrade.tsx @@ -13,8 +13,8 @@ export default function DevelopersUpgradePage() { Developers - Version update guide - Step-by-step guide to updating your code from DDD Design System v3 to v4 + Version update guide + Step-by-step guide to updating your code from DDD Design System v3 to v4 (Angular) and v5 to v6 (React) @@ -38,8 +38,8 @@ export default function DevelopersUpgradePage() { The component is stable and supported in the latest major release. However, we recommend using the public form pattern for a more modular, flexible, and accessible approach. - - + + Major differences between current and new version diff --git a/src/routes/get-started/qa-testing/QATestingOverview.tsx b/src/routes/get-started/qa-testing/QATestingOverview.tsx index 33d4d5b3f..d66474a73 100644 --- a/src/routes/get-started/qa-testing/QATestingOverview.tsx +++ b/src/routes/get-started/qa-testing/QATestingOverview.tsx @@ -8,7 +8,7 @@ export default function QATestingOverviewPage() { QA Testing - + Outline of the testing procedure for the DDD design system. The procedure ensures that all components function correctly and integrate seamlessly within DDD products. diff --git a/src/routes/home.tsx b/src/routes/home.tsx index 777be2c42..ad45ba89b 100644 --- a/src/routes/home.tsx +++ b/src/routes/home.tsx @@ -80,7 +80,7 @@ const HomePage = () => {
- Start by using the design system in your service + Start by using the design system in your service Use the existing components and patterns in the design system to save time and build off of the current standard. Typically, these cover around 80% of your service's needs. @@ -103,8 +103,8 @@ const HomePage = () => { heading="What happens when I need a new or different component or pattern?" headingSize="medium" > - - If a component or pattern doesn’t exists in the design system or doesn’t meet the needs of your users, + + If a component or pattern doesn't exists in the design system or doesn't meet the needs of your users, follow the process below: @@ -135,10 +135,10 @@ const HomePage = () => { Additional resources - + Common capabilities: Shared digital services - + A directory of reusable backend services designed to help you and your team work more efficiently and align to government infrastructure standards. @@ -152,10 +152,10 @@ const HomePage = () => { - + User Experience best practices - + These resources establish best practices to shape and guide the work of DDD user experience designers. From 6758147cc051d4fdb20774a2cc738ed198cdf059 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 13 Aug 2025 14:51:10 -0600 Subject: [PATCH 10/35] feat(#2127): button group - added examples --- .../button-group/ButtonGroupExamples.tsx | 28 + src/examples/compact-button-group.tsx | 172 +++ src/examples/multiple-actions-in-a-table.tsx | 1193 +++++++++++++++++ src/routes/components/ButtonGroup.tsx | 6 +- 4 files changed, 1396 insertions(+), 3 deletions(-) create mode 100644 src/examples/button-group/ButtonGroupExamples.tsx create mode 100644 src/examples/compact-button-group.tsx create mode 100644 src/examples/multiple-actions-in-a-table.tsx diff --git a/src/examples/button-group/ButtonGroupExamples.tsx b/src/examples/button-group/ButtonGroupExamples.tsx new file mode 100644 index 000000000..0c2e6d905 --- /dev/null +++ b/src/examples/button-group/ButtonGroupExamples.tsx @@ -0,0 +1,28 @@ +import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; +import MultipleActionsinATable from "@examples/multiple-actions-in-a-table.tsx"; +import RemoveAFilter from "@examples/require-user-action-before-continuing.tsx"; +import CompactButtonGroup from "@examples/compact-button-group.tsx"; + +export const ButtonGroupExamples = () => { + + return <> + {/*Button Group Example 1*/} + + + + + {/*Button Group example 2*/} + + + + + {/*Button Group example 3*/} + + + + + ; +}; diff --git a/src/examples/compact-button-group.tsx b/src/examples/compact-button-group.tsx new file mode 100644 index 000000000..166e2f971 --- /dev/null +++ b/src/examples/compact-button-group.tsx @@ -0,0 +1,172 @@ +import { useContext } from "react"; +import { Sandbox } from "@components/sandbox"; +import { GoabButtonGroup, GoabButton } from "@abgov/react-components"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet"; + +function onClick() { + console.log('clicked'); +} + +export const CompactButtonGroup = () => { + const { version } = useContext(LanguageVersionContext); + + return ( + + + {version === "old" && ( + + )} + + {version === "old" && ( + + + Button + + + Button + + + Button + + + `} + /> + )} + + {version === "new" && ( + + )} + + {version === "new" && ( + + + Button + + + Button + + + Button + + + `} + /> + )} + + {version === "old" && ( + + )} + + {version === "old" && ( + + + Button + + + Button + + + Button + + + `} + /> + )} + + {version === "new" && ( + + )} + + {version === "new" && ( + + + Button + + + Button + + + Button + + + `} + /> + )} + + + + Button + + + Button + + + Button + + + + ) +} + +export default CompactButtonGroup; diff --git a/src/examples/multiple-actions-in-a-table.tsx b/src/examples/multiple-actions-in-a-table.tsx new file mode 100644 index 000000000..161deea0b --- /dev/null +++ b/src/examples/multiple-actions-in-a-table.tsx @@ -0,0 +1,1193 @@ +import { + GoabBadge, + GoabBlock, + GoabButton, + GoabButtonGroup, + GoabDropdown, + GoabDropdownItem, + GoabPagination, + GoabTable, + GoabSpacer, +} from "@abgov/react-components"; +import { Sandbox } from "@components/sandbox"; +import { GoabBadgeType } from "@abgov/ui-components-common"; +import { useContext, useEffect, useState } from "react"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { GoabDropdownOnChangeDetail } from "@abgov/ui-components-common"; + +interface User { + badgeType: string; + status: string; + name: string; + text: string; + number: number; +} + +export default function MultipleActionsinATable() { + const { version } = useContext(LanguageVersionContext); + const [users, setUsers] = useState([]); + const [pageUsers, setPageUsers] = useState([]); + const [page, setPage] = useState(1); + const [perPage, setPerPage] = useState(5); + + useEffect(() => { + const _users: User[] = [ + { + badgeType: "success", + status: "Approved", + name:"1", + text: "Ralph Edwards", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"2", + text: "Devon Lane", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"3", + text: "Marvin McKinney", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"4", + text: "Albert Flores", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"5", + text: "Ronald Richards", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"6", + text: "Diane Russell", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"7", + text: "Raoul Emmerich", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"8", + text: "Delilah Farrell", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"9", + text: "Brock Sipes", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"10", + text: "Aylin Hansen", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"11", + text: "Eldora Waters", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"12", + text: "Guillermo Kohler", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"13", + text: "Ryley Medhurst", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"14", + text: "Craig Russel", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"15", + text: "Scot Hayes", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"16", + text: "Albert Flores", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"17", + text: "Amiya Langosh", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"18", + text: "Demetrius Cormier", + number: 1234567890, + }, + ]; + setUsers(_users); + setPageUsers(_users.slice(0, perPage)); + }, [perPage]); + + function changePage(newPage: number) { + const offset = (newPage - 1) * (perPage); + const _users = users.slice(offset, offset + perPage); + setPage(newPage); + setPageUsers(_users); + } + + function handlePerPageCountChangeEvent(event: GoabDropdownOnChangeDetail) { + const perPageValue = parseInt(event.value || '1'); + setPage(1); + setPerPage(perPageValue); + const _users = users.slice(0, perPageValue); + setPageUsers(_users); + } + + return ( + <> + + + {version === "old" && ( + ([]); + const [pageUsers, setPageUsers] = useState([]); + const [page, setPage] = useState(1); + const [perPage, setPerPage] = useState(5); + + useEffect(() => { + const _users: User[] = [ + { + badgeType: "success", + status: "Approved", + name:"1", + text: "Ralph Edwards", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"2", + text: "Devon Lane", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"3", + text: "Marvin McKinney", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"4", + text: "Albert Flores", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"5", + text: "Ronald Richards", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"6", + text: "Diane Russell", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"7", + text: "Raoul Emmerich", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"8", + text: "Delilah Farrell", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"9", + text: "Brock Sipes", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"10", + text: "Aylin Hansen", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"11", + text: "Eldora Waters", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"12", + text: "Guillermo Kohler", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"13", + text: "Ryley Medhurst", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"14", + text: "Craig Russel", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"15", + text: "Scot Hayes", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"16", + text: "Albert Flores", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"17", + text: "Amiya Langosh", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"18", + text: "Demetrius Cormier", + number: 1234567890, + }, + ]; + setUsers(_users); + setPageUsers(_users.slice(0, perPage)); + }, [perPage]); + + function changePage(newPage: number) { + const offset = (newPage - 1) * (perPage); + const _users = users.slice(offset, offset + perPage); + setPage(newPage); + setPageUsers(_users); + } + + function handlePerPageCountChangeEvent(name: string, value: string | string[]) { + const perPageValue = Array.isArray(value) ? parseInt(value[0]) : parseInt(value); + setPage(1); + setPerPage(perPageValue); + const _users = users.slice(0, perPageValue); + setPageUsers(_users); + } + `} + /> + )} + + {version === "old" && ( + + + + Status + Name + File number + + + + + {pageUsers.map(user => ( + + + {user.text} + {user.number} + + + + Edit + + + Test + + + View + + + + + ))} + + + + + + Show + + + + + + of {users.length} + + + + changePage(event.page)} + variant="links-only" + /> + + `} + /> + )} + + {version === "new" && ( + ([]); + const [pageUsers, setPageUsers] = useState([]); + const [page, setPage] = useState(1); + const [perPage, setPerPage] = useState(5); + + useEffect(() => { + const _users: User[] = [ + { + badgeType: "success", + status: "Approved", + name:"1", + text: "Ralph Edwards", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"2", + text: "Devon Lane", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"3", + text: "Marvin McKinney", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"4", + text: "Albert Flores", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"5", + text: "Ronald Richards", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"6", + text: "Diane Russell", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"7", + text: "Raoul Emmerich", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"8", + text: "Delilah Farrell", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"9", + text: "Brock Sipes", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"10", + text: "Aylin Hansen", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"11", + text: "Eldora Waters", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"12", + text: "Guillermo Kohler", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"13", + text: "Ryley Medhurst", + number: 1234567890, + }, + { + badgeType: "emergency", + status: "Denied", + name:"14", + text: "Craig Russel", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"15", + text: "Scot Hayes", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"16", + text: "Albert Flores", + number: 1234567890, + }, + { + badgeType: "success", + status: "Approved", + name:"17", + text: "Amiya Langosh", + number: 1234567890, + }, + { + badgeType: "midtone", + status: "In progress", + name:"18", + text: "Demetrius Cormier", + number: 1234567890, + }, + ]; + setUsers(_users); + setPageUsers(_users.slice(0, perPage)); + }, [perPage]); + + function changePage(newPage: number) { + const offset = (newPage - 1) * (perPage); + const _users = users.slice(offset, offset + perPage); + setPage(newPage); + setPageUsers(_users); + } + + function handlePerPageCountChangeEvent(event: GoabDropdownOnChangeDetail) { + const perPageValue = parseInt(event.value || '1'); + setPage(1); + setPerPage(perPageValue); + const _users = users.slice(0, perPageValue); + setPageUsers(_users); + } + `} + /> + )} + + {version === "new" && ( + + + + Status + Name + File number + + + + + {pageUsers.map(user => ( + + + {user.text} + {user.number} + + + + Edit + + + Test + + + View + + + + + ))} + + + + + + Show + + + + + + of {users.length} + + + + changePage(event.page)} + variant="links-only" + /> + + `} + /> + )} + + {version === "old" && ( + + )} + + {version === "old" && ( + + + + Status + Name + File number + + + + + {pageUsers.map(user => ( + + + {{ user.text }} + {{ user.number }} + + + + Edit + + + Test + + + View + + + + + ))} + + + + + + Show + + + + + + of {{ this.users.length }} + + + + + + `} + /> + )} + + {version === "new" && ( + + )} + + {version === "new" && ( + + + + Status + Name + File number + + + + + {pageUsers.map(user => ( + + + {{ user.text }} + {{ user.number }} + + + + Edit + + + Test + + + View + + + + + ))} + + + + + + Show + + + + + + of {{ this.users.length }} + + + + + + `} + /> + )} + + + + + + + Status + Name + File number + + + + + {pageUsers.map(user => ( + + + {user.text} + {user.number} + + + + Edit + + + Test + + + View + + + + + ))} + + + + + + Show + + + + + + of {users.length} + + + + changePage(event.page)} + variant="links-only" + /> + + + + ); +} + \ No newline at end of file diff --git a/src/routes/components/ButtonGroup.tsx b/src/routes/components/ButtonGroup.tsx index 056b0cc13..4ee4ffedd 100644 --- a/src/routes/components/ButtonGroup.tsx +++ b/src/routes/components/ButtonGroup.tsx @@ -11,7 +11,7 @@ import { GoabButtonGroupAlignment } from "@abgov/ui-components-common"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; import { DesignEmpty } from "@components/empty-states/design-empty/DesignEmpty.tsx"; import { AccessibilityEmpty } from "@components/empty-states/accessibility-empty/AccessibilityEmpty.tsx"; -import { ExamplesEmpty } from "@components/empty-states/examples-empty/ExamplesEmpty.tsx"; +import { ButtonGroupExamples } from "@examples/button-group/ButtonGroupExamples.tsx"; const FIGMA_LINK = "https://www.figma.com/design/3pb2IK8s2QUqWieH79KdN7/%E2%9D%96-Component-library-%7C-DDD?node-id=27301-302108"; @@ -156,11 +156,11 @@ export default function ButtonGroupPage() { heading={ <> Examples - + } > - + From 8977e161ec6deeb22e5f180d6b70b1aa40e346b8 Mon Sep 17 00:00:00 2001 From: Benji Franck Date: Mon, 11 Aug 2025 15:26:33 -0600 Subject: [PATCH 11/35] Chore(#2966): Add initial Copilot instructions --- .github/copilot-instructions.md | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..3b67e0c47 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,37 @@ +# Project Overview +This project contains the public documentation for the Government of Alberta's Design System. + +## Libraries and Frameworks +- The site is built with React components from the Government of Alberta's UI Components library. + +## Folder Structure +- `src/routes/home.tsx`: The home page. +- `src/routes/get-started`: The pages for starting with the design system. +- `src/routes/examples/ExamplesOverview.tsx`: The page listing all examples. +- `src/examples`: Examples of patterns, pages, tasks, component configurations, flows, and more. +- `src/routes/components/AllComponents.tsx`: The page listing all components. +- `src/routes/components`: The pages for each UI component. +- `src/routes/design-tokens`: The pages for design tokens. +- `src/routes/foundations`: The pages for design foundations. + +## Component versions +- Documentation for the most recent version of components are shown with `version === "new"`. +- Documentation for old Long-Term Support (LTS) components are shown with `version === "old"`. + +## Commits & Pull Requests +- Use Conventional Commits format for commit messages. +- Use the present tense. +- Use the imperative mood. +- Limit the first line to 72 characters or less. +- Start the commit message with a reference to the GitHub Issue number, such as `feat(#1234):` +- If the commit relates to an issue, include "Closes #ISSUE_NUMBER" in the commit message. +- If the commit relates to a breaking change, include "BREAKING CHANGE:" in the commit message. + +## Pull Requests +- Only add a single commit to a Pull Request. +- Start the Pull Request title with a reference to the GitHub Issue number, such as `feat(#1234):` + +## CSS and Design Tokens +- Use CSS custom properties that are defined by our design tokens. +- Name custom properties for global styles in this format: `--goa-[category]-[name]`, such as `--goa-color-primary`. +- Name custom properties for component-specific styles in this format: `--goa-[component]-[category]-[name]`. From 6d66863bd59642af5d0d927c2339289c39ebbb55 Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 14 Aug 2025 13:12:54 -0600 Subject: [PATCH 12/35] feat(#2140): microsite header - removed "span" tags to center version text. --- src/examples/show-version-number.tsx | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/examples/show-version-number.tsx b/src/examples/show-version-number.tsx index a494e5c12..f75609233 100644 --- a/src/examples/show-version-number.tsx +++ b/src/examples/show-version-number.tsx @@ -18,9 +18,7 @@ export default function ShowVersionNumberExample() { allowCopy={true} code={` -
- v1.23 -
+
v1.23
`} />} @@ -32,9 +30,7 @@ export default function ShowVersionNumberExample() { allowCopy={true} code={` -
- v1.23 -
+
v1.23
`} />} @@ -47,7 +43,7 @@ export default function ShowVersionNumberExample() { code={` v1.23} + version="v1.23" > `} />} @@ -60,7 +56,7 @@ export default function ShowVersionNumberExample() { code={` v1.23} + version="v1.23" > `} />} @@ -68,7 +64,7 @@ export default function ShowVersionNumberExample() { {/* ...React + Angular code snippets here (same as original)... */} v1.23} + version="v1.23" /> From 1468014a54aafe80cf6743d8ce289a6f97ae50e7 Mon Sep 17 00:00:00 2001 From: Benji Franck Date: Thu, 14 Aug 2025 15:08:32 -0600 Subject: [PATCH 13/35] fix(#2801): fix Angular LTS initial tab example --- src/examples/set-a-specific-tab-to-be-active.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/set-a-specific-tab-to-be-active.tsx b/src/examples/set-a-specific-tab-to-be-active.tsx index c910cbcb9..3f005b8d3 100644 --- a/src/examples/set-a-specific-tab-to-be-active.tsx +++ b/src/examples/set-a-specific-tab-to-be-active.tsx @@ -113,7 +113,7 @@ export const SetASpecificTabToBeActive = () => { tags="angular" allowCopy={true} code={` - +
All
From e9930b40d0ea893fb87f913d2f34765209690116 Mon Sep 17 00:00:00 2001 From: Thomas Jeffery Date: Thu, 14 Aug 2025 17:48:41 -0600 Subject: [PATCH 14/35] Move reveal components to new directory structure and fix imports --- AI_INSTRUCTIONS.md | 511 ++++++++++++++++++ CLAUDE.md | 177 ++++++ .../CheckboxRevealSlotExample.tsx} | 0 .../RadioRevealSlotExample.tsx} | 0 .../reveal-input-based-on-a-selection.tsx | 8 +- 5 files changed, 692 insertions(+), 4 deletions(-) create mode 100644 AI_INSTRUCTIONS.md create mode 100644 CLAUDE.md rename src/examples/{reveal-checkbox-input-based-on-selection.tsx => checkbox/CheckboxRevealSlotExample.tsx} (100%) rename src/examples/{reveal-radio-input-based-on-selection.tsx => radio/RadioRevealSlotExample.tsx} (100%) diff --git a/AI_INSTRUCTIONS.md b/AI_INSTRUCTIONS.md new file mode 100644 index 000000000..b847800e4 --- /dev/null +++ b/AI_INSTRUCTIONS.md @@ -0,0 +1,511 @@ +# AI Instructions for GoA Design System Website Updates + +This document provides comprehensive instructions for AI assistants working on the GoA Design System documentation website (`ui-components-docs`). Understanding this architecture is critical for making safe, effective changes. + +## Table of Contents +1. [Project Overview](#project-overview) +2. [GoabText Spacing System](#goabtext-spacing-system) +3. [Website Architecture](#website-architecture) +4. [Version & Framework System](#version--framework-system) +5. [Component Property Documentation](#component-property-documentation) +6. [Spacing Patterns by Page Type](#spacing-patterns-by-page-type) +7. [Development Workflow](#development-workflow) +8. [Areas Requiring Special Care](#areas-requiring-special-care) +9. [Common Tasks & Guidelines](#common-tasks--guidelines) +10. [Quality Assurance](#quality-assurance) + +## Project Overview + +### Technology Stack +- **Framework**: React 18.2.0 + TypeScript + Vite +- **Design System**: `@abgov/react-components` v6.6.1, `@abgov/web-components` v1.36.1 +- **Routing**: React Router v6.13.0 +- **Styling**: CSS Modules + Design System components + +### Key Architecture Principles +- **Dynamic Content**: Much content is GitHub-sourced and version-dependent +- **Multi-Version Support**: 4 versions (LTS/Latest × React/Angular) +- **Component Reuse**: Examples shared between individual pages and component documentation +- **Semantic HTML**: Always use proper heading hierarchy with `tag` prop +- **Default-First Design**: GoabText has intelligent defaults, override only when needed + +## GoabText Spacing System (CURRENT) + +### Understanding the Philosophy +GoabText now has **built-in default margins** that provide good starting values for most scenarios. The defaults ensure text never gets cramped and creates proper visual hierarchy automatically. + +### Default Spacing Values + +**Default Top Margins by Size:** +- `heading-xl`: `2XL` +- `heading-l`: `2XL` +- `heading-m`: `2XL` +- `heading-s`: `XL` +- `heading-xs`: `XL` +- `body-l`: `2XL` +- `body-m`: `L` +- `body-s`: `L` +- `body-xs`: `S` + +**Default Bottom Margins by Size:** +- `heading-xl`: `L` +- `heading-l`: `L` +- `heading-m`: `M` +- `heading-s`: `S` +- `heading-xs`: `XS` +- `body-l`: `L` +- `body-m`: `L` +- `body-s`: `L` +- `body-xs`: `L` + +### When to Override Defaults +- **Connected Content**: Use `mt="none"` when content should flow directly from previous element +- **Container Boundaries**: Use `mt="none"` or `mb="none"` at container edges for alignment +- **Custom Relationships**: Override with specific values when design requires different spacing +- **Legacy Cleanup**: Remove explicit margins that now duplicate the new defaults + +### Semantic HTML Requirements +**Always use proper semantic tags with the `tag` prop:** +```tsx +// ✅ CORRECT: Semantic h1 with visual flexibility +Page Title + +// ❌ WRONG: Missing semantic meaning +Page Title + +// ❌ WRONG: Raw HTML instead of GoabText +

Page Title

+``` + +## Website Architecture + +### Main Route Structure +``` +src/routes/ +├── home.tsx # Landing page +├── get-started/ # Onboarding content +│ ├── GetStartedOverview.tsx +│ ├── developers/ # Developer guides +│ ├── designers/ # Designer resources +│ └── qa-testing/ # QA testing guides +├── foundations/ # Design principles (safe for systematic changes) +│ ├── Accessibility.tsx +│ ├── Color.tsx +│ ├── Typography.tsx +│ └── [other foundation pages] +├── components/ # Component documentation (REQUIRES MANUAL REVIEW) +├── examples/ # Usage patterns (REQUIRES MANUAL REVIEW) +└── design-tokens/ # Design token documentation (safe for systematic changes) + ├── color/ + ├── spacing/ + └── [other token pages] +``` + +### Key Shared Components +- **ComponentContent**: Wrapper for consistent page structure with table of contents +- **CardLite**: Reusable navigation cards used throughout the site +- **AccessibilityEmpty**: Shared accessibility guidance component +- **Sandbox**: Interactive component playground (components section only) +- **ExamplePageTemplate**: Dynamic template for individual example pages + +### Content Sources +- **Static Content**: Foundations, Get Started, Design Tokens (manually maintained) +- **GitHub-Sourced Metadata**: Component and example descriptions, status, links +- **Dynamic Templates**: Examples and component pages use template systems +- **Shared Examples**: Individual example components reused across contexts + +## Version & Framework System + +### Four-Version Architecture +The website supports **4 distinct versions** of code examples: +1. **LTS/React** (`version === "old"`, `tags="react"`) +2. **Latest/React** (`version === "new"`, `tags="react"`) +3. **LTS/Angular** (`version === "old"`, `tags="angular"`) +4. **Latest/Angular** (`version === "new"`, `tags="angular"`) + +### Version Context Usage +```tsx +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +const {version, language} = useContext(LanguageVersionContext); + +// Conditional rendering based on version +{version === "new" && } +{version === "old" && } + +// Framework-specific content +tags="react" +tags="angular" +tags={["angular", "reactive"]} // Angular reactive forms +tags={["angular", "template-driven"]} // Angular template-driven forms +``` + +### Component Naming Differences +- **LTS**: `GoA` prefix, `goa-` HTML tags, `(_click)` events +- **Latest**: `Goab` prefix, `goab-` HTML tags, `(onClick)` events + +### Example Structure Requirements +Examples must support all 4 versions: +```tsx +export const ExampleComponent = () => { + const {version} = useContext(LanguageVersionContext); + + return ( + + {/* Visual demo that works across all versions */} + Demo Button + + {/* Version-specific React code */} + {version === "old" && `} />} + {version === "new" && `} />} + + {/* Version-specific Angular code */} + {version === "old" && `} />} + {version === "new" && `} />} + + ); +}; +``` + +## Component Property Documentation + +### Documentation Flow +1. **Type Definitions** → `ui-components/libs/common/src/lib/common.ts` +2. **React Interface** → `ui-components/libs/react-components/src/lib/[component]/[component].tsx` +3. **Documentation Props** → `ui-components-docs/src/routes/components/[Component].tsx` + +### ComponentProperty Structure +```tsx +export type ComponentProperty = { + name: string; // Property name + type?: string | string[]; // TypeScript type + inline union values + lang?: "react" | "angular"; // Framework-specific props + required?: boolean; // Required property flag + description?: string; // Human-readable description + defaultValue?: string; // Default value if any + badge?: { content: string; type: GoabBadgeType }; // Special badges +}; +``` + +### Property Documentation Patterns +```tsx +// Component-specific properties +const componentProperties: ComponentProperty[] = [ + { + name: "type", + type: "GoabButtonType (primary | submit | secondary | tertiary | start)", + description: "Sets the type of button.", + defaultValue: "primary", + }, + // Framework-specific variations + { + name: "leadingIcon", + type: "GoabIconType", + lang: "react", + description: "Shows an icon to the left of the text.", + }, + { + name: "leadingicon", // lowercase for Angular + type: "GoabIconType", + lang: "angular", + description: "Shows an icon to the left of the text.", + }, + // Shared properties (reuse these) + TestIdProperty, // From common-properties.ts + MarginProperty, // From common-properties.ts +]; + +// Legacy version properties +const oldComponentProperties: ComponentProperty[] = [ + // Properties for LTS version +]; +``` + +### Version & Framework Filtering +The `ComponentProperties` component automatically: +- Filters properties by framework (React vs Angular) +- Filters properties by version (LTS vs Latest) +- Displays context-appropriate properties + +### Updating Component Properties +When updating component documentation: +1. **Check type definitions** in `common.ts` first +2. **Update React interface** if needed +3. **Update documentation arrays** to match +4. **Use shared properties** from `common-properties.ts` when possible +5. **Maintain version differences** between old/new property arrays + +## Spacing Patterns by Page Type + +### Standard Page Pattern (Foundations, Get Started, Design Tokens) +```tsx +Page Title +Introduction paragraph explaining the page content. +``` +- **Title**: Uses default `2XL` top + `L` bottom margins +- **Introduction**: Uses `mt="none"` to connect to title, default bottom margin + +### Subsection Pages with Category Labels +**Get Started Developer/Designer/QA pages:** +```tsx +Developers +Specific Page Title +Introduction paragraph +``` + +**Foundation Pages with Content Guidelines/Style Guide:** +```tsx +Content guidelines {/* or "Style guide" */} +Page Title +Introduction paragraph +``` + +**Foundation Category Assignment:** +- **Content Guidelines**: ErrorMessages, HelperText, DateFormat, Capitalization +- **Style Guide**: Color, Iconography, Photography, Logo, Typography, Layout + +### Design Token Pages +```tsx +Token Name +``` +- **Critical**: Never use `

` tags - always use `GoabText` with `tag="h1"` +- Let defaults handle all spacing + +### Container Spacing Rules +When GoabText is inside GoabContainer: +- **First element**: Consider `mt="none"` for edge alignment +- **Last element**: Consider `mb="none"` for edge alignment +- **Important**: Only override when visual alignment requires it + +## Development Workflow + +### Before Making Changes +1. **Always read files first** before editing to understand current structure +2. **Check for double spacing** caused by explicit margins + new defaults +3. **Test with defaults first** - only override when content relationships require it +4. **Understand page context** - different sections have different patterns + +### Development Commands +```bash +npm run dev # Start development server +npm run build # Build for production +npm run lint # Run ESLint +npm run prettier # Format code +npm run make:route # Create new route (script available) +``` + +### File Reading Requirements +- **Always read existing files** before making changes +- **Check imports and dependencies** to understand component usage +- **Verify spacing patterns** match established hierarchy +- **Look for `

` tags** that should be converted to `GoabText` with `tag="h1"` + +## Areas Requiring Special Care + +### Safe for Systematic Changes +- **Foundations section** (`src/routes/foundations/`) - Static content pages +- **Get Started section** (`src/routes/get-started/`) - Onboarding content +- **Design Tokens section** (`src/routes/design-tokens/`) - Token documentation +- **Home page** (`src/routes/home.tsx`) - Landing page content + +### Requires Manual Review (DO NOT APPLY SYSTEMATIC CHANGES) +- **Examples section** (`src/routes/examples/`, `src/examples/`) + - Dynamic template system + - GitHub integration + - 4-version code snippet requirements + - Shared components with specific layout needs +- **Components section** (`src/routes/components/`) + - Interactive sandboxes + - Property documentation tables + - Version-specific functionality + - Technical content with different hierarchy needs + +### Example Section Complexity +- **ExamplePageTemplate** dynamically imports examples based on URL slug +- **Individual examples** reused across multiple component documentation pages +- **Sandbox components** have specific spacing needs for interactive functionality +- **Version switching** affects code snippet display throughout examples +- **GitHub metadata** drives descriptions, tags, and status - don't edit manually + +## Common Tasks & Guidelines + +### Converting HTML Tags to GoabText +```tsx +// ❌ BEFORE: Raw HTML +

Page Title

+ +// ✅ AFTER: Semantic GoabText +Page Title +``` + +### Fixing Double Spacing Issues +```tsx +// ❌ BEFORE: Double spacing (explicit + defaults) +Title + +// ✅ AFTER: Trust defaults, override relationships +Title +Connected introduction +``` + +### Adding New Component Properties +1. **Define types** in `ui-components/libs/common/src/lib/common.ts` +2. **Add to React interface** in component file +3. **Update documentation** in component page: +```tsx +const componentProperties: ComponentProperty[] = [ + { + name: "newProp", + type: "NewPropType (value1 | value2)", + description: "Description of the new property.", + defaultValue: "value1", + }, + // ... existing props +]; +``` + +### Creating New Examples +Examples must support 4 versions and be reusable: +```tsx +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const NewExample = () => { + const {version} = useContext(LanguageVersionContext); + + return ( + + {/* Interactive demo */} + + + {/* 4 version-specific code snippets */} + {version === "old" && } + {version === "new" && } + {version === "old" && } + {version === "new" && } + + ); +}; +``` + +### Updating Foundation Pages +Most foundation pages need subtitle categorization: +```tsx +// Add appropriate subtitle +Content guidelines // or "Style guide" +Page Title +Introduction paragraph +``` + +### Working with Shared Components +- **CardLite**: Used for navigation cards throughout site +- **AccessibilityEmpty**: Common accessibility guidance (has specific spacing requirements) +- **ComponentContent**: Page wrapper with TOC support +- Changes to shared components affect multiple pages + +## Quality Assurance + +### Visual Hierarchy Checklist +- [ ] Page titles use `tag="h1"` with `size="heading-xl"` +- [ ] Introduction text uses `size="body-l"` with `mt="none"` when following titles +- [ ] Section headings follow proper hierarchy (h2, h3, etc.) +- [ ] Spacing creates clear content flow without excessive gaps +- [ ] Container boundaries align properly + +### Technical Checklist +- [ ] No raw `

` tags (use `GoabText` with `tag="h1"`) +- [ ] Proper subtitle patterns on Foundation and Get Started pages +- [ ] Container spacing rules applied correctly when needed +- [ ] Component imports are correct +- [ ] No double spacing from explicit margins + defaults + +### Content Relationship Checklist +- [ ] Connected content uses `mt="none"` appropriately +- [ ] Section breaks have adequate separation (defaults usually sufficient) +- [ ] Related content appears visually connected +- [ ] Unrelated content has clear separation + +### Version System Checklist (Examples/Components) +- [ ] 4 code versions supported (LTS/Latest × React/Angular) +- [ ] Proper version context usage (`version === "new"` vs `version === "old"`) +- [ ] Correct component prefixes (`GoA` vs `Goab`) +- [ ] Appropriate framework tags on code snippets +- [ ] Interactive demos work across all versions + +### Component Property Checklist +- [ ] Type definitions exist in `common.ts` +- [ ] React interface matches documentation +- [ ] Property arrays include all interface properties +- [ ] Shared properties reused from `common-properties.ts` +- [ ] Version differences properly documented +- [ ] Framework-specific properties handled correctly + +## Error Prevention + +### Common Mistakes to Avoid +1. **Don't add explicit margins** unless overriding defaults for content relationships +2. **Don't ignore semantic HTML** - always use `tag` prop for proper heading hierarchy +3. **Don't edit GitHub-sourced metadata** manually +4. **Don't apply systematic changes** to examples/components sections without understanding their complexity +5. **Don't batch update** spacing without testing visual results +6. **Don't assume examples are simple** - they support 4 versions and are reused across contexts + +### Validation Steps +1. **Read and understand existing file structure** before making changes +2. **Test with default spacing first** before adding overrides +3. **Override only for content relationships** that require tighter spacing +4. **Verify semantic heading hierarchy** is maintained +5. **Check spacing on both desktop and mobile** if possible +6. **Ensure changes align with design system principles** + +### When to Stop and Ask +- **Examples section changes** beyond simple content updates +- **Component property changes** that affect TypeScript interfaces +- **New component creation** or major architectural changes +- **Version system modifications** +- **Uncertain about spacing patterns** for specific page types + +## Migration from Legacy Patterns + +### Identifying Legacy Issues +Look for these patterns that may now create excessive spacing: +```tsx +// LEGACY: May create double spacing +Title + +// CURRENT: Trust defaults, override relationships +Title +Connected content +``` + +### Systematic Review Priorities +1. **Page titles and introductions** - Most likely to have excessive spacing +2. **Foundation pages** - Need subtitle categorization and spacing cleanup +3. **Design token pages** - Convert `

` tags to `GoabText` +4. **Container boundaries** - Check for proper edge alignment +5. **Content hierarchies** - Verify proper flow relationships + +## Support & Resources + +### Key Reference Files +- **Current instructions**: `/CLAUDE.md` - Historical context and spacing evolution +- **GoabText implementation**: `ui-components/libs/web-components/src/components/text/Text.svelte` +- **Common properties**: `src/components/component-properties/common-properties.ts` +- **Version constants**: `src/components/version-language-switcher/version-language-constants.ts` + +### Testing Your Changes +1. **Start development server**: `npm run dev` +2. **Navigate to affected pages** and verify spacing +3. **Test version switching** if working with examples/components +4. **Check both desktop and mobile** views when possible +5. **Compare with similar pages** for consistency +6. **Verify semantic HTML** in browser dev tools + +### Getting Help +- **Review existing similar pages** for established patterns +- **Check design system component documentation** for proper usage +- **Test changes in development environment** before assuming they're correct +- **Refer to this document** for spacing standards and architectural understanding + +--- + +**Remember**: This website is a sophisticated, multi-version, GitHub-integrated documentation platform. The GoabText defaults provide excellent starting points - your job is to override intelligently for content relationships and maintain the semantic HTML structure that makes the site accessible and SEO-friendly. Always prioritize user experience and design system principles in your updates. \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..b43bc7116 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,177 @@ +# GoA Design System Website - Development Notes + +This document captures development workflow, historical context, and lessons learned while working on the GoA Design System website. For comprehensive AI guidance, see [AI_INSTRUCTIONS.md](./AI_INSTRUCTIONS.md). + +## Website Structure + +### Main Sections +- **Home**: Landing page with key resources and navigation +- **Get Started**: Onboarding for designers, developers, QA testers +- **Foundations**: Design principles, accessibility, branding, content guidelines +- **Examples**: Common patterns and implementations (requires manual review for changes) +- **Components**: Interactive component documentation (requires manual review for changes) +- **Design Tokens**: Color, spacing, typography tokens + +### Key Architecture Patterns +- Built with React + Vite +- Uses `@abgov/react-components` v6.6.1 and `@abgov/web-components` v1.36.1 +- React Router for navigation with nested routes +- ComponentContent wrapper for consistent page structure + +## GoabText Spacing System Evolution + +### Historical Timeline +1. **Original System**: GoabText had some default margins +2. **v6 Migration Period**: Temporarily changed to `mt="none"` and `mb="none"` defaults, requiring explicit margins +3. **Current System**: GoabText now has intelligent **size-based default margins** that provide good starting values + +### Current Philosophy (2024+) +- **Defaults-first approach**: GoabText has built-in margins based on text size +- **Override when needed**: Use `mt="none"` or `mb="none"` to connect related content +- **Semantic HTML required**: Always use `tag` prop for proper heading hierarchy + +### Design System v4/v6 Changes +- Component prefixes changed: `GoA` → `Goab` (React), `goa-` → `goab-` (Angular) +- Margin properties changed from `string` type to `Spacing` type +- Evolution from explicit margins to intelligent defaults + +## Current Spacing Approach + +### Quick Reference Patterns +```tsx +// Standard page pattern - trust defaults, override relationships +Page Title +Introduction text + +// Pages with category labels +Content guidelines +Page Title +Introduction text + +// Always use semantic tags for accessibility +Section Heading +``` + +### Key Principles +- **Trust the defaults** - GoabText provides good spacing automatically +- **Override for relationships** - Use `mt="none"` to connect related content +- **Semantic HTML always** - Use `tag="h1"`, `tag="h2"`, etc. for accessibility +- **Container boundaries** - Consider edge alignment with `mt="none"` or `mb="none"` + +## Component Usage Insights + +### GoabText Sizing Hierarchy +- `heading-xl`: Main page titles +- `body-l`: Page introductions and important paragraphs +- `heading-m`: Section headings +- `body-m`: Regular content + +### Common Components +- `ComponentContent`: Wrapper with table of contents support +- `GoabDivider`: Section separators with consistent margins +- `CardLite`: Reusable cards for navigation (Foundations, Examples, Components, Design tokens) +- `AccessibilityEmpty`: Common accessibility guidance component used on component pages + - Located at: `src/components/empty-states/accessibility-empty/AccessibilityEmpty.tsx` + - Contains two GoabText elements with specific spacing requirements + +## File Organization + +### Route Structure +``` +src/routes/ +├── home.tsx +├── get-started/ +│ ├── GetStartedLayout.tsx +│ ├── GetStartedOverview.tsx +│ ├── designers/ +│ ├── developers/ +│ └── [other pages] +├── foundations/ +├── examples/ (excluded from systematic changes) +├── components/ (excluded from systematic changes) +└── design-tokens/ +``` + +### Key Files Modified +- Home page: Fixed "Start by using the design system" spacing +- CardLite component: Consistent card heading patterns +- All Get Started pages: Subtitle/title/introduction spacing +- Foundation pages: Introduction text consistency + added subtitles +- Design token pages: Replaced h1 tags with GoabText for consistent spacing +- AccessibilityEmpty component: Adjusted margins for tighter text spacing + +## Development Best Practices + +### Human Developer Workflow +1. **Start development server**: `npm run dev` +2. **Read files first** before making changes to understand structure +3. **Test spacing visually** - the defaults should look good, override only for content relationships +4. **Check semantic HTML** in browser dev tools to verify heading hierarchy +5. **Test responsive behavior** when possible + +### Common Migration Tasks +- **Convert `

` tags**: Replace with `` +- **Remove excessive explicit margins**: Trust defaults, add `mt="none"` for content relationships +- **Add semantic tags**: Ensure proper `tag="h1"`, `tag="h2"` hierarchy +- **Foundation page categorization**: Add "Content guidelines" or "Style guide" subtitles + +### Legacy Pattern Cleanup +Look for these outdated patterns: +```tsx +// ❌ OLD: Explicit margins that now create double spacing +Title + +// ✅ NEW: Trust defaults, override relationships +Title +Connected content +``` + +### Areas Requiring Manual Review +- **Components section**: Interactive sandboxes and version switching +- **Examples section**: 4-version support and GitHub integration + +## Key Learnings from Past Migrations + +1. **Spacing System Evolution**: The progression from explicit margins → no defaults → intelligent defaults taught us the importance of design system consistency +2. **Manual Review Essential**: Automated changes can miss important context about content relationships +3. **Component Interconnections**: Changes to shared components (CardLite, AccessibilityEmpty) affect multiple pages +4. **Version Complexity**: The 4-version system (LTS/Latest × React/Angular) adds significant complexity to examples and components +5. **GitHub Integration**: Dynamic content sourcing means some information should never be manually edited + +## Historical Context + +### Major Migration Periods +- **v4 → v6**: Component prefix changes (`GoA` → `Goab`), margin type system updates +- **Spacing System Updates**: Multiple iterations to find the right balance between automatic spacing and manual control +- **Version System Implementation**: Addition of LTS/Latest support with framework switching +- **GitHub Integration**: Move to dynamic metadata sourcing for examples and components + +### Lessons for Future Changes +- **Test across all page types** before rolling out systematic changes +- **Understand content relationships** before adjusting spacing +- **Preserve semantic HTML** structure for accessibility +- **Document architectural decisions** to prevent future confusion + +## Quick Reference for Developers + +### Development Commands +```bash +npm run dev # Start development server +npm run build # Build for production +npm run lint # Run ESLint +npm run prettier # Format code +``` + +### Safe Areas for Changes +- Foundations section (static content) +- Get Started section (static content) +- Design Tokens section (static content) +- Home page content + +### Areas Requiring Extra Care +- Examples section (dynamic templates, GitHub integration) +- Components section (interactive sandboxes, property tables) + +--- + +**For comprehensive guidance on making changes, see [AI_INSTRUCTIONS.md](./AI_INSTRUCTIONS.md)** \ No newline at end of file diff --git a/src/examples/reveal-checkbox-input-based-on-selection.tsx b/src/examples/checkbox/CheckboxRevealSlotExample.tsx similarity index 100% rename from src/examples/reveal-checkbox-input-based-on-selection.tsx rename to src/examples/checkbox/CheckboxRevealSlotExample.tsx diff --git a/src/examples/reveal-radio-input-based-on-selection.tsx b/src/examples/radio/RadioRevealSlotExample.tsx similarity index 100% rename from src/examples/reveal-radio-input-based-on-selection.tsx rename to src/examples/radio/RadioRevealSlotExample.tsx diff --git a/src/examples/reveal-input-based-on-a-selection.tsx b/src/examples/reveal-input-based-on-a-selection.tsx index 42c0d09b3..c208d1994 100644 --- a/src/examples/reveal-input-based-on-a-selection.tsx +++ b/src/examples/reveal-input-based-on-a-selection.tsx @@ -1,6 +1,6 @@ -import { RevealRadioInputBasedOnSelection } from "@examples/reveal-radio-input-based-on-selection.tsx"; +import { RadioRevealSlotExample } from "@examples/radio/RadioRevealSlotExample.tsx"; import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; -import { RevealCheckboxInputBasedOnSelection } from "@examples/reveal-checkbox-input-based-on-selection.tsx"; +import { CheckboxRevealSlotExample } from "@examples/checkbox/CheckboxRevealSlotExample.tsx"; export default function RevealInputBasedOnASelection() { @@ -10,13 +10,13 @@ export default function RevealInputBasedOnASelection() { exampleTitle="Reveal a checkbox input based on a selection" figmaExample="https://www.figma.com/design/aIRjvBzpIUH0GbkffjbL04/%E2%9D%96-Patterns-library-%7C-DDD?node-id=6307-131333&t=i24jD5GZOelxxzSN-4"> - + - + ); } \ No newline at end of file From 7b7b5ecd55305c868d2a92a3cc27af8947090e93 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 15 Aug 2025 10:52:50 -0600 Subject: [PATCH 15/35] feat(#2132): drop down - added more contextual examples --- .../basic-question-page-with-a-dropdown.tsx | 202 ++++++++++++++++++ .../choose-one-option-from-a-list.tsx | 120 +++++++++++ src/examples/dropdown/DropdownExamples.tsx | 24 +++ ...-through-long-list-to-choose-an-option.tsx | 150 +++++++++++++ src/routes/components/Dropdown.tsx | 2 +- 5 files changed, 497 insertions(+), 1 deletion(-) create mode 100644 src/examples/basic-question-page-with-a-dropdown.tsx create mode 100644 src/examples/choose-one-option-from-a-list.tsx create mode 100644 src/examples/filter-through-long-list-to-choose-an-option.tsx diff --git a/src/examples/basic-question-page-with-a-dropdown.tsx b/src/examples/basic-question-page-with-a-dropdown.tsx new file mode 100644 index 000000000..5f8f87538 --- /dev/null +++ b/src/examples/basic-question-page-with-a-dropdown.tsx @@ -0,0 +1,202 @@ +import { Sandbox } from "@components/sandbox"; +import "./question-page/question-page-examples.css"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabButton, + GoabFormItem, + GoabDropdown, + GoabDropdownItem +} from "@abgov/react-components"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { useContext } from "react"; + +export default function BasicPageWithDropdown() { + const { version } = useContext(LanguageVersionContext); + return ( +
+ + + {/*CSS Code Snippet*/} + ') center center no-repeat; + } + + a.back-link:visited::before, + a.back-link:hover::before { + background: url('data:image/svg+xml,') center center no-repeat; + } + + a.back-link { + margin-top: var(--goa-space-m); + } + `} + /> + + {/*Angular Code Snippet - need for leadingContent slot*/} + + {version === "old" && + Back + + + + {}} name="province-territory" ariaLabelledBy="provinceLabel"> + + + + + + + + + + + + + + + + + Continue + + `} + />} + + {version === "new" && + Back + + + + {}} name="province-territory" ariaLabelledBy="provinceLabel"> + + + + + + + + + + + + + + + + + Continue + + `} + />} + + {/*React Code Snippet - need for leadingContent slot*/} + {version === "old" && + Back + + + + {}} name="province-territory" ariaLabelledBy="provinceLabel"> + + + + + + + + + + + + + + + + + Continue + + `} + />} + + {version === "new" && + Back + + + + {}} name="province-territory" ariaLabelledBy="provinceLabel"> + + + + + + + + + + + + + + + + + Continue + + `} + />} + + + Back + + + + {}} name="province-territory" ariaLabelledBy="provinceLabel"> + + + + + + + + + + + + + + + + + Continue + + +
+ ); +} diff --git a/src/examples/choose-one-option-from-a-list.tsx b/src/examples/choose-one-option-from-a-list.tsx new file mode 100644 index 000000000..04b21143b --- /dev/null +++ b/src/examples/choose-one-option-from-a-list.tsx @@ -0,0 +1,120 @@ +import { GoabDropdown, GoabDropdownItem, GoabFormItem } from "@abgov/react-components"; +import { useContext } from "react"; +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const ChooseOneOptionFromList = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + return ( + + + + {version === "old" && } + + {version === "old" && + + + + + + + `} + />} + + {version === "new" && + + + + + + + `} + />} + + {version === "old" && } + + {version === "old" && + + + + + + + `} + />} + + {version === "new" && } + + {version === "new" && + + + + + + + `} + />} + + + + + + + + + + ); +} + +export default ChooseOneOptionFromList; diff --git a/src/examples/dropdown/DropdownExamples.tsx b/src/examples/dropdown/DropdownExamples.tsx index b172aa191..e7a47d56b 100644 --- a/src/examples/dropdown/DropdownExamples.tsx +++ b/src/examples/dropdown/DropdownExamples.tsx @@ -2,11 +2,27 @@ import { DynamicallyAddAnItemToADropdownList } from "@examples/dynamically-add-a import { DynamicallyChangeItemsInADropdownList } from "@examples/dynamically-change-items-in-a-dropdown-list.tsx"; +import { FilterItemsInADropdownList } from "@examples/filter-through-long-list-to-choose-an-option.tsx"; +import { ChooseOneOptionFromList } from "@examples/choose-one-option-from-a-list.tsx"; import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; +import BasicPageWithDropdown from "@examples/basic-question-page-with-a-dropdown.tsx"; + export const DropdownExamples = () => { return ( <> + + + + + + + + @@ -18,6 +34,14 @@ export const DropdownExamples = () => { figmaExample=""> + + + + + + ); } diff --git a/src/examples/filter-through-long-list-to-choose-an-option.tsx b/src/examples/filter-through-long-list-to-choose-an-option.tsx new file mode 100644 index 000000000..b6800e4a3 --- /dev/null +++ b/src/examples/filter-through-long-list-to-choose-an-option.tsx @@ -0,0 +1,150 @@ +import { GoabDropdown, GoabDropdownItem, GoabFormItem } from "@abgov/react-components"; +import { useContext } from "react"; +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; + +export const FilterItemsInADropdownList = () => { + const {version} = useContext(LanguageVersionContext); + + return ( + + + + {version === "old" && } + + {version === "old" && + + + + + + + + + + + + + `} + />} + + {version === "new" && + + + + + + + + + + + + + `} + />} + + {version === "old" && } + + {version === "old" && + + + + + + + + + + + + + `} + />} + + {version === "new" && } + + {version === "new" && + + + + + + + + + + + + + `} + />} + + + + + + + + + + + + + + + + ); +} + +export default FilterItemsInADropdownList; diff --git a/src/routes/components/Dropdown.tsx b/src/routes/components/Dropdown.tsx index 160473ab3..af111a26a 100644 --- a/src/routes/components/Dropdown.tsx +++ b/src/routes/components/Dropdown.tsx @@ -426,7 +426,7 @@ export default function DropdownPage() { heading={ <> Examples - + }> From 247dab21a2edd2274b5ede9193b49bd614fcd304 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 19 Aug 2025 15:55:33 -0600 Subject: [PATCH 16/35] feat(#2137): input - added phone number and bank account examples --- src/examples/ask-a-user-for-bank-details.tsx | 197 ++++++++++++++++++ src/examples/enter-a-phone-number.tsx | 113 ++++++++++ src/examples/text-field/TextFieldExamples.tsx | 14 ++ src/routes/components/TextField.tsx | 2 +- 4 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 src/examples/ask-a-user-for-bank-details.tsx create mode 100644 src/examples/enter-a-phone-number.tsx diff --git a/src/examples/ask-a-user-for-bank-details.tsx b/src/examples/ask-a-user-for-bank-details.tsx new file mode 100644 index 000000000..59719ffbc --- /dev/null +++ b/src/examples/ask-a-user-for-bank-details.tsx @@ -0,0 +1,197 @@ +import { Sandbox } from "@components/sandbox"; +import { GoabBlock, GoabFormItem, GoabInput } from "@abgov/react-components"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + +export const AskAUserForBankDetails = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + + return ( + + {/*React code*/} + + {version === "old" && (''); + const [account, setAccount] = useState(''); + const [bank, setBank] = useState(''); + function onChangeName(event: GoabInputOnChangeDetail) { + setName(event.value); + } + function onChangeAccount(event: GoabInputOnChangeDetail) { + setAccount(event.value); + } + function onChangeBank(event: GoabInputOnChangeDetail) { + setBank(event.value); + } + `} + />} + + {version === "old" && + + + + + + + + + + + + + `} + />} + + {version === "new" && (''); + const [account, setAccount] = useState(''); + const [bank, setBank] = useState(''); + function onChangeName(event: GoabInputOnChangeDetail) { + setName(event.value); + } + function onChangeAccount(event: GoabInputOnChangeDetail) { + setAccount(event.value); + } + function onChangeBank(event: GoabInputOnChangeDetail) { + setBank(event.value); + } + `} + />} + {version === "new" && + + + + + + + + + + + + + `} + />} + + {/*Angular code*/} + + {version === "old" && } + + {version === "new" && } + + + + + + + + + + + + + + + + + ) +} + +export default AskAUserForBankDetails; diff --git a/src/examples/enter-a-phone-number.tsx b/src/examples/enter-a-phone-number.tsx new file mode 100644 index 000000000..9ddade987 --- /dev/null +++ b/src/examples/enter-a-phone-number.tsx @@ -0,0 +1,113 @@ +import { GoabBlock, GoabButton, GoabFormItem, GoabInput } from "@abgov/react-components"; +import { Sandbox } from "@components/sandbox"; +import { useContext } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; + +export const EnterAPhoneNumber = () => { + const {version} = useContext(LanguageVersionContext); + const noop = () => {} + return ( + + + {/*Angular code*/} + + {version === "old" && ( + + )} + + {version === "new" && ( + + )} + + {/*React code*/} + + {version === "old" && ( + (""); + function onChangePhoneNumber(event: GoabInputOnChangeDetail) { + setPhoneNumber(event.value); + } + `} + /> + )} + + {version === "old" && ( + + + + `} + /> + )} + + {version === "new" && ( + (""); + function onChangePhoneNumber(event: GoabInputOnChangeDetail) { + setPhoneNumber(event.value); + } + `} + /> + )} + + {version === "new" && ( + + + + `} + /> + )} + +
+ + + +
+
+ ); +} + +export default EnterAPhoneNumber; diff --git a/src/examples/text-field/TextFieldExamples.tsx b/src/examples/text-field/TextFieldExamples.tsx index 94179cc0a..b57696d1f 100644 --- a/src/examples/text-field/TextFieldExamples.tsx +++ b/src/examples/text-field/TextFieldExamples.tsx @@ -7,6 +7,8 @@ import { import { TextFieldRightAlignExample } from "@examples/text-field/TextFieldRightAlignExample.tsx"; import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; import { AskAUserForAnAddress } from "@examples/ask-a-user-for-an-address.tsx"; +import { AskAUserForBankDetails } from "@examples/ask-a-user-for-bank-details.tsx"; +import { EnterAPhoneNumber } from "@examples/enter-a-phone-number.tsx"; export default function TextFieldExamples() { return ( @@ -30,6 +32,12 @@ export default function TextFieldExamples() { + + + + @@ -47,6 +55,12 @@ export default function TextFieldExamples() { figmaExample="https://www.figma.com/design/aIRjvBzpIUH0GbkffjbL04/%E2%9D%96-Patterns-library-%7C-DDD?node-id=1896-179631&t=X0IQW5flDDaj8Vyg-4"> + + + + ); } \ No newline at end of file diff --git a/src/routes/components/TextField.tsx b/src/routes/components/TextField.tsx index bb6d03907..158419268 100644 --- a/src/routes/components/TextField.tsx +++ b/src/routes/components/TextField.tsx @@ -798,7 +798,7 @@ export default function TextFieldPage() { heading={ <> Examples - + }> From f90727b51aecb1866290806e80a1466f83c1f858 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 19 Aug 2025 15:59:50 -0600 Subject: [PATCH 17/35] feat(#2137): input - removed redundant imports --- src/examples/enter-a-phone-number.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/enter-a-phone-number.tsx b/src/examples/enter-a-phone-number.tsx index 9ddade987..b5216d7fe 100644 --- a/src/examples/enter-a-phone-number.tsx +++ b/src/examples/enter-a-phone-number.tsx @@ -1,4 +1,4 @@ -import { GoabBlock, GoabButton, GoabFormItem, GoabInput } from "@abgov/react-components"; +import { GoabFormItem, GoabInput } from "@abgov/react-components"; import { Sandbox } from "@components/sandbox"; import { useContext } from "react"; import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; From 3435e20e337a062a9d929373b7f6c4cca63f6b9c Mon Sep 17 00:00:00 2001 From: Chris Olsen Date: Wed, 20 Aug 2025 12:20:56 -0600 Subject: [PATCH 18/35] fix: update playground script path in docs --- src/routes/get-started/Contribute.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/get-started/Contribute.tsx b/src/routes/get-started/Contribute.tsx index 6db946d4e..cc082cc3e 100644 --- a/src/routes/get-started/Contribute.tsx +++ b/src/routes/get-started/Contribute.tsx @@ -182,7 +182,7 @@ export default function ContributePage() {
  • Run the bash script: - +
  • The commands above will install all necessary packages and create a “playground” folder containing both React and Angular environments. Since nothing in this folder is committed to the repository, you can freely make any changes you want. These environments are designed for testing purposes.
  • From 76bd0f3bd6b070e37afef7e50c083caf0694048e Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 22 Aug 2025 16:14:11 -0600 Subject: [PATCH 19/35] feat(#2126): button - add "compact buttons" example --- src/examples/button/ButtonExamples.tsx | 10 +- src/examples/compact-buttons-in-a-table.tsx | 466 ++++++++++++++++++++ src/routes/components/Button.tsx | 2 +- 3 files changed, 476 insertions(+), 2 deletions(-) create mode 100644 src/examples/compact-buttons-in-a-table.tsx diff --git a/src/examples/button/ButtonExamples.tsx b/src/examples/button/ButtonExamples.tsx index 484468bc7..7b94722e0 100644 --- a/src/examples/button/ButtonExamples.tsx +++ b/src/examples/button/ButtonExamples.tsx @@ -1,6 +1,7 @@ import { AskAUserForAnAddress } from "@examples/ask-a-user-for-an-address.tsx"; import { ConfirmADestructiveAction } from "@examples/confirm-a-destructive-action.tsx"; import { DisabledButtonWithARequiredField } from "@examples/disabled-button-with-a-required-field.tsx"; +import { CompactButtonsInATable } from "@examples/compact-buttons-in-a-table.tsx"; import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; export const ButtonExamples = () => { @@ -20,11 +21,18 @@ export const ButtonExamples = () => { - {/*Button example */} + {/*Button example 3*/} + + {/*Button example 4*/} + + + ; }; diff --git a/src/examples/compact-buttons-in-a-table.tsx b/src/examples/compact-buttons-in-a-table.tsx new file mode 100644 index 000000000..c17eaf4df --- /dev/null +++ b/src/examples/compact-buttons-in-a-table.tsx @@ -0,0 +1,466 @@ +import { Sandbox } from "@components/sandbox"; +import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; +import { + GoabButton, + GoabButtonGroup, + GoabPagination, + GoabTable +} from "@abgov/react-components"; +import { useContext, useEffect, useState } from "react"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { faker } from "@faker-js/faker"; + +interface User { + id: string; + firstName: string; + lastName: string; +} +export const CompactButtonsInATable = () => { + const { version } = useContext(LanguageVersionContext); + const [users, setUsers] = useState([]); + const [pageUsers, setPageUsers] = useState([]); + const [page, setPage] = useState(1); + const [perPage, setPerPage] = useState(10); + const noop = () => {}; + + useEffect(() => { + const _users = []; + for (let i = 1; i <= 100; i++) { + _users.push({ + id: faker.string.uuid(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName() + }); + } + setUsers(_users); + setPageUsers(_users.slice(0, perPage)); + }, [perPage]); + + function changePage(newPage: number) { + const offset = (newPage - 1) * perPage; + const _users = users.slice(offset, offset + perPage); + setPage(newPage); + setPageUsers(_users); + } + + return ( + <> + + + {/*============= React code ==============*/} + {version === "old" && ( + ([]); + const [pageUsers, setPageUsers] = useState([]); + const [page, setPage] = useState(1); + const [perPage, setPerPage] = useState(10); + + useEffect(() => { + const _users = []; + for (let i = 1; i <= 100; i++) { + _users.push({ + id: faker.datatype.uuid(), + firstName: faker.name.firstName(), + lastName: faker.name.lastName() + }); + } + setUsers(_users); + setPageUsers(_users.slice(0, perPage)); + }, [perPage]); + + function changePage(newPage: number) { + const offset = (newPage - 1) * 10; + const _users = users.slice(offset, offset + perPage); + setPage(newPage); + setPageUsers(_users); + } + `} + /> + )} + + {version === "new" && ( + ([]); + const [pageUsers, setPageUsers] = useState([]); + const [page, setPage] = useState(1); + const [perPage, setPerPage] = useState(10); + + useEffect(() => { + const _users = []; + for (let i = 1; i <= 100; i++) { + _users.push({ + id: faker.string.uuid(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName() + }); + } + setUsers(_users); + setPageUsers(_users.slice(0, perPage)); + }, [perPage]); + + function changePage(newPage: number) { + const offset = (newPage - 1) * 10; + const _users = users.slice(offset, offset + perPage); + setPage(newPage); + setPageUsers(_users); + } + + `} + /> + )} + + {version === "old" && ( + + + + First name + Last name + Number + + + + + {pageUsers.map(u => ( + + {u.firstName} + {u.lastName} + 12345667 + + + + View + + + + + ))} + + + + changePage(event.page)} + /> + `} + /> + )} + + {version === "new" && ( + + + + First name + Last name + Number + + + + + {pageUsers.map(u => ( + + {u.firstName} + {u.lastName} + 12345667 + + + + View + + + + + ))} + + + + changePage(event.page)} + /> + `} + /> + )} + + {/*================ Angular code ==================*/} + {version === "old" && ( + + )} + + {version === "new" && ( + + )} + + {version === "old" && ( + + + + First name + Last name + Number + + + + + + {{ user.firstName }} + {{ user.lastName }} + 12345667 + + + + View + + + + + + + + + `} + /> + )} + + {version === "new" && ( + + + + First name + Last name + Number + + + + + + {{ user.firstName }} + {{ user.lastName }} + 12345667 + + + + View + + + + + + + + + `} + /> + )} + + + + + First name + Last name + Number + + + + + {pageUsers.map(u => ( + + {u.firstName} + {u.lastName} + 12345667 + + + + View + + + + + ))} + + + + changePage(event.page)} + /> + + + ); +} + +export default CompactButtonsInATable; \ No newline at end of file diff --git a/src/routes/components/Button.tsx b/src/routes/components/Button.tsx index 2ab63d3d7..df56ee085 100644 --- a/src/routes/components/Button.tsx +++ b/src/routes/components/Button.tsx @@ -248,7 +248,7 @@ export default function ButtonPage() { heading={ <> Examples - + } > From 149054ca20c9322cc3f81a6740d2c27492676c2d Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 22 Aug 2025 16:22:27 -0600 Subject: [PATCH 20/35] feat(#2126): button - fixed error --- src/examples/compact-buttons-in-a-table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/compact-buttons-in-a-table.tsx b/src/examples/compact-buttons-in-a-table.tsx index c17eaf4df..d89a69532 100644 --- a/src/examples/compact-buttons-in-a-table.tsx +++ b/src/examples/compact-buttons-in-a-table.tsx @@ -20,7 +20,7 @@ export const CompactButtonsInATable = () => { const [users, setUsers] = useState([]); const [pageUsers, setPageUsers] = useState([]); const [page, setPage] = useState(1); - const [perPage, setPerPage] = useState(10); + const [perPage] = useState(10); const noop = () => {}; useEffect(() => { From a8030ac2b50a61312fab6b7f03fd7139a887b38f Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 22 Aug 2025 16:25:18 -0600 Subject: [PATCH 21/35] feat(#2126): button - adjusted code samples --- src/examples/compact-buttons-in-a-table.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/examples/compact-buttons-in-a-table.tsx b/src/examples/compact-buttons-in-a-table.tsx index d89a69532..606f73411 100644 --- a/src/examples/compact-buttons-in-a-table.tsx +++ b/src/examples/compact-buttons-in-a-table.tsx @@ -67,7 +67,7 @@ export const CompactButtonsInATable = () => { const [users, setUsers] = useState([]); const [pageUsers, setPageUsers] = useState([]); const [page, setPage] = useState(1); - const [perPage, setPerPage] = useState(10); + const [perPage] = useState(10); useEffect(() => { const _users = []; @@ -111,7 +111,7 @@ export const CompactButtonsInATable = () => { const [users, setUsers] = useState([]); const [pageUsers, setPageUsers] = useState([]); const [page, setPage] = useState(1); - const [perPage, setPerPage] = useState(10); + const [perPage] = useState(10); useEffect(() => { const _users = []; From af17d7fb220e9863c9f0a687a3559ff0820a4960 Mon Sep 17 00:00:00 2001 From: syedszeeshan <47701214+syedszeeshan@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:37:38 -0400 Subject: [PATCH 22/35] fix(#1321): docs button deprecate submit type --- src/routes/components/Button.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/components/Button.tsx b/src/routes/components/Button.tsx index 2ab63d3d7..0f55b05ba 100644 --- a/src/routes/components/Button.tsx +++ b/src/routes/components/Button.tsx @@ -33,7 +33,7 @@ export default function ButtonPage() { label: "Type", type: "list", name: "type", - options: ["primary", "submit", "secondary", "tertiary", "start"], + options: ["primary", "secondary", "tertiary", "start"], value: "", defaultValue: "primary", }, @@ -71,7 +71,7 @@ export default function ButtonPage() { const oldComponentProperties: ComponentProperty[] = [ { name: "type", - type: "primary | submit | secondary | tertiary | start", + type: "primary | secondary | tertiary | start", description: "Sets the type of button.", defaultValue: "primary", }, @@ -140,7 +140,7 @@ export default function ButtonPage() { const componentProperties: ComponentProperty[] = [ { name: "type", - type: "GoabButtonType (primary | submit | secondary | tertiary | start)", + type: "GoabButtonType (primary | secondary | tertiary | start)", description: "Sets the type of button.", defaultValue: "primary", }, From 823bcd909e1c84a25597e1e4e864a02e9e42c399 Mon Sep 17 00:00:00 2001 From: Dustin Nielsen Date: Mon, 25 Aug 2025 18:51:01 -0600 Subject: [PATCH 23/35] fix(#2732): Updating DatePicker component to include type property --- package-lock.json | 16 ++-- package.json | 4 +- src/components/sandbox/Sandbox.tsx | 2 +- src/examples/date-of-birth.tsx | 39 ++++++++++ .../date-picker/DatePickerExamples.tsx | 15 ++++ src/routes/components/DatePicker.tsx | 75 +++++++++++++++---- 6 files changed, 126 insertions(+), 25 deletions(-) create mode 100644 src/examples/date-of-birth.tsx diff --git a/package-lock.json b/package-lock.json index 6586cdaa1..f4f5aa7d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,9 @@ "name": "code-sandbox", "version": "0.0.0", "dependencies": { - "@abgov/react-components": "6.7.0", + "@abgov/react-components": "6.7.1-alpha.1", "@abgov/ui-components-common": "1.7.0", - "@abgov/web-components": "1.37.0", + "@abgov/web-components": "1.37.1-alpha.2", "@faker-js/faker": "^8.3.1", "highlight.js": "^11.8.0", "js-cookie": "^3.0.5", @@ -68,9 +68,9 @@ } }, "node_modules/@abgov/react-components": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@abgov/react-components/-/react-components-6.7.0.tgz", - "integrity": "sha512-/d1pZqnw9PRApQIj6RGeens9pq2XYJVx3b9cwBy5IVKvs9eLyjBsXGsXRJK2Vnl8wjp+CUKIyzFvweYoT0atFQ==", + "version": "6.7.1-alpha.1", + "resolved": "https://registry.npmjs.org/@abgov/react-components/-/react-components-6.7.1-alpha.1.tgz", + "integrity": "sha512-s5+tGLY2DOeMV3BjiIz0c71hESIF/kcWA3PrFxvPCoCuPWiilLL0ktmd9sCRPp5qhcbWtW6M8vuLatwIiD28qQ==", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", @@ -83,9 +83,9 @@ "integrity": "sha512-dnqLxTJdBxNZFKPDyckaHHrkipjFIwXyU63rlEkcHgKhn4d+KrwlbMuxtsS73FvH4bozyQm2OM+sPu32wyWgNA==" }, "node_modules/@abgov/web-components": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@abgov/web-components/-/web-components-1.37.0.tgz", - "integrity": "sha512-GjKoy1G3JlHBc6a4fxS5luYmxCchAXmIrBYecnkq6q3IhdkY1r1McDO8/AB0P2E0gcT1IlOtpGcKKdjDHuxCEw==", + "version": "1.37.1-alpha.2", + "resolved": "https://registry.npmjs.org/@abgov/web-components/-/web-components-1.37.1-alpha.2.tgz", + "integrity": "sha512-WoQZAwccxRPQHWHBS/7gDISCFbEnWrsRZvS8U9iK0N3jr00YTtlvxdwEDywZAcgrXitxa8qlIVbpylZVLzDdmQ==", "peerDependencies": { "@sveltejs/vite-plugin-svelte": "3.x", "glob": "10.x", diff --git a/package.json b/package.json index 9dad8b44f..1660d33b7 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "prettier": "npx prettier . --write" }, "dependencies": { - "@abgov/react-components": "6.7.0", + "@abgov/react-components": "6.7.1-alpha.1", "@abgov/ui-components-common": "1.7.0", - "@abgov/web-components": "1.37.0", + "@abgov/web-components": "1.37.1-alpha.2", "@faker-js/faker": "^8.3.1", "highlight.js": "^11.8.0", "js-cookie": "^3.0.5", diff --git a/src/components/sandbox/Sandbox.tsx b/src/components/sandbox/Sandbox.tsx index afe38e897..f7a89edda 100644 --- a/src/components/sandbox/Sandbox.tsx +++ b/src/components/sandbox/Sandbox.tsx @@ -134,7 +134,7 @@ export const Sandbox = (props: SandboxProps) => { properties={props.formItemProperties} /> )} - +
    { + return ( + + + + + + + + + `} + /> + + + + + `} + /> + + ) +} + +export default DateOfBirth; \ No newline at end of file diff --git a/src/examples/date-picker/DatePickerExamples.tsx b/src/examples/date-picker/DatePickerExamples.tsx index 3829fdfbe..c6ac76f32 100644 --- a/src/examples/date-picker/DatePickerExamples.tsx +++ b/src/examples/date-picker/DatePickerExamples.tsx @@ -1,8 +1,13 @@ import { TodayDatePickerField } from "@examples/choose-a-date.tsx"; import { ResetDatePickerField } from "@examples/reset-date-picker-field.tsx"; +import { DateOfBirth } from "@examples/date-of-birth.tsx"; import { SandboxHeader } from "@components/sandbox/sandbox-header/sandboxHeader.tsx"; +import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; +import { useContext } from "react"; export const DatePickerExamples = () => { + const { version } = useContext(LanguageVersionContext); + return ( <> { figmaExample=""> + + {version === "new" && ( + <> + + + < DateOfBirth /> + + )} ) } diff --git a/src/routes/components/DatePicker.tsx b/src/routes/components/DatePicker.tsx index 921566c93..668f5a96a 100644 --- a/src/routes/components/DatePicker.tsx +++ b/src/routes/components/DatePicker.tsx @@ -1,6 +1,6 @@ import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx"; import { ComponentBinding, Sandbox } from "@components/sandbox"; -import { useContext, useState } from "react"; +import { useContext, useState, useEffect } from "react"; import { ComponentProperties, ComponentProperty, @@ -71,6 +71,32 @@ export default function DatePickerPage() { value: false, }, ]); + + useEffect(() => { + setComponentBindings(prevBindings => { + if (version === "new") { + // Add the type property if it doesn't exist + if (!prevBindings.find(binding => binding.name === "type")) { + return [ + ...prevBindings, + { + label: "Type", + type: "list", + name: "type", + options: ["", "calendar", "input"], + value: "", + defaultValue: "calendar", + } + ]; + } + } else { + // Remove the type property if it exists + return prevBindings.filter(binding => binding.name !== "type"); + } + return prevBindings; + }); + }, [version]); + const { formItemBindings, formItemProps, onFormItemChange } = useSandboxFormItem({ label: "Item", }); @@ -95,7 +121,7 @@ export default function DatePickerPage() { { name: "min", type: "string", - defaultValue: "5 year previous", + defaultValue: "5 years previous", description: "Minimum date value allowed.", }, { @@ -125,6 +151,12 @@ export default function DatePickerPage() { type: "string", description: "Name of the date field.", }, + { + name: "type", + type: "calendar | input", + description: "Sets the type of date picker to use.", + defaultValue: "calendar", + }, { name: "value", type: "Date | string | null | undefined", @@ -133,14 +165,14 @@ export default function DatePickerPage() { { name: "min", type: "Date | string", - defaultValue: "5 year previous", - description: "Minimum date value allowed.", + defaultValue: "5 years previous", + description: "Minimum date value allowed. Only used for calendar type.", }, { name: "max", type: "Date | string", defaultValue: "5 years forward", - description: "Maximum date value allowed.", + description: "Maximum date value allowed. Only used for calendar type.", }, { name: "error", @@ -311,16 +343,31 @@ export default function DatePickerPage() { - - Examples - - - } - > - - + Examples + + + } + > + + + )} + + {version === "old" && ( + + Examples + + + } + > + + + )} From 0d91fed35cc109e1249adf45468ca5d9c95b2fb4 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 27 Aug 2025 13:31:12 -0600 Subject: [PATCH 24/35] feat(#2132): drop down - replaced "back-link" tags with GoabLink --- .../basic-question-page-with-a-dropdown.tsx | 58 ++++++------------- 1 file changed, 17 insertions(+), 41 deletions(-) diff --git a/src/examples/basic-question-page-with-a-dropdown.tsx b/src/examples/basic-question-page-with-a-dropdown.tsx index 5f8f87538..b68f6894a 100644 --- a/src/examples/basic-question-page-with-a-dropdown.tsx +++ b/src/examples/basic-question-page-with-a-dropdown.tsx @@ -5,7 +5,8 @@ import { GoabButton, GoabFormItem, GoabDropdown, - GoabDropdownItem + GoabDropdownItem, + GoabLink } from "@abgov/react-components"; import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; import { useContext } from "react"; @@ -16,31 +17,6 @@ export default function BasicPageWithDropdown() {
    - {/*CSS Code Snippet*/} - ') center center no-repeat; - } - - a.back-link:visited::before, - a.back-link:hover::before { - background: url('data:image/svg+xml,') center center no-repeat; - } - - a.back-link { - margin-top: var(--goa-space-m); - } - `} - /> - {/*Angular Code Snippet - need for leadingContent slot*/} {version === "old" && - Back - + + Back + {}} name="province-territory" ariaLabelledBy="provinceLabel"> @@ -80,9 +56,9 @@ export default function BasicPageWithDropdown() { tags="angular" allowCopy={true} code={` - - Back - + + Back + {}} name="province-territory" ariaLabelledBy="provinceLabel"> @@ -113,9 +89,9 @@ export default function BasicPageWithDropdown() { tags="react" allowCopy={true} code={` - - Back - + + Back + {}} name="province-territory" ariaLabelledBy="provinceLabel"> @@ -145,9 +121,9 @@ export default function BasicPageWithDropdown() { tags="react" allowCopy={true} code={` - - Back - + + Back + {}} name="province-territory" ariaLabelledBy="provinceLabel"> @@ -172,9 +148,9 @@ export default function BasicPageWithDropdown() { `} />} - - Back - + + Back + {}} name="province-territory" ariaLabelledBy="provinceLabel"> From 8ae8d57d0513755eeb69777431ecc86daa7931a8 Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 28 Aug 2025 11:05:20 -0600 Subject: [PATCH 25/35] feat(#2300): details - adjusted margins in examples --- src/examples/ask-a-user-for-direct-deposit-information.tsx | 2 +- src/examples/show-a-list-to-help-answer-a-question.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/examples/ask-a-user-for-direct-deposit-information.tsx b/src/examples/ask-a-user-for-direct-deposit-information.tsx index 0faf09f91..f10e0701f 100644 --- a/src/examples/ask-a-user-for-direct-deposit-information.tsx +++ b/src/examples/ask-a-user-for-direct-deposit-information.tsx @@ -139,7 +139,7 @@ export const AskAUserForDirectDepositInformation = () => { - +

    Below is an example of where you can find the required bank information on a personal cheque. diff --git a/src/examples/show-a-list-to-help-answer-a-question.tsx b/src/examples/show-a-list-to-help-answer-a-question.tsx index d7bff981f..30678c393 100644 --- a/src/examples/show-a-list-to-help-answer-a-question.tsx +++ b/src/examples/show-a-list-to-help-answer-a-question.tsx @@ -51,7 +51,7 @@ export const ShowAListToHelpAnswerAQuestion = () => { - +

    Examples of education expenses From 0900ab144e737405a673a62ebbe40b9cb6f90a27 Mon Sep 17 00:00:00 2001 From: Dustin Nielsen Date: Mon, 15 Sep 2025 12:58:10 -0600 Subject: [PATCH 26/35] fix(#2732): Removed birthday example that used Input --- src/examples/ask-a-user-for-a-birthday.tsx | 129 ------------------ src/examples/text-field/TextFieldExamples.tsx | 7 - 2 files changed, 136 deletions(-) delete mode 100644 src/examples/ask-a-user-for-a-birthday.tsx diff --git a/src/examples/ask-a-user-for-a-birthday.tsx b/src/examples/ask-a-user-for-a-birthday.tsx deleted file mode 100644 index cd47bcec0..000000000 --- a/src/examples/ask-a-user-for-a-birthday.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { Sandbox } from "@components/sandbox"; -import { GoabBlock, GoabDropdown, GoabDropdownItem, GoabFormItem, GoabInput } from "@abgov/react-components"; -import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; -import { useContext } from "react"; -import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx"; - - -export const AskAUserForABirthday = () => { - const {version} = useContext(LanguageVersionContext); - - const noop = () => {} - return ( - - {/*React code*/} - {version === "new" && (''); - const [month, setMonth] = useState(''); - const [year, setYear] = useState(''); - `} - />} - - {version === "new" && - - - setMonth(event.value)} name="month" value={month}> - - - - - - - - - - - - - - - - - setDay(event.value)} value={day} name="day" width="2ch"> - - - setYear(event.value)} value={year} name="year" width="4ch"> - - - - `} - />} - - {/*Angular code*/} - {version === "new" && } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ) -} - -export default AskAUserForABirthday; diff --git a/src/examples/text-field/TextFieldExamples.tsx b/src/examples/text-field/TextFieldExamples.tsx index 94179cc0a..4476a1d3f 100644 --- a/src/examples/text-field/TextFieldExamples.tsx +++ b/src/examples/text-field/TextFieldExamples.tsx @@ -1,4 +1,3 @@ -import { AskAUserForABirthday } from "@examples/ask-a-user-for-a-birthday.tsx"; import { Search } from "@examples/search.tsx"; import { AskAUserForDollarAmounts } from "@examples/ask-a-user-for-dollar-amounts.tsx"; import { @@ -18,12 +17,6 @@ export default function TextFieldExamples() { - - - - From 344d4ca977efafb56bb495121cd3d4b22c8acb1a Mon Sep 17 00:00:00 2001 From: Dustin Nielsen Date: Wed, 17 Sep 2025 11:07:53 -0600 Subject: [PATCH 27/35] fix(#2732): Lowering the number of examples for Input --- src/routes/components/TextField.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/components/TextField.tsx b/src/routes/components/TextField.tsx index bb6d03907..f31ed9325 100644 --- a/src/routes/components/TextField.tsx +++ b/src/routes/components/TextField.tsx @@ -798,7 +798,7 @@ export default function TextFieldPage() { heading={ <> Examples - + }> From 1d3785c609e7f960e267475dd713515b03065de6 Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 18 Sep 2025 13:21:18 -0600 Subject: [PATCH 28/35] feat(#2302): popover - adjusted Table Filter example --- src/examples/popover/PopoverExamples.tsx | 5 +- src/examples/popover/TablePopover.tsx | 536 +++++++++-------------- 2 files changed, 210 insertions(+), 331 deletions(-) diff --git a/src/examples/popover/PopoverExamples.tsx b/src/examples/popover/PopoverExamples.tsx index 0ae830eba..fd4f6eb8d 100644 --- a/src/examples/popover/PopoverExamples.tsx +++ b/src/examples/popover/PopoverExamples.tsx @@ -1,3 +1,4 @@ +import { GoabSpacer } from "@abgov/react-components"; import { ButtonClosePopover } from "@examples/popover/ButtonClosePopover"; import { LinkClosePopover } from "@examples/popover/LinkClosePopover"; import { IconButtonClosePopover } from "@examples/popover/IconButtonClosePopover"; @@ -11,9 +12,7 @@ export const PopoverExamples = () => { const { version, language } = useContext(LanguageVersionContext); return ( <> - {version === "old" && ( - - )} + {/*Popover Example - close using a button*/} diff --git a/src/examples/popover/TablePopover.tsx b/src/examples/popover/TablePopover.tsx index 5aa3c3f5e..45179eace 100644 --- a/src/examples/popover/TablePopover.tsx +++ b/src/examples/popover/TablePopover.tsx @@ -1,4 +1,4 @@ -import { useContext, useState, useEffect, useCallback } from "react"; +import { useContext, useState } from "react"; import { Sandbox } from "@components/sandbox"; import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx"; import { @@ -19,236 +19,94 @@ import { GoabRadioGroupOnChangeDetail } from "@abgov/ui-components-common"; export const TablePopover = () => { const { version } = useContext(LanguageVersionContext); - const [selectedChips, setSelectedChips] = useState([]); - const [filter] = useState('All'); + const [selectedFilter, setSelectedFilter] = useState(null); + const popoverValues = [ - { - key: 1, - type: "success", - status: "Open", - }, - { - key: 2, - type: "midtone", - status: "Closed", - }, - { - key: 3, - type: "midtone", - status: "Closed", - }, - { - key: 4, - type: "midtone", - status: "Closed", - }, - { - key: 5, - type: "success", - status: "Open", - }, - { - key: 6, - type: "midtone", - status: "Closed", - }, + { key: 1, type: "success", status: "Open" }, + { key: 2, type: "midtone", status: "Closed" }, + { key: 3, type: "midtone", status: "Closed" }, + { key: 4, type: "midtone", status: "Closed" }, + { key: 5, type: "success", status: "Open" }, + { key: 6, type: "midtone", status: "Closed" }, ]; - const [dataFiltered, setDataFiltered] = useState(popoverValues); - const target = ( - + Filter ); function radioGroupOnChange(event: GoabRadioGroupOnChangeDetail) { - setSelectedChips([...selectedChips, event.value]); - return; - }; - - const checkNested = useCallback((obj: object, chip: string): boolean => { - return Object.values(obj).some(value => - typeof value === "object" && value !== null - ? checkNested(value, chip) - : typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase()) - ); - }, []); + setSelectedFilter(event.value); + } - const removeFilter = (chip: string) => { - setSelectedChips(selectedChips.filter(c => c !== chip)); - return; - }; - - const getFilteredData = useCallback ((selectedChips: string[]) => { - if (selectedChips.length === 0) { - return popoverValues; - } - const filteredData = popoverValues.filter((item: object) => - selectedChips.every(chip => checkNested(item, chip)) - ); - - return filteredData; - }, - [checkNested, popoverValues] - ); + const filteredData = selectedFilter ? popoverValues.filter((item) => + item.status === selectedFilter + ) : popoverValues; - useEffect(() => { - setDataFiltered(getFilteredData(selectedChips)); - }, [getFilteredData, selectedChips]); - return ( <> {/*============= React code ==============*/} - {version === "old" && ( + + {version === "new" && ( - Filter - - ); + const [selectedFilter, setSelectedFilter] = useState(null); const popoverValues = [ { key: 1, type: "success", - status: "Open", + status: "Open" }, { key: 2, type: "midtone", - status: "Closed", + status: "Closed" }, { key: 3, type: "midtone", - status: "Closed", + status: "Closed" }, { key: 4, type: "midtone", - status: "Closed", + status: "Closed" }, { key: 5, type: "success", - status: "Open", + status: "Open" }, { key: 6, type: "midtone", - status: "Closed", + status: "Closed" }, ]; - `} - /> - )} - - {version === "new" && ( - + Filter ); - const popoverValues = [ - { - key: 1, - type: "success", - status: "Open", - }, - { - key: 2, - type: "midtone", - status: "Closed", - }, - { - key: 3, - type: "midtone", - status: "Closed", - }, - { - key: 4, - type: "midtone", - status: "Closed", - }, - { - key: 5, - type: "success", - status: "Open", - }, - { - key: 6, - type: "midtone", - status: "Closed", - }, - ]; - `} - /> - )} - - {version === "old" && ( - -

    Table with a filter

    - -
    - - - - - - - Remove filter -
    -
    -
    - - - - Status - Text - Number - Action - - - - {popoverValues.map(u => ( - - - Lorem ipsum - 1234567890 - Action - - ))} - - + function radioGroupOnChange(event: GoabRadioGroupOnChangeDetail) { + setSelectedFilter(event.value); + } + + const filteredData = selectedFilter ? popoverValues.filter((item) => + item.status === selectedFilter + ) : popoverValues; `} /> )} - + {version === "new" && ( {
    - - - + + + - Remove filter + setSelectedFilter(null)} + aria-label="Remove filter" + > + Remove filter +
    + {selectedFilter && ( +
    + + Filter: + + setSelectedFilter(null)} + /> + setSelectedFilter(null)} + > + Clear all + +
    + )} + - Status - Text - Number - Action + Status + Text + Number + Action - {popoverValues.map(u => ( - - + {filteredData.map((u) => ( + + + + Lorem ipsum 1234567890 - Action - + + Action + + ))} `} /> )} - + {/*================ Angular code ==================*/} - {version === "old" && ( - - )} - {version === "new" && ( - )} - - {version === "old" && ( - -

    Table with a filter

    - -
    - - - - - - - Remove filter -
    -
    - Filter -
    -
    -
  • - - - - Status - Text - Number - Action - - - - - Lorem ipsum - 1234567890 - Action - - - + @Component({ + selector: 'app-table-popover', + templateUrl: './table-popover.component.html', + }) + + export class TablePopoverComponent { + selectedFilter = new FormControl(null); + + popoverValues: PopoverValue[] = [ + { + key: 1, + type: 'success', + status: 'Open' + }, + { + key: 2, + type: 'midtone', + status: 'Closed' + }, + { + key: 3, + type: 'midtone', + status: 'Closed' + }, + { + key: 4, + type: 'midtone', + status: 'Closed' + }, + { + key: 5, + type: 'success', + status: 'Open' + }, + { + key: 6, + type: 'midtone', + status: 'Closed' + }, + ]; + + get filteredData(): PopoverValue[] { + const filter = this.selectedFilter.value; + return filter + ? this.popoverValues.filter(item => item.status === filter) + : this.popoverValues; + } + + clearFilter() { + this.selectedFilter.setValue(null); + } + } `} /> )} - + {version === "new" && ( { code={`

    Table with a filter

    - +
    - - - + + + Remove filter
    -
    - Filter -
    + + + Filter + +
    + +
    + + Filter: + + + + Clear all + +
    + @@ -459,39 +324,50 @@ export const TablePopover = () => { `} /> )} +

    Table with a filter

    - - - + + + + setSelectedFilter(null)} + > + Remove filter +
    - {selectedChips.length > 0 && ( + {selectedFilter && (
    - - Filter: - - {selectedChips.length > 0 && - selectedChips.map((selectedChip, index) => ( + + Filter: + removeFilter(selectedChip)} + onClick={() => setSelectedFilter(null)} /> - ))} - setSelectedChips([])}> - Clear all - + setSelectedFilter(null)} + aria-label="Clear all filters" + > + Clear all +
    )} + @@ -502,17 +378,21 @@ export const TablePopover = () => { - {dataFiltered.map(u => ( - - + {filteredData.map((u) => ( + + + + Lorem ipsum 1234567890 - Action - + + Action + + ))} ); -} +}; From 342c7ad3b65d99f7437129b9f27122b4afd21127 Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 18 Sep 2025 13:25:10 -0600 Subject: [PATCH 29/35] feat(#2302): popover - removed "Remove Filter" button --- src/examples/popover/TablePopover.tsx | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/examples/popover/TablePopover.tsx b/src/examples/popover/TablePopover.tsx index 45179eace..b6d2ebcba 100644 --- a/src/examples/popover/TablePopover.tsx +++ b/src/examples/popover/TablePopover.tsx @@ -123,14 +123,6 @@ export const TablePopover = () => { - setSelectedFilter(null)} - aria-label="Remove filter" - > - Remove filter -
    @@ -270,7 +262,6 @@ export const TablePopover = () => { - Remove filter { - setSelectedFilter(null)} - > - Remove filter -
    From 72d0ffbcb0c18599d147bce748eccfbec5561f6c Mon Sep 17 00:00:00 2001 From: syedszeeshan <47701214+syedszeeshan@users.noreply.github.com> Date: Fri, 19 Sep 2025 15:24:43 -0400 Subject: [PATCH 30/35] fix(#2598): add app header menu props --- src/routes/components/AppHeader.tsx | 51 ++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/routes/components/AppHeader.tsx b/src/routes/components/AppHeader.tsx index cdbdd36d8..dcb0ea00c 100644 --- a/src/routes/components/AppHeader.tsx +++ b/src/routes/components/AppHeader.tsx @@ -116,6 +116,29 @@ export default function AppHeaderPage() { description: "Function invoked when the menu hamburger button (on mobile/tablet device) is clicked." } ]; + + const appHeaderMenuLegacyProperties: ComponentProperty[] = [ + { + name: "heading", + type: "string", + description: "Set the heading text displayed for the menu.", + required: true, + }, + { + name: "leadingicon", + type: "GoAIconType", + description: "Set the leading icon for the menu item.", + lang: "angular" + }, + { + name: "leadingIcon", + type: "GoAIconType", + description: "Set the leading icon for the menu item.", + lang: "react" + }, + ...LegacyTestIdProperties, + ]; + const componentProperties: ComponentProperty[] = [ { name: "url", @@ -146,6 +169,21 @@ export default function AppHeaderPage() { } ]; + const appHeaderMenuProperties: ComponentProperty[] = [ + { + name: "heading", + type: "string", + description: "Set the heading text displayed for the menu.", + required: true, + }, + { + name: "leadingIcon", + type: "GoabIconType", + description: "Set the leading icon for the menu item.", + }, + TestIdProperty, + ]; + function onSandboxChange(bindings: ComponentBinding[], props: Record) { setAppHeaderProps(props as CastingType); @@ -174,7 +212,18 @@ export default function AppHeaderPage() { {/*Component properties*/} - + + + {/*App Header Menu Component properties*/} + From f067b297a16887c53b6a74798c8692ac31bfa7b5 Mon Sep 17 00:00:00 2001 From: Dustin Nielsen Date: Fri, 26 Sep 2025 15:54:09 -0600 Subject: [PATCH 31/35] fix(#3043): Updated LTS Policy information --- .../VersionUpdateNotification.tsx | 5 ++- src/routes/get-started/LtsPolicyPage.tsx | 35 +++++++++++-------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/components/version-language-switcher/VersionUpdateNotification.tsx b/src/components/version-language-switcher/VersionUpdateNotification.tsx index a6156a5a6..4ac93c711 100644 --- a/src/components/version-language-switcher/VersionUpdateNotification.tsx +++ b/src/components/version-language-switcher/VersionUpdateNotification.tsx @@ -27,10 +27,9 @@ export function VersionUpdateNotification({ version }: VersionUpdateNotification {version === "old" ? ( <> - Support for the Long Term Support (LTS) version of the Design system will be available until September - 2025.{" "} + Long-term support (LTS) for v3 (Angular) and v5 (React) has ended. Read the{" "} - View the upgrade guide + upgrade guide ) : ( diff --git a/src/routes/get-started/LtsPolicyPage.tsx b/src/routes/get-started/LtsPolicyPage.tsx index 460922e72..29f85c91c 100644 --- a/src/routes/get-started/LtsPolicyPage.tsx +++ b/src/routes/get-started/LtsPolicyPage.tsx @@ -4,31 +4,38 @@ import { Link } from "react-router-dom"; export const LtsPolicyPage = () => { return ( <> - Long Term Support (LTS) + Long Term Support (LTS) - - The Long Term Support (LTS) version will continue to be supported until September 30, 2025. Learn more about what you can expect. + + LTS for the design system has ended. Version v3 (Angular) and v5 (React) are no longer supported. - - The previous version of the design system v3 (Angular) and v5 (React) is now in Long-Term Support (LTS). Here's what that means: + + What this means: -
      -
    • Bug fixes only: We'll continue fixing critical bugs and regressions.
    • -
    • No new features or enhancements: All new development is happening in the latest major version.
    • -
    • Same reliable experience: Your project will continue to work as expected.
    • -
    +
      +
    • No fixes or patches: We won't ship bug or security fixes for v3/v5
    • +
    • No new features or enhancements: All new work happens in the current major version.
    • +
    • Use at your own risk: Existing projects may continue to run, but we won't test or guarantee compatibility with new browsers, OS updates, or framework changes.
    • +
    - - Ready to update to the latest version? Visit our update guide + + What to do next - +
      +
    • Upgrade to the latest version. See the update guide
    • +
    • Need help planning the upgrade? Book a drop in hours session for guidance
    • +
    +
    + + - Projects still using LTS will continue to work, but new issues or bugs will not be prioritized. + Projects still using LTS will continue to work, but new issues or bugs in v3 (Angular) and v5 (React) will not be fixed. ); From e13236196a58cb77956f2a5957442fa2fd264b3d Mon Sep 17 00:00:00 2001 From: Chris Olsen Date: Mon, 29 Sep 2025 11:28:11 -0600 Subject: [PATCH 32/35] fix(#2779): remove non-required event handling from version switcher --- package-lock.json | 28 +++++++------------ package.json | 4 +-- .../VersionLanguageSwitcher.tsx | 27 +++++++----------- .../version-language-switcher.css | 12 +++++++- 4 files changed, 33 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index f4f5aa7d9..a81aef758 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,9 @@ "name": "code-sandbox", "version": "0.0.0", "dependencies": { - "@abgov/react-components": "6.7.1-alpha.1", + "@abgov/react-components": "6.8.0-alpha.2", "@abgov/ui-components-common": "1.7.0", - "@abgov/web-components": "1.37.1-alpha.2", + "@abgov/web-components": "1.38.0-alpha.3", "@faker-js/faker": "^8.3.1", "highlight.js": "^11.8.0", "js-cookie": "^3.0.5", @@ -68,9 +68,10 @@ } }, "node_modules/@abgov/react-components": { - "version": "6.7.1-alpha.1", - "resolved": "https://registry.npmjs.org/@abgov/react-components/-/react-components-6.7.1-alpha.1.tgz", - "integrity": "sha512-s5+tGLY2DOeMV3BjiIz0c71hESIF/kcWA3PrFxvPCoCuPWiilLL0ktmd9sCRPp5qhcbWtW6M8vuLatwIiD28qQ==", + "version": "6.8.0-alpha.2", + "resolved": "https://registry.npmjs.org/@abgov/react-components/-/react-components-6.8.0-alpha.2.tgz", + "integrity": "sha512-C4ZmYzOWrFUKtcmcP+3Zz3zcUBQgziZqx3lVB5jkQT052vqt/5JQQWkB8Danw0fjfgnuO/MheOWH8qZEuZjFlg==", + "license": "Apache-2.0", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", @@ -83,9 +84,10 @@ "integrity": "sha512-dnqLxTJdBxNZFKPDyckaHHrkipjFIwXyU63rlEkcHgKhn4d+KrwlbMuxtsS73FvH4bozyQm2OM+sPu32wyWgNA==" }, "node_modules/@abgov/web-components": { - "version": "1.37.1-alpha.2", - "resolved": "https://registry.npmjs.org/@abgov/web-components/-/web-components-1.37.1-alpha.2.tgz", - "integrity": "sha512-WoQZAwccxRPQHWHBS/7gDISCFbEnWrsRZvS8U9iK0N3jr00YTtlvxdwEDywZAcgrXitxa8qlIVbpylZVLzDdmQ==", + "version": "1.38.0-alpha.3", + "resolved": "https://registry.npmjs.org/@abgov/web-components/-/web-components-1.38.0-alpha.3.tgz", + "integrity": "sha512-mE8qwOCO+V7gHvZqrONgo81c0HBekci7jSwO+GoOQRrRMYoh17vTRM3tPPrtRznqJ+QyQBQS5G2tWkpoqbHMsg==", + "license": "Apache-2.0", "peerDependencies": { "@sveltejs/vite-plugin-svelte": "3.x", "glob": "10.x", @@ -990,16 +992,6 @@ "node": ">= 18" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true, - "peer": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@remix-run/router": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", diff --git a/package.json b/package.json index 1660d33b7..e062f4968 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "prettier": "npx prettier . --write" }, "dependencies": { - "@abgov/react-components": "6.7.1-alpha.1", + "@abgov/react-components": "6.8.0-alpha.2", "@abgov/ui-components-common": "1.7.0", - "@abgov/web-components": "1.37.1-alpha.2", + "@abgov/web-components": "1.38.0-alpha.3", "@faker-js/faker": "^8.3.1", "highlight.js": "^11.8.0", "js-cookie": "^3.0.5", diff --git a/src/components/version-language-switcher/VersionLanguageSwitcher.tsx b/src/components/version-language-switcher/VersionLanguageSwitcher.tsx index e98056ed2..b7bb1da14 100644 --- a/src/components/version-language-switcher/VersionLanguageSwitcher.tsx +++ b/src/components/version-language-switcher/VersionLanguageSwitcher.tsx @@ -2,6 +2,7 @@ import { GoabIcon, GoabPopover } from "@abgov/react-components"; + import { ANGULAR_VERSIONS, getVersionedUrlPath, Language, LanguageVersion, VERSIONED_ANGULAR_URL_SEGMENT, @@ -16,7 +17,7 @@ export const VersionLanguageSwitcher = () => { const {language, version, setLanguage, setVersion} = useContext(LanguageVersionContext); const location = useLocation(); const navigate = useNavigate(); - const [hash, setHash] = React.useState(window.location.hash); + const [hash, setHash] = React.useState(window.location.hash); useEffect(() => { function setLanguageAndVersionFromUrl() { @@ -33,7 +34,7 @@ export const VersionLanguageSwitcher = () => { setLanguageAndVersionFromUrl(); }); - // popover collapses when Url hash tag changes + // popover collapses when Url hash tag changes const generateHyperlink = (newValue: LanguageVersion | Language) => { return hash === newValue ? "#" : `#${newValue}`; }; @@ -85,18 +86,10 @@ export const VersionLanguageSwitcher = () => { return str.charAt(0).toUpperCase() + str.slice(1); } - const openLanguagePopOver = (e: React.MouseEvent) => { - e.preventDefault(); - }; - - const openVersionPopOver = (e: React.MouseEvent) => { - e.preventDefault(); - }; - const getCurrentVersionLabel = (language: string, version: string) => { if (language === "react") { return version === "new" ? REACT_VERSIONS.NEW.label : REACT_VERSIONS.OLD.label; - } if (language === "angular") { + } if (language === "angular") { return version === "new" ? ANGULAR_VERSIONS.NEW.label : ANGULAR_VERSIONS.OLD.label; } } @@ -106,9 +99,10 @@ export const VersionLanguageSwitcher = () => {
    openLanguagePopOver(e)}> - {capitalizeFirstLetter(language)} - +
    + + {language} +
    } padded={false}> <> @@ -121,10 +115,9 @@ export const VersionLanguageSwitcher = () => {
    openVersionPopOver(e)}> +
    {getCurrentVersionLabel(language, version)} - +
    } padded={false}> <> {["new", "old"].map(ver => ( diff --git a/src/components/version-language-switcher/version-language-switcher.css b/src/components/version-language-switcher/version-language-switcher.css index f2594c468..0e4f4b11e 100644 --- a/src/components/version-language-switcher/version-language-switcher.css +++ b/src/components/version-language-switcher/version-language-switcher.css @@ -55,4 +55,14 @@ gap: 0; margin-bottom: var(--goa-space-3xs); } -} \ No newline at end of file +} + +.menu-link { + display: flex; + align-item: center; + color: var(--goa-color-interactive-default); +} + +.menu-link:hover { + color: var(--goa-color-interactive-hover); +} From 8b652bb3a5a5e55a67e8516265eab2d01e18f186 Mon Sep 17 00:00:00 2001 From: Chris Olsen Date: Mon, 29 Sep 2025 14:25:02 -0600 Subject: [PATCH 33/35] fix: correct css style name --- .../VersionLanguageSwitcher.tsx | 11 +++++------ .../version-language-switcher.css | 4 +++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/version-language-switcher/VersionLanguageSwitcher.tsx b/src/components/version-language-switcher/VersionLanguageSwitcher.tsx index b7bb1da14..8b9377c6f 100644 --- a/src/components/version-language-switcher/VersionLanguageSwitcher.tsx +++ b/src/components/version-language-switcher/VersionLanguageSwitcher.tsx @@ -95,13 +95,12 @@ export const VersionLanguageSwitcher = () => { } return ( - <> -
    +
    - {language} + {capitalizeFirstLetter(language)}
    } padded={false}> @@ -116,7 +115,8 @@ export const VersionLanguageSwitcher = () => { - {getCurrentVersionLabel(language, version)} + + {getCurrentVersionLabel(language, version)}
    } padded={false}> <> @@ -127,7 +127,6 @@ export const VersionLanguageSwitcher = () => { ))}
    -
    - +
    ); } diff --git a/src/components/version-language-switcher/version-language-switcher.css b/src/components/version-language-switcher/version-language-switcher.css index 0e4f4b11e..6b4c3fa31 100644 --- a/src/components/version-language-switcher/version-language-switcher.css +++ b/src/components/version-language-switcher/version-language-switcher.css @@ -59,10 +59,12 @@ .menu-link { display: flex; - align-item: center; + align-items: center; + justify-content: center; color: var(--goa-color-interactive-default); } .menu-link:hover { color: var(--goa-color-interactive-hover); + text-decoration: underline; } From 048ec5712cebbbf978419d5c0e11df55cc2753e6 Mon Sep 17 00:00:00 2001 From: Chris Olsen Date: Mon, 29 Sep 2025 14:31:58 -0600 Subject: [PATCH 34/35] fix: better vertically align microsite header version menus --- src/components/version-language-switcher/HelpButton.tsx | 3 +-- .../version-language-switcher/version-language-switcher.css | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/version-language-switcher/HelpButton.tsx b/src/components/version-language-switcher/HelpButton.tsx index 7fb14e824..21b7e088e 100644 --- a/src/components/version-language-switcher/HelpButton.tsx +++ b/src/components/version-language-switcher/HelpButton.tsx @@ -26,7 +26,6 @@ export function HelpButton() { return ( ); -} \ No newline at end of file +} diff --git a/src/components/version-language-switcher/version-language-switcher.css b/src/components/version-language-switcher/version-language-switcher.css index 6b4c3fa31..3bd4e681c 100644 --- a/src/components/version-language-switcher/version-language-switcher.css +++ b/src/components/version-language-switcher/version-language-switcher.css @@ -30,12 +30,10 @@ } .version-language-switcher { - height: 20px; display: flex; flex-direction: row; align-items: center; /* vertically align content */ gap: var(--goa-space-s); - margin-bottom: var(--goa-space-xs); } @media (max-width: 623px) { From 58a75d0af5ff780aa59c946003494b453bb3de82 Mon Sep 17 00:00:00 2001 From: Dustin Nielsen Date: Mon, 29 Sep 2025 19:06:44 -0600 Subject: [PATCH 35/35] Revert "fix(#2779): remove non-required event handling from version switcher" --- package-lock.json | 28 +++++++++------ package.json | 4 +-- .../version-language-switcher/HelpButton.tsx | 3 +- .../VersionLanguageSwitcher.tsx | 36 +++++++++++-------- .../version-language-switcher.css | 16 ++------- 5 files changed, 47 insertions(+), 40 deletions(-) diff --git a/package-lock.json b/package-lock.json index a81aef758..f4f5aa7d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,9 @@ "name": "code-sandbox", "version": "0.0.0", "dependencies": { - "@abgov/react-components": "6.8.0-alpha.2", + "@abgov/react-components": "6.7.1-alpha.1", "@abgov/ui-components-common": "1.7.0", - "@abgov/web-components": "1.38.0-alpha.3", + "@abgov/web-components": "1.37.1-alpha.2", "@faker-js/faker": "^8.3.1", "highlight.js": "^11.8.0", "js-cookie": "^3.0.5", @@ -68,10 +68,9 @@ } }, "node_modules/@abgov/react-components": { - "version": "6.8.0-alpha.2", - "resolved": "https://registry.npmjs.org/@abgov/react-components/-/react-components-6.8.0-alpha.2.tgz", - "integrity": "sha512-C4ZmYzOWrFUKtcmcP+3Zz3zcUBQgziZqx3lVB5jkQT052vqt/5JQQWkB8Danw0fjfgnuO/MheOWH8qZEuZjFlg==", - "license": "Apache-2.0", + "version": "6.7.1-alpha.1", + "resolved": "https://registry.npmjs.org/@abgov/react-components/-/react-components-6.7.1-alpha.1.tgz", + "integrity": "sha512-s5+tGLY2DOeMV3BjiIz0c71hESIF/kcWA3PrFxvPCoCuPWiilLL0ktmd9sCRPp5qhcbWtW6M8vuLatwIiD28qQ==", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", @@ -84,10 +83,9 @@ "integrity": "sha512-dnqLxTJdBxNZFKPDyckaHHrkipjFIwXyU63rlEkcHgKhn4d+KrwlbMuxtsS73FvH4bozyQm2OM+sPu32wyWgNA==" }, "node_modules/@abgov/web-components": { - "version": "1.38.0-alpha.3", - "resolved": "https://registry.npmjs.org/@abgov/web-components/-/web-components-1.38.0-alpha.3.tgz", - "integrity": "sha512-mE8qwOCO+V7gHvZqrONgo81c0HBekci7jSwO+GoOQRrRMYoh17vTRM3tPPrtRznqJ+QyQBQS5G2tWkpoqbHMsg==", - "license": "Apache-2.0", + "version": "1.37.1-alpha.2", + "resolved": "https://registry.npmjs.org/@abgov/web-components/-/web-components-1.37.1-alpha.2.tgz", + "integrity": "sha512-WoQZAwccxRPQHWHBS/7gDISCFbEnWrsRZvS8U9iK0N3jr00YTtlvxdwEDywZAcgrXitxa8qlIVbpylZVLzDdmQ==", "peerDependencies": { "@sveltejs/vite-plugin-svelte": "3.x", "glob": "10.x", @@ -992,6 +990,16 @@ "node": ">= 18" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "peer": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@remix-run/router": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", diff --git a/package.json b/package.json index e062f4968..1660d33b7 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "prettier": "npx prettier . --write" }, "dependencies": { - "@abgov/react-components": "6.8.0-alpha.2", + "@abgov/react-components": "6.7.1-alpha.1", "@abgov/ui-components-common": "1.7.0", - "@abgov/web-components": "1.38.0-alpha.3", + "@abgov/web-components": "1.37.1-alpha.2", "@faker-js/faker": "^8.3.1", "highlight.js": "^11.8.0", "js-cookie": "^3.0.5", diff --git a/src/components/version-language-switcher/HelpButton.tsx b/src/components/version-language-switcher/HelpButton.tsx index 21b7e088e..7fb14e824 100644 --- a/src/components/version-language-switcher/HelpButton.tsx +++ b/src/components/version-language-switcher/HelpButton.tsx @@ -26,6 +26,7 @@ export function HelpButton() { return ( ); -} +} \ No newline at end of file diff --git a/src/components/version-language-switcher/VersionLanguageSwitcher.tsx b/src/components/version-language-switcher/VersionLanguageSwitcher.tsx index 8b9377c6f..e98056ed2 100644 --- a/src/components/version-language-switcher/VersionLanguageSwitcher.tsx +++ b/src/components/version-language-switcher/VersionLanguageSwitcher.tsx @@ -2,7 +2,6 @@ import { GoabIcon, GoabPopover } from "@abgov/react-components"; - import { ANGULAR_VERSIONS, getVersionedUrlPath, Language, LanguageVersion, VERSIONED_ANGULAR_URL_SEGMENT, @@ -17,7 +16,7 @@ export const VersionLanguageSwitcher = () => { const {language, version, setLanguage, setVersion} = useContext(LanguageVersionContext); const location = useLocation(); const navigate = useNavigate(); - const [hash, setHash] = React.useState(window.location.hash); + const [hash, setHash] = React.useState(window.location.hash); useEffect(() => { function setLanguageAndVersionFromUrl() { @@ -34,7 +33,7 @@ export const VersionLanguageSwitcher = () => { setLanguageAndVersionFromUrl(); }); - // popover collapses when Url hash tag changes + // popover collapses when Url hash tag changes const generateHyperlink = (newValue: LanguageVersion | Language) => { return hash === newValue ? "#" : `#${newValue}`; }; @@ -86,22 +85,30 @@ export const VersionLanguageSwitcher = () => { return str.charAt(0).toUpperCase() + str.slice(1); } + const openLanguagePopOver = (e: React.MouseEvent) => { + e.preventDefault(); + }; + + const openVersionPopOver = (e: React.MouseEvent) => { + e.preventDefault(); + }; + const getCurrentVersionLabel = (language: string, version: string) => { if (language === "react") { return version === "new" ? REACT_VERSIONS.NEW.label : REACT_VERSIONS.OLD.label; - } if (language === "angular") { + } if (language === "angular") { return version === "new" ? ANGULAR_VERSIONS.NEW.label : ANGULAR_VERSIONS.OLD.label; } } return ( -
    + <> +
    - - {capitalizeFirstLetter(language)} -
    + openLanguagePopOver(e)}> + {capitalizeFirstLetter(language)} + } padded={false}> <> @@ -114,10 +121,10 @@ export const VersionLanguageSwitcher = () => { - - {getCurrentVersionLabel(language, version)} -
    + openVersionPopOver(e)}> + {getCurrentVersionLabel(language, version)} + } padded={false}> <> {["new", "old"].map(ver => ( @@ -127,6 +134,7 @@ export const VersionLanguageSwitcher = () => { ))} -
    + + ); } diff --git a/src/components/version-language-switcher/version-language-switcher.css b/src/components/version-language-switcher/version-language-switcher.css index 3bd4e681c..f2594c468 100644 --- a/src/components/version-language-switcher/version-language-switcher.css +++ b/src/components/version-language-switcher/version-language-switcher.css @@ -30,10 +30,12 @@ } .version-language-switcher { + height: 20px; display: flex; flex-direction: row; align-items: center; /* vertically align content */ gap: var(--goa-space-s); + margin-bottom: var(--goa-space-xs); } @media (max-width: 623px) { @@ -53,16 +55,4 @@ gap: 0; margin-bottom: var(--goa-space-3xs); } -} - -.menu-link { - display: flex; - align-items: center; - justify-content: center; - color: var(--goa-color-interactive-default); -} - -.menu-link:hover { - color: var(--goa-color-interactive-hover); - text-decoration: underline; -} +} \ No newline at end of file