Search results
Install
npx shadcn add @klarhimmel/app-search-resultsUsage
import { Theme } from '@/components/klarhimmel/theme/style';
import { BlockSurface } from '@/components/klarhimmel/blocks/surface';
import AppSearchResults from '@/components/klarhimmel/blocks/app-search-results';
export default function Section() {
return (
<Theme theme="brand">
<BlockSurface>
<AppSearchResults props={{
"eyebrow": "Exempelhotellet",
"title": "Search the hotel",
"description": "Rooms, treatments and events in one place.",
"searchLabel": "Search",
"searchButton": "Search",
"query": "spa",
"facets": [
{
"name": "Type",
"options": [
{
"label": "Treatments",
"checked": false
},
{
"label": "Rooms",
"checked": false
},
{
"label": "Events",
"checked": false
}
]
},
{
"name": "Price",
"options": [
{
"label": "Under 1 000 kr",
"checked": false
},
{
"label": "1 000 kr or more",
"checked": false
}
]
}
],
"results": [
{
"title": "Spa day for two",
"summary": "Pool, sauna and a sixty-minute treatment each, with lunch in the garden room.",
"href": "#spa-day",
"meta": "Treatments · 1 800 kr",
"matches": [
"Treatments",
"1 000 kr or more"
]
},
{
"title": "Deep tissue massage",
"summary": "Sixty minutes with a therapist, booked in the spa on the ground floor.",
"href": "#massage",
"meta": "Treatments · 890 kr",
"matches": [
"Treatments",
"Under 1 000 kr"
]
},
{
"title": "Room 311, balcony and bath",
"summary": "A double room with spa access included for every night of your stay.",
"href": "#room-311",
"meta": "Rooms · 1 490 kr",
"matches": [
"Rooms",
"1 000 kr or more"
]
},
{
"title": "Spa weekend for groups",
"summary": "Eight to twenty guests: treatments, dinner and a guided morning swim.",
"href": "#group-weekend",
"meta": "Events · 14 500 kr",
"matches": [
"Events",
"1 000 kr or more"
]
},
{
"title": "Spa gift card",
"summary": "A card for any treatment, valid for twelve months and sent by email.",
"href": "#gift-card",
"meta": "Treatments · 500 kr",
"matches": [
"Treatments",
"Under 1 000 kr"
]
}
],
"resultsLabel": "results",
"singular": "result",
"forLabel": "for",
"removeLabel": "Remove filter",
"clearAll": "Clear all filters",
"filtersLabel": "Filters",
"noResults": {
"title": "Nothing matches that search",
"hint": "Check the spelling, use fewer words or remove a filter.",
"suggestionsLabel": "Try one of these"
},
"suggestions": [
"massage",
"sauna",
"weekend"
],
"state": "filled",
"messages": {
"loading": "Searching…",
"error": "The search failed. Try again.",
"retry": "Try again"
}
}} />
</BlockSurface>
</Theme>
);
}States
search results in 4 forms: filled, empty, loading, error.
state: filled
Exempelhotellet
Search the hotel
Rooms, treatments and events in one place.
Filters
The search failed. Try again.Searching…5 results for “spa”
Spa day for two
Pool, sauna and a sixty-minute treatment each, with lunch in the garden room.
Treatments · 1 800 kr
- Treatments
- 1 000 kr or more
Deep tissue massage
Sixty minutes with a therapist, booked in the spa on the ground floor.
Treatments · 890 kr
- Treatments
- Under 1 000 kr
Room 311, balcony and bath
A double room with spa access included for every night of your stay.
Rooms · 1 490 kr
- Rooms
- 1 000 kr or more
Spa weekend for groups
Eight to twenty guests: treatments, dinner and a guided morning swim.
Events · 14 500 kr
- Events
- 1 000 kr or more
Spa gift card
A card for any treatment, valid for twelve months and sent by email.
Treatments · 500 kr
- Treatments
- Under 1 000 kr
Nothing matches that search
Check the spelling, use fewer words or remove a filter.
Try one of these
state: empty
Exempelhotellet
Search the hotel
Rooms, treatments and events in one place.
Filters
The search failed. Try again.Searching…0 results for “spa”
Nothing matches that search
Check the spelling, use fewer words or remove a filter.
Try one of these
state: loading
Exempelhotellet
Search the hotel
Rooms, treatments and events in one place.
Filters
The search failed. Try again.Searching…Nothing matches that search
Check the spelling, use fewer words or remove a filter.
Try one of these
state: error
Exempelhotellet
Search the hotel
Rooms, treatments and events in one place.
Filters
The search failed. Try again.Searching…Nothing matches that search
Check the spelling, use fewer words or remove a filter.
Try one of these
Notes
When to use it
A results page with a search box, checkbox filters and a count. For a plain sortable list of records, `app-data-table` and `app-data-filters` are the better pair; this block is for content that people search by words.
Writing for it
- Each result has a title (80), a summary (160) and a matches list of up to 3 words. The matches must be written exactly like the facet option labels, because that is how filtering and the counts work. - Within one facet the options add up, and across facets they narrow. Make that obvious in the facet names (30), for example Type and Price, not two facets that overlap. - Give suggestions (up to 4, 40 characters each) as real searches that return something, since they only appear on the no-results state.
Watch out for
The text search runs on the results you supply, so 12 results is the ceiling and anything beyond that must be paged by your own app. The count in each option updates with the other filters and shows blank outside the filled state.
Pairs well with
Usage
The block in a page, with its default content (long lists shortened). Every prop is in the table below.
import { Theme } from '@/components/klarhimmel/theme/style';
import { BlockSurface } from '@/components/klarhimmel/blocks/surface';
import AppSearchResults from '@/components/klarhimmel/blocks/app-search-results';
export default function Section() {
return (
<Theme theme="brand">
<BlockSurface>
<AppSearchResults props={{
"eyebrow": "Exempelhotellet",
"title": "Search the hotel",
"description": "Rooms, treatments and events in one pla…",
"searchLabel": "Search",
"searchButton": "Search",
"query": "spa",
"facets": [
{
"name": "Type",
"options": [
{
"label": "Treatments",
"checked": false
}
]
}
],
"results": [
{
"title": "Spa day for two",
"summary": "Pool, sauna and a sixty-minute treatmen…",
"href": "#spa-day",
"meta": "Treatments · 1 800 kr",
"matches": [
"Treatments"
]
}
],
"resultsLabel": "results",
"singular": "result",
"forLabel": "for",
"removeLabel": "Remove filter",
"clearAll": "Clear all filters",
"filtersLabel": "Filters",
"noResults": {
"title": "Nothing matches that search",
"hint": "Check the spelling, use fewer words or …",
"suggestionsLabel": "Try one of these"
},
"suggestions": [
"massage"
],
"state": "filled",
"messages": {
"loading": "Searching…",
"error": "The search failed. Try again.",
"retry": "Try again"
}
}} />
</BlockSurface>
</Theme>
);
}Props
facets are checkbox groups and results name the options they belong to (matches, in the same words as the option labels); counts are worked out from the results given. query is where the page opens; the labels build the announced count ("5 results for spa").
| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | 'Exempelhotellet' | Text, up to 60 characters. Optional; empty is not rendered. |
title | string | 'Search the hotel' | Text, up to 120 characters. |
description | string | 'Rooms, treatments and events in one…' | Text, up to 300 characters. Optional; empty is not rendered. |
searchLabel | string | 'Search' | Text, up to 40 characters. |
searchButton | string | 'Search' | Text, up to 30 characters. |
query | string | 'spa' | Text, up to 80 characters. |
facets | { name, options }[] | 2 items | List of 1 to 3. Each item: name, options. |
results | { title, summary, href, meta, matches }[] | 5 items | List of up to 12. Each item: title, summary, href, meta (optional), matches. |
resultsLabel | string | 'results' | Text, up to 20 characters. |
singular | string | 'result' | Text, up to 20 characters. |
forLabel | string | 'for' | Text, up to 10 characters. |
removeLabel | string | 'Remove filter' | Text, up to 30 characters. |
clearAll | string | 'Clear all filters' | Text, up to 30 characters. |
filtersLabel | string | 'Filters' | Text, up to 30 characters. |
noResults | { title, hint, suggestionsLabel } | {…} | Fields: title, hint, suggestionsLabel. |
suggestions | string[] | 3 items | List of up to 4. |
state | 'filled' | 'empty' | 'loading' | 'error' | 'filled' | One of 'filled', 'empty', 'loading', 'error'. |
messages | { loading, error, retry } | {…} | Fields: loading, error, retry. |
headingLevel | '1' | '2' | - | One of '1', '2'. Optional; empty is not rendered. |
Install
Installs
app-search-results- Badge
- Button
- Checkbox
- Input
- Skeleton
- About
- A results page: a search box, checkbox facets whose counts follow the other filters, active filters as removable chips, a result count that is announced when it changes, and a no-results state with suggestions.
- States
- Filled, empty, loading, error. The count is announced; removing a filter moves focus to it; no results offers suggestions.