Skip to content

Commit 2edd4d9

Browse files
Merge pull request #64 from communitiesuk/search-with-autocomplete-component
New autocomplete search component and updates to search component
2 parents 940a0bf + aed7c5e commit 2edd4d9

File tree

14 files changed

+2186
-38
lines changed

14 files changed

+2186
-38
lines changed

package-lock.json

Lines changed: 33 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"@tailwindcss/forms": "^0.5.9",
4646
"@tailwindcss/typography": "^0.5.15",
4747
"@types/eslint": "^9.6.0",
48+
"accessible-autocomplete": "^3.0.1",
4849
"autoprefixer": "^10.4.20",
4950
"eslint": "^9.7.0",
5051
"eslint-config-prettier": "^9.1.0",

src/app.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
@import "tailwindcss/components";
33
@import "tailwindcss/utilities";
44

5-
65
@import "/css/govuk-additional.css";
76
@import "/css/code-block.css";
87
@import "/css/fonts.css";

src/lib/components/ui/Search.svelte

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { browser } from "$app/environment";
44
import IconSearch from "$lib/icons/IconSearch.svelte";
55
import DOMPurify from "dompurify";
6+
import { onMount } from "svelte";
67
78
// Define the props based on GOV.UK documentation
89
type Props = {
@@ -17,7 +18,7 @@
1718
name?: string; // Name attribute for input
1819
aria_controls?: string; // ID of controlled element
1920
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
2122
wrap_label_in_a_heading?: boolean; // Wrap label in heading
2223
heading_level?: 1 | 2 | 3 | 4 | 5 | 6; // Heading level
2324
margin_bottom?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; // Component margin
@@ -46,7 +47,7 @@
4647
4748
// --- Prop Defaults & Processing ---
4849
let {
49-
value = "",
50+
value = $bindable(""), // Make value bindable
5051
label_text = "Search on GOV.UK",
5152
label_id = undefined,
5253
inline_label = undefined, // Default depends on label_size
@@ -77,15 +78,21 @@
7778
7879
// Generate default ID if none provided (only in browser)
7980
const defaultId = $derived(
80-
label_id ??
81+
label_id ||
8182
(browser
8283
? `search-main-${crypto.randomUUID().slice(0, 8)}`
8384
: "search-main-ssr"),
8485
);
8586
8687
// 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
8790
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
8996
);
9097
9198
// --- Derived Classes & Attributes ---
@@ -99,26 +106,32 @@
99106
`govuk-!-margin-bottom-${margin_bottom}`,
100107
size === "large" && "gem-c-search--large",
101108
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",
103112
!isInlineLabel && "gem-c-search--separate-label",
104113
classes,
105114
),
106115
);
107116
108117
const derivedLabelClasses = $derived(
109118
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
116130
!isInlineLabel &&
117131
label_margin_bottom !== undefined &&
118132
label_margin_bottom >= 0 &&
119133
label_margin_bottom <= 9 &&
120134
`govuk-!-margin-bottom-${label_margin_bottom}`,
121-
label_custom_class, // Always add the custom class if present
122135
),
123136
);
124137
@@ -138,6 +151,7 @@
138151
});
139152
140153
// --- Render Logic ---
154+
// Define Tag based on heading_level
141155
const Tag = $derived(`h${heading_level}`);
142156
</script>
143157

@@ -165,7 +179,7 @@
165179
{@render LabelContent()}
166180
{/if}
167181

168-
{#if hint}
182+
{#if hint && !isInlineLabel && !(homepage || on_govuk_blue)}
169183
<div id="{defaultId}-hint" class="govuk-hint">
170184
{hint}
171185
</div>
@@ -181,8 +195,15 @@
181195
{name}
182196
title="Search"
183197
type="search"
198+
placeholder={hint && !isInlineLabel && (homepage || on_govuk_blue)
199+
? hint
200+
: undefined}
184201
bind:value
185-
aria-describedby={hint ? `${defaultId}-hint` : undefined}
202+
aria-describedby={hint
203+
? `${defaultId}-hint`
204+
: label_text
205+
? `${defaultId}-label`
206+
: undefined}
186207
autocorrect={correctionValue}
187208
autocapitalize={correctionValue}
188209
/>
@@ -260,7 +281,8 @@
260281
}
261282
}
262283
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 {
264286
position: absolute;
265287
left: 2px;
266288
top: 2px;
@@ -272,10 +294,14 @@
272294
background: #fff;
273295
}
274296
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 {
276301
color: #0b0c0c;
277302
}
278303
304+
/* REMOVED :global() - Restore original scoped rule */
279305
.gem-c-search__input[type="search"] {
280306
margin: 0;
281307
width: 100%;
@@ -401,7 +427,9 @@
401427
background-color: hsl(180, 4.347826087%, 9.5098039216%);
402428
}
403429
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 {
405433
color: #505a5f;
406434
}
407435

0 commit comments

Comments
 (0)