|
3 | 3 | import { browser } from "$app/environment";
|
4 | 4 | import IconSearch from "$lib/icons/IconSearch.svelte";
|
5 | 5 | import DOMPurify from "dompurify";
|
| 6 | + import { onMount } from "svelte"; |
6 | 7 |
|
7 | 8 | // Define the props based on GOV.UK documentation
|
8 | 9 | type Props = {
|
|
17 | 18 | name?: string; // Name attribute for input
|
18 | 19 | aria_controls?: string; // ID of controlled element
|
19 | 20 | button_text?: string; // Visually hidden button text
|
20 |
| - label_size?: "xl" | "l" | "m" | "s" | null; // Label text size |
| 21 | + label_size?: "xl" | "l" | "m" | "s" | "" | null; // Add "" to the type |
21 | 22 | wrap_label_in_a_heading?: boolean; // Wrap label in heading
|
22 | 23 | heading_level?: 1 | 2 | 3 | 4 | 5 | 6; // Heading level
|
23 | 24 | margin_bottom?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; // Component margin
|
|
46 | 47 |
|
47 | 48 | // --- Prop Defaults & Processing ---
|
48 | 49 | let {
|
49 |
| - value = "", |
| 50 | + value = $bindable(""), // Make value bindable |
50 | 51 | label_text = "Search on GOV.UK",
|
51 | 52 | label_id = undefined,
|
52 | 53 | inline_label = undefined, // Default depends on label_size
|
|
77 | 78 |
|
78 | 79 | // Generate default ID if none provided (only in browser)
|
79 | 80 | const defaultId = $derived(
|
80 |
| - label_id ?? |
| 81 | + label_id || |
81 | 82 | (browser
|
82 | 83 | ? `search-main-${crypto.randomUUID().slice(0, 8)}`
|
83 | 84 | : "search-main-ssr"),
|
84 | 85 | );
|
85 | 86 |
|
86 | 87 | // Determine if label should be inline
|
| 88 | + // If label_size is set, force isInlineLabel = false |
| 89 | + // Otherwise, respect inline_label if set to false, default to true |
87 | 90 | const isInlineLabel = $derived(
|
88 |
| - inline_label === undefined ? !label_size : inline_label, |
| 91 | + label_size |
| 92 | + ? false // If label_size is set, it's NOT inline |
| 93 | + : inline_label === false |
| 94 | + ? false // If no size, but explicitly set to false, it's NOT inline |
| 95 | + : true, // Otherwise (no size, inline_label is true or undefined), it IS inline |
89 | 96 | );
|
90 | 97 |
|
91 | 98 | // --- Derived Classes & Attributes ---
|
|
99 | 106 | `govuk-!-margin-bottom-${margin_bottom}`,
|
100 | 107 | size === "large" && "gem-c-search--large",
|
101 | 108 | homepage && "gem-c-search--homepage",
|
102 |
| - on_govuk_blue ? "gem-c-search--on-govuk-blue" : "gem-c-search--on-white", |
| 109 | + on_govuk_blue || homepage |
| 110 | + ? "gem-c-search--on-govuk-blue" |
| 111 | + : "gem-c-search--on-white", |
103 | 112 | !isInlineLabel && "gem-c-search--separate-label",
|
104 | 113 | classes,
|
105 | 114 | ),
|
106 | 115 | );
|
107 | 116 |
|
108 | 117 | const derivedLabelClasses = $derived(
|
109 | 118 | clsx(
|
110 |
| - // Only add default classes if NO custom class is provided |
111 |
| - !label_custom_class && |
112 |
| - (label_size |
113 |
| - ? [`govuk-label`, `govuk-label--${label_size}`] |
114 |
| - : "gem-c-search__label"), |
115 |
| - homepage && label_size && "gem-c-search__label--white", |
| 119 | + label_custom_class |
| 120 | + ? label_custom_class // If custom class, use it... |
| 121 | + : [ |
| 122 | + // Otherwise calculate standard classes: |
| 123 | + isInlineLabel ? "gem-c-search__label" : "govuk-label", // Base class depends on inline status |
| 124 | + !isInlineLabel && label_size ? `govuk-label--${label_size}` : null, // Size modifier only if separate and size set |
| 125 | + (!isInlineLabel && on_govuk_blue) || homepage |
| 126 | + ? "gem-c-search__label--white" |
| 127 | + : null, // White text only if separate and on blue |
| 128 | + ], |
| 129 | + // Margin applies if NOT inline, regardless of custom class |
116 | 130 | !isInlineLabel &&
|
117 | 131 | label_margin_bottom !== undefined &&
|
118 | 132 | label_margin_bottom >= 0 &&
|
119 | 133 | label_margin_bottom <= 9 &&
|
120 | 134 | `govuk-!-margin-bottom-${label_margin_bottom}`,
|
121 |
| - label_custom_class, // Always add the custom class if present |
122 | 135 | ),
|
123 | 136 | );
|
124 | 137 |
|
|
138 | 151 | });
|
139 | 152 |
|
140 | 153 | // --- Render Logic ---
|
| 154 | + // Define Tag based on heading_level |
141 | 155 | const Tag = $derived(`h${heading_level}`);
|
142 | 156 | </script>
|
143 | 157 |
|
|
165 | 179 | {@render LabelContent()}
|
166 | 180 | {/if}
|
167 | 181 |
|
168 |
| - {#if hint} |
| 182 | + {#if hint && !isInlineLabel && !(homepage || on_govuk_blue)} |
169 | 183 | <div id="{defaultId}-hint" class="govuk-hint">
|
170 | 184 | {hint}
|
171 | 185 | </div>
|
|
181 | 195 | {name}
|
182 | 196 | title="Search"
|
183 | 197 | type="search"
|
| 198 | + placeholder={hint && !isInlineLabel && (homepage || on_govuk_blue) |
| 199 | + ? hint |
| 200 | + : undefined} |
184 | 201 | bind:value
|
185 |
| - aria-describedby={hint ? `${defaultId}-hint` : undefined} |
| 202 | + aria-describedby={hint |
| 203 | + ? `${defaultId}-hint` |
| 204 | + : label_text |
| 205 | + ? `${defaultId}-label` |
| 206 | + : undefined} |
186 | 207 | autocorrect={correctionValue}
|
187 | 208 | autocapitalize={correctionValue}
|
188 | 209 | />
|
|
260 | 281 | }
|
261 | 282 | }
|
262 | 283 |
|
263 |
| - .govuk-frontend-supported .gem-c-search__label { |
| 284 | + /* Apply :global() to the external .govuk-frontend-supported class as it's not scoped to the component */ |
| 285 | + :global(.govuk-frontend-supported) .gem-c-search__label { |
264 | 286 | position: absolute;
|
265 | 287 | left: 2px;
|
266 | 288 | top: 2px;
|
|
272 | 294 | background: #fff;
|
273 | 295 | }
|
274 | 296 |
|
275 |
| - .govuk-frontend-supported .gem-c-search--separate-label .gem-c-search__label { |
| 297 | + /* Apply :global() to the external .govuk-frontend-supported class as it's not scoped to the component */ |
| 298 | + :global(.govuk-frontend-supported) |
| 299 | + .gem-c-search--separate-label |
| 300 | + .gem-c-search__label { |
276 | 301 | color: #0b0c0c;
|
277 | 302 | }
|
278 | 303 |
|
| 304 | + /* REMOVED :global() - Restore original scoped rule */ |
279 | 305 | .gem-c-search__input[type="search"] {
|
280 | 306 | margin: 0;
|
281 | 307 | width: 100%;
|
|
401 | 427 | background-color: hsl(180, 4.347826087%, 9.5098039216%);
|
402 | 428 | }
|
403 | 429 |
|
404 |
| - .govuk-frontend-supported .gem-c-search--on-govuk-blue .gem-c-search__label { |
| 430 | + :global(.govuk-frontend-supported) |
| 431 | + .gem-c-search--on-govuk-blue |
| 432 | + .gem-c-search__label { |
405 | 433 | color: #505a5f;
|
406 | 434 | }
|
407 | 435 |
|
|
0 commit comments