Tags
Overview
The tags system comprises four components that handle tag display, filtering, sidebar navigation, and bulk management. TagsCards renders a responsive grid of tag cards for browsing; TagsFilter (tags-items) provides a searchable checkbox list with sort controls; TagsItemsColumn builds a full sidebar with tag navigation, active filters display, and sort options; and TagsModal shows selected tags in a modal dialog with removal capability.
Architecture
template/components/
tags-cards.tsx # Grid display of tag cards with navigation
tags-items.tsx # Searchable tag filter with checkboxes and sort
tags-items-column.tsx # Sidebar column with tag navigation and filters
tags-modal.tsx # Modal for viewing/removing selected tags
TagsCards
Import
import { TagsCards } from "@/components/tags-cards";
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
tags | Tag[] | Yes | - | Array of tag objects to display as cards. |
basePath | string | No | undefined | Base URL path for tag links (currently unused; navigation uses /?tags={id}). |
className | string | No | undefined | Additional CSS classes for each tag card wrapper. |
compact | boolean | No | false | Compact mode with smaller padding, text sizes, and no text truncation. Ideal for dedicated tags listing pages. |
Usage Examples
Basic Usage
<TagsCards tags={tags} />
Compact Mode for Tag Listing Page
<TagsCards tags={tags} compact />
Behavior
- Clicking a tag navigates to
/?tags={tagId}to filter the main listing. - Active tags (matching URL
?tagsparam) receive a highlighted border style. - A loading spinner overlay appears on the clicked card during navigation.
- Returns
nullwhen the tags array is empty.
Card Anatomy
Each card displays:
- Hash icon in a themed container.
- Tag name with
capitalizeand hover color transition. - Arrow icon that slides in on hover.
- Item count badge at the bottom showing
{count} items. - Gradient accent in the bottom-right corner.
TagsFilter
Import
import TagsFilter from "@/components/tags-items";
// Types
import type { TagOption, SortOption, TagsFilterProps } from "@/components/tags-items";
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
tags | TagOption[] | Yes | - | Array of tag options, each with id and name. |
onTagsChange | (selectedTags: string[]) => void | Yes | - | Callback fired when the tag selection changes. Receives an array of selected tag IDs. |
onSortChange | (sortOption: string) => void | Yes | - | Callback fired when the sort option changes. |
className | string | No | undefined | Additional CSS classes for the container. |
Built-in Sort Options
| Value | Label |
|---|---|
time-desc | Sort by Time (dsc) |
time-asc | Sort by Time (asc) |
name-desc | Sort by Name (dsc) |
name-asc | Sort by Name (asc) |
Usage Examples
<TagsFilter
tags={[
{ id: "react", name: "React" },
{ id: "vue", name: "Vue" },
{ id: "angular", name: "Angular" },
]}
onTagsChange={(selected) => console.log("Selected:", selected)}
onSortChange={(sort) => console.log("Sort:", sort)}
/>
Features
- Search input filters tags by name in real time.
- Select all checkbox toggles all visible (filtered) tags.
- Individual checkboxes for each tag with theme-colored active state.
- Sort dropdown with collapsible option list.
TagsItemsColumn
Import
import { TagsItemsColumn } from "@/components/tags-items-column";
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
total | number | Yes | - | Total number of items across all tags. Displayed in the "All" link badge. |
tag | Tag[] | Yes | - | Array of tag objects used to populate the sidebar navigation. |
Usage Examples
<TagsItemsColumn total={150} tag={tags} />
Layout
The component renders two layouts:
| Breakpoint | Layout |
|---|---|
Mobile (md:hidden) | Collapsible Accordion containing the tag list. |
Desktop (hidden md:flex) | Fixed-width sidebar (max 280px / 256px) with search, tag list, active filters, and sort controls. |
Desktop Sidebar Sections
- Search bar -
SearchInputfor filtering items by keyword. - Tags list - Scrollable list of tag links with item counts. Active tag is highlighted with
bg-theme-primary-500 text-white. Tag names longer than 20 characters are truncated with tooltip. - Active filters - Displays current search term, selected tags (removable), and active sort option. Includes a "Clear All" button.
- Sort controls -
SortControlcomponent for changing sort order.
TagsModal
Import
import { TagsModal } from "@/components/tags-modal";
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
isOpen | boolean | Yes | - | Controls modal visibility. |
onClose | () => void | Yes | - | Callback to close the modal. |
selectedTags | string[] | Yes | - | Array of currently selected tag IDs. |
tags | Tag[] | Yes | - | Full list of available tags (used to resolve names from IDs). |
onRemoveTag | (tagId: string) => void | Yes | - | Callback fired when a tag chip is clicked for removal. |
Usage Examples
<TagsModal
isOpen={showTagsModal}
onClose={() => setShowTagsModal(false)}
selectedTags={selectedTagIds}
tags={allTags}
onRemoveTag={(tagId) => removeTag(tagId)}
/>
Features
- Displays selected tags as removable chips with a
xbutton. - Scrollable container (
max-h-60) for many selected tags. - Empty state with animated icon, heading, and descriptive text.
- Close button at the bottom using theme primary color.
- All text is translatable via the
tagsModalnamespace.
Styling
- TagsCards: Responsive grid from 1 to 6 columns depending on breakpoint and container width mode. Cards use glassmorphic styling with
backdrop-blur-mdand gradient accents. - TagsFilter: Dark-themed panel (
bg-gray-900) designed for overlay/sidebar use withbg-gray-800/50search input. - TagsItemsColumn: Light/dark adaptive sidebar with
backdrop-blur-xsand bordered sections. - TagsModal: Uses HeroUI
Modalwith custom class overrides for header border and backdrop blur.
Accessibility
- TagsCards: Cards have
role="button",tabIndex={0},aria-label, and keyboard event handlers for Enter/Space. - TagsFilter: Checkbox inputs have proper
<label>wrappers for click targeting. Search input has a visible search icon placeholder. - TagsItemsColumn: Uses HeroUI
Accordionwitharia-label="Tags"for the mobile collapsible. Tag links use HeroUITooltipfor truncated names. - TagsModal: HeroUI
Modalprovides built-in focus trapping, Escape to close, and backdrop click to dismiss.
Related Components
- Filter System - Parent filtering infrastructure that coordinates tag selection.
- Categories Grid - Similar card-based browsing for categories.
- Sort Menu - Standalone sort dropdown used alongside tag filters.