diff --git a/src/lib/components/ui/Breadcrumbs.svelte b/src/lib/components/ui/Breadcrumbs.svelte new file mode 100644 index 00000000..95ee514a --- /dev/null +++ b/src/lib/components/ui/Breadcrumbs.svelte @@ -0,0 +1,198 @@ + + + + + {#each breadcrumbItems as item} + + {item.text} + + {/each} + + diff --git a/src/lib/components/ui/CheckBox.svelte b/src/lib/components/ui/CheckBox.svelte index 9f1ad5af..f440ed9e 100644 --- a/src/lib/components/ui/CheckBox.svelte +++ b/src/lib/components/ui/CheckBox.svelte @@ -14,7 +14,7 @@ }; // Component props - const { + let { legend, hint, error, @@ -24,6 +24,7 @@ small = false, options = [], validate = undefined, + selectedValues = $bindable([]), } = $props<{ legend: string; hint?: string; @@ -34,11 +35,9 @@ small?: boolean; options?: CheckboxOption[]; validate?: (values: string[]) => string | undefined; + selectedValues?: string[]; }>(); - // Component state - let selectedValues = $state([]); - // Add support detection let isSupported = $state(false); // Check for browser support on mount diff --git a/src/lib/components/ui/Radios.svelte b/src/lib/components/ui/Radios.svelte index cb7deec3..f74079fd 100644 --- a/src/lib/components/ui/Radios.svelte +++ b/src/lib/components/ui/Radios.svelte @@ -14,7 +14,8 @@ }; // Component props - const { + let { + selectedValue = $bindable(null), legend, hint, error, @@ -36,11 +37,9 @@ inline?: boolean; options?: RadioOption[]; validate?: (value: string) => string | undefined; + selectedValue?: string | null; }>(); - // Component state for single selection - let selectedValue = $state(null); - // Add support detection let isSupported = $state(false); onMount(() => { @@ -48,16 +47,9 @@ document.body?.classList.contains("govuk-frontend-supported") ?? false; }); - // Derived state to check if a value is selected and handle validation - let isChecked = $derived((value: string) => selectedValue === value); let validationError = $derived( isSupported && validate ? validate(selectedValue ?? "") : undefined, ); - - function toggleRadio(option: RadioOption) { - if (!isSupported) return; - selectedValue = selectedValue === option.value ? null : option.value; - } toggleRadio(option)} data-behaviour={option.exclusive ? "exclusive" : undefined} /> - \ No newline at end of file + diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 40b14b26..bdad7602 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,5 +1,6 @@ + + + +{#if !homepage} + + + + Component Demo + + + + + + + + + + + + + + + + + + Examples + + Basic Automatically Generated Breadcrumbs + + import Breadcrumbs from '$lib/components/ui/Breadcrumbs.svelte'; +<\/script> + + +`} + /> + + + + + + + + Custom Specified Breadcrumbs Items + +`} + /> + + + + + + + + Collapsed on Mobile with Inverse Colors + + + +`} + /> + + + + + + + + + +{/if} + + diff --git a/src/routes/components/ui/checkbox/+page.svelte b/src/routes/components/ui/checkbox/+page.svelte index c968c063..15d2b40f 100644 --- a/src/routes/components/ui/checkbox/+page.svelte +++ b/src/routes/components/ui/checkbox/+page.svelte @@ -90,6 +90,13 @@ inputType: "input", value: "Select all that apply", }, + { + name: "selectedValues", + category: "Content", + isProp: true, + inputType: "javascript", + value: "[]", + }, { name: "name", category: "Form", @@ -209,6 +216,16 @@ ), ); + // Demo state for bindable example + let demoSelected = $state([]); + + const demoOptions = [ + { value: "option1", label: "Option 1" }, + { value: "option2", label: "Option 2" }, + { value: "option3", label: "Option 3" }, + { value: "none", label: "None of the above", exclusive: true }, + ]; + let snippetSections = [ { value: "email", @@ -853,36 +870,98 @@ + + Bindable Values + + import CheckBox from "$lib/components/ui/CheckBox.svelte"; + + let selected = $state([]); // Initialise empty array for selections + + const options = [ + { value: "option1", label: "Option 1" }, + { value: "option2", label: "Option 2" }, + { value: "option3", label: "Option 3" }, + { value: "none", label: "None of the above", exclusive: true } + ]; + + + + + + Select options from dropdown + + + {#each options as option} + {option.label} + {/each} + + + + + + + +Currently selected: {selected.join(', ')}`} + language="svelte" + /> + + + + + + Select options from dropdown + + + {#each demoOptions as option} + {option.label} + {/each} + + + + + + + + + Currently selected: {demoSelected.join(", ")} + + + + {/if} diff --git a/src/routes/components/ui/radios/+page.svelte b/src/routes/components/ui/radios/+page.svelte index d3b08d53..b75d9f24 100644 --- a/src/routes/components/ui/radios/+page.svelte +++ b/src/routes/components/ui/radios/+page.svelte @@ -83,6 +83,13 @@ inputType: "input", value: "", }, + { + name: "selectedValue", + category: "Content", + isProp: true, + inputType: "input", + value: "", + }, { name: "name", category: "Form", @@ -205,6 +212,9 @@ ), ); + // Demo state for bindable example + let demoSelectedOption = $state("option2"); + let snippetSections = [ { value: "email", @@ -434,7 +444,7 @@ { value: "none", label: "I do not wish to receive updates", - exclusive: true + exclusive: true, }, ]} /> @@ -566,7 +576,9 @@ - Using Snippets and Nested Components for Conditional Content + + Using Snippets and Nested Components for Conditional Content + import Radios from "$lib/components/ui/Radios.svelte"; @@ -641,7 +653,9 @@ /> - + + + + Bindable Value + + import Radios from "$lib/components/ui/Radios.svelte"; + + let selectedOption = $state("option2"); + + const options = [ + { value: "option1", label: "Option 1" }, + { value: "option2", label: "Option 2" }, + { value: "option3", label: "Option 3" } + ]; + + + + + Type 'option1', 'option2', or 'option3' to select a radio button + + + + + + +Currently selected: {selectedOption}`} + language="svelte" + /> + + + + + + Type 'option1', 'option2', or 'option3' to select a radio button + + + + + + + + + Currently selected: {demoSelectedOption} + + {/if} @@ -656,7 +741,12 @@ Email Address We'll use this for important notifications - + {/snippet} @@ -664,7 +754,7 @@ Phone Number Include country code if international - + {/snippet} @@ -675,7 +765,7 @@ name="contact-timing" small={true} legendSize="s" - validate={(value) => !value ? "Please select a time slot" : undefined} + validate={(value) => (!value ? "Please select a time slot" : undefined)} options={[ { value: "morning", label: "Morning (9am - 12pm)" }, { value: "afternoon", label: "Afternoon (12pm - 5pm)" },
Currently selected: {selected.join(', ')}
+ Currently selected: {demoSelected.join(", ")} +
Currently selected: {selectedOption}
Currently selected: {demoSelectedOption}