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 @@ + + + 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 } + ]; + + + +
+ + +
+ +
+ +
+ +

Currently selected: {selected.join(', ')}

`} + language="svelte" + /> + +
+
+
+ + +
+ +
+ +
+ +

+ 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" } + ]; + + +
+ + +
+ + + +

Currently selected: {selectedOption}

`} + language="svelte" + /> + +
+
+
+ + +
+ +
+ +
+ +

Currently selected: {demoSelectedOption}

+
+
{/if} @@ -656,7 +741,12 @@
We'll use this for important notifications
- +
{/snippet} @@ -664,7 +754,7 @@
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)" },