A Svelte and Tailwind library that provides components for building search functionalities, including SearchDialog
, SearchItem
, and SearchGroup
.
Before using this library, ensure you have the following installed in your project:
- Svelte - A component framework that compiles code to tiny, framework-less vanilla JS.
- Tailwind CSS - A utility-first CSS framework for rapid UI development.
- @tailwindcss/forms - A plugin that provides a basic reset for form styles.
Install the library and its peer dependencies using npm:
npm install svelter-search-ui tailwindcss @tailwindcss/forms
Note: Make sure you have Svelte set up in your project. If not, you can create a new Svelte project
In the consuming project's tailwind.config.js (or tailwind.config.cjs), you need to include your library's components in the content array:
// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{html,js,svelte,ts}',
'./node_modules/svelter-search-ui/**/*.{html,js,svelte,ts}',
],
theme: {
extend: {},
},
plugins: [
require('@tailwindcss/forms'),
],
};
Import the components into your Svelte application:
<script>
import { SearchDialog, SearchItem, SearchGroup } from 'svelter-search-ui';
</script>
SearchDialog
is the main component that renders the search interface.
show
(boolean, default:false
): Controls the visibility of the search dialog.placeholder
(string, default:"Search..."
): Placeholder text for the search input.resultCount
(number, default:0
): The number of search results found.isLoading
(boolean, default:false
): Indicates if the search results are loading.showRecent
(boolean, default:true
): Determines if recent search items should be displayed when there's no input.noRecentItemsText
(string, default:"No recent searches to show"
): Text to display when there are no recent searches.recentItemsGroupName
(string, default:"Recent Searches"
): The name for the recent items group.
search
: Dispatched when the search input changes (after a debounce of 350ms). The event detail contains{ value }
.
recent-results
: Slot to customize the recent search results section.no-recent-results
: Slot to customize the content when there are no recent searches.info
: Slot to provide additional information or help content.not-found
: Slot to customize the content when no search results are found.search-results
: Slot to display the search results.footer
: Slot to customize the footer content.
<script>
import { SearchDialog } from 'svelter-search-ui';
let showDialog = true;
function handleSearch(event) {
const searchValue = event.detail.value;
// Perform search logic here
}
</script>
<SearchDialog
bind:show={showDialog}
placeholder="Type to search..."
on:search={handleSearch}
>
<!-- Customize slots if needed -->
</SearchDialog>
SearchItem
represents an individual search result or suggestion.
title
(string): The title of the search item.url
(string, default:"#"
): The URL associated with the item.target
(string, optional): Specifies where to open the linked document ("_blank"
,"_self"
, etc.).subtitle
(string, optional): A brief description or subtitle.isRecentItem
(boolean, default:false
): Indicates if the item is a recent search.
select
: Dispatched when the search item is selected.
media
: Slot to customize the media/icon displayed alongside the item.
<SearchItem
title="Item Title"
subtitle="Item subtitle"
url="/item-url"
target="_blank"
on:select={() => {
// Handle item selection
}}
>
<!-- Customize the media slot if needed -->
<div slot="media">
<!-- Custom icon or image -->
</div>
</SearchItem>
SearchGroup
groups multiple SearchItem
components under a common category.
name
(string): The name of the group.resultCount
(number, optional): The number of items in the group.
- Default Slot: Place your
SearchItem
components here.
<SearchGroup name="Group Name" resultCount={2}>
<SearchItem title="Item 1" />
<SearchItem title="Item 2" />
</SearchGroup>
Here's a basic example of how to use the components together:
<script>
import { SearchDialog, SearchItem, SearchGroup } from 'svelter-search-ui';
let showDialog = true;
let searchResults = [];
let isLoading = false;
function handleSearch(event) {
const searchValue = event.detail.value;
isLoading = true;
// Simulate async search operation
setTimeout(() => {
searchResults = [
{ title: 'Apple', subtitle: 'A sweet red fruit' },
{ title: 'Banana', subtitle: 'A long yellow fruit' },
];
isLoading = false;
}, 1000);
}
</script>
<SearchDialog
bind:show={showDialog}
isLoading={isLoading}
resultCount={searchResults.length}
on:search={handleSearch}
>
<ul slot="search-results">
<SearchGroup name="Fruits" resultCount={searchResults.length}>
{#each searchResults as result}
<SearchItem
title={result.title}
subtitle={result.subtitle}
on:select={() => (showDialog = false)}
/>
{/each}
</SearchGroup>
</ul>
</SearchDialog>
This project is licensed under the MIT License.