|
1 | 1 | <script lang="ts">
|
2 |
| - import type { Snippet } from 'svelte'; |
| 2 | + import type { Snippet } from "svelte"; |
3 | 3 |
|
4 |
| - import { onMount } from 'svelte'; |
5 |
| - import { SvelteSet } from 'svelte/reactivity'; |
| 4 | + import { onMount } from "svelte"; |
| 5 | + import { SvelteSet } from "svelte/reactivity"; |
6 | 6 |
|
7 | 7 | let {
|
8 | 8 | sections = [],
|
9 |
| - hideAllSections = 'Hide all sections', |
10 |
| - hideSection = 'Hide', |
11 |
| - hideSectionAriaLabel = 'Hide this section', |
12 |
| - showAllSections = 'Show all sections', |
13 |
| - showSection = 'Show', |
14 |
| - showSectionAriaLabel = 'Show this section', |
| 9 | + hideAllSections = "Hide all sections", |
| 10 | + hideSection = "Hide", |
| 11 | + hideSectionAriaLabel = "Hide this section", |
| 12 | + showAllSections = "Show all sections", |
| 13 | + showSection = "Show", |
| 14 | + showSectionAriaLabel = "Show this section", |
15 | 15 | allSectionToggle = true,
|
16 | 16 | minSectionsAllSectionToggle = 2,
|
17 | 17 | rememberIsExpandedState = true,
|
18 |
| - headingLevel = 'h4', |
| 18 | + headingLevel = "h4", |
19 | 19 | }: {
|
20 | 20 | sections: {
|
21 | 21 | heading: string;
|
|
37 | 37 | } = $props();
|
38 | 38 |
|
39 | 39 | //Attempt to ensure that ids are unique by attaching extra characters
|
40 |
| - let uniqueSections = sections.map((section, i) => { |
41 |
| - return { |
42 |
| - ...section, |
43 |
| - uniqueid: |
44 |
| - section.id + |
45 |
| - section.heading.slice(1, 3) + |
46 |
| - (section?.summary?.slice(0, 2) ?? ''), |
47 |
| - }; |
48 |
| - }); |
| 40 | + let uniqueSections = $derived( |
| 41 | + sections.map((section) => { |
| 42 | + return { |
| 43 | + ...section, |
| 44 | + uniqueid: |
| 45 | + section.id + |
| 46 | + section.heading.slice(1, 3) + |
| 47 | + (section?.summary?.slice(0, 2) ?? ""), |
| 48 | + }; |
| 49 | + }), |
| 50 | + ); |
49 | 51 |
|
50 |
| - let expandedSections = new SvelteSet( |
51 |
| - uniqueSections |
52 |
| - .filter((section) => section.expanded) |
53 |
| - .map((section) => section.uniqueid) |
| 52 | + let expandedSections = $derived( |
| 53 | + new SvelteSet( |
| 54 | + uniqueSections |
| 55 | + .filter((section) => section.expanded) |
| 56 | + .map((section) => section.uniqueid), |
| 57 | + ), |
54 | 58 | );
|
55 | 59 |
|
56 | 60 | let allExpanded = $derived(expandedSections.size === sections.length);
|
57 | 61 |
|
58 |
| - let ariaLiveValue: 'polite' | 'off' | 'assertive' | null | undefined = |
59 |
| - $state('polite'); |
| 62 | + let ariaLiveValue: "polite" | "off" | "assertive" | null | undefined = |
| 63 | + $state("polite"); |
60 | 64 |
|
61 | 65 | // Event handlers
|
62 | 66 |
|
|
67 | 71 | expandedSections.add(uniqueid);
|
68 | 72 | }
|
69 | 73 | //Announce the contents change when an accoridion section is expanded
|
70 |
| - ariaLiveValue = 'polite'; |
| 74 | + ariaLiveValue = "polite"; |
71 | 75 | }
|
72 | 76 |
|
73 | 77 | function toggleAll() {
|
74 | 78 | if (!allExpanded) {
|
75 | 79 | uniqueSections.forEach((section) =>
|
76 |
| - expandedSections.add(section.uniqueid) |
| 80 | + expandedSections.add(section.uniqueid), |
77 | 81 | );
|
78 | 82 | } else {
|
79 | 83 | expandedSections.clear();
|
80 | 84 | }
|
81 | 85 | //Don't announce all of the changes when we open all sections - this gets noisy and the content isn't associated with the label
|
82 |
| - ariaLiveValue = 'off'; |
| 86 | + ariaLiveValue = "off"; |
83 | 87 | }
|
84 | 88 |
|
85 | 89 | // Only use session storage logic if rememberIsExpandedState is true
|
|
92 | 96 | expandedSections.add(section.uniqueid);
|
93 | 97 | } else {
|
94 | 98 | const stored = sessionStorage.getItem(section.uniqueid);
|
95 |
| - if (stored === 'true') { |
| 99 | + if (stored === "true") { |
96 | 100 | expandedSections.add(section.uniqueid);
|
97 | 101 | }
|
98 | 102 | }
|
|
113 | 117 | uniqueSections.forEach((section) => {
|
114 | 118 | sessionStorage.setItem(
|
115 | 119 | section.uniqueid,
|
116 |
| - expandedSections.has(section.uniqueid).toString() |
| 120 | + expandedSections.has(section.uniqueid).toString(), |
117 | 121 | );
|
118 | 122 | });
|
119 | 123 | }
|
|
197 | 201 | class:govuk-accordion__section--expanded={isExpanded}
|
198 | 202 | >
|
199 | 203 | <div class="govuk-accordion__section-header">
|
200 |
| - {#if headingLevel.toLowerCase() == 'h2'} |
| 204 | + {#if headingLevel.toLowerCase() == "h2"} |
201 | 205 | <h2 class="govuk-accordion__section-heading">
|
202 | 206 | {@render headerContent(section, isExpanded)}
|
203 | 207 | </h2>
|
204 |
| - {:else if headingLevel.toLowerCase() == 'h3'} |
| 208 | + {:else if headingLevel.toLowerCase() == "h3"} |
205 | 209 | <h3 class="govuk-accordion__section-heading">
|
206 | 210 | {@render headerContent(section, isExpanded)}
|
207 | 211 | </h3>
|
208 |
| - {:else if headingLevel.toLowerCase() == 'h4'} |
| 212 | + {:else if headingLevel.toLowerCase() == "h4"} |
209 | 213 | <h4 class="govuk-accordion__section-heading">
|
210 | 214 | {@render headerContent(section, isExpanded)}
|
211 | 215 | </h4>
|
212 |
| - {:else if headingLevel.toLowerCase() == 'h5'} |
| 216 | + {:else if headingLevel.toLowerCase() == "h5"} |
213 | 217 | <h5 class="govuk-accordion__section-heading">
|
214 | 218 | {@render headerContent(section, isExpanded)}
|
215 | 219 | </h5>
|
216 |
| - {:else if headingLevel.toLowerCase() == 'h6'} |
| 220 | + {:else if headingLevel.toLowerCase() == "h6"} |
217 | 221 | <h6 class="govuk-accordion__section-heading">
|
218 | 222 | {@render headerContent(section, isExpanded)}
|
219 | 223 | </h6>
|
|
224 | 228 | class="govuk-accordion__section-content"
|
225 | 229 | aria-live={ariaLiveValue}
|
226 | 230 | hidden={!isExpanded}
|
227 |
| - role={uniqueSections.length < 6 ? 'region' : ''} |
| 231 | + role={uniqueSections.length < 6 ? "region" : ""} |
228 | 232 | aria-labelledby={uniqueSections.length < 6
|
229 |
| - ? section.uniqueid + '-button' |
230 |
| - : ''} |
| 233 | + ? section.uniqueid + "-button" |
| 234 | + : ""} |
231 | 235 | >
|
232 |
| - {#if typeof section.content === 'string'} |
| 236 | + {#if typeof section.content === "string"} |
233 | 237 | <p class="govuk-body">{section.content}</p>
|
234 | 238 | {:else}
|
235 | 239 | {@render section.content()}
|
|
0 commit comments