feat: introduce SectionHeader component (#185)

* feat: introduce SectionHeader component

* fix: use ReactNode for label

* fix: adjust gap spacing in SectionHeader component

* fix: update text color classes in SectionHeader

* fix: label prop
This commit is contained in:
Gustavo Carvalho
2026-02-15 01:06:55 -03:00
committed by GitHub
parent 94d6d9f8fa
commit c16f61dc35
5 changed files with 51 additions and 21 deletions

View File

@@ -326,7 +326,7 @@ function SettingsApp() {
{(isSaving || saveMessage) && (
<div
className={clsx(
'flex items-center gap-2 px-3 py-1.5 rounded-full text-xs font-medium duration-300',
'flex items-center gap-2 px-3 py-1.5 rounded-full text-xs font-medium',
saveMessage?.includes('Error')
? 'bg-red-500/10 text-red-500'
: isDark

View File

@@ -4,6 +4,7 @@ import { clsx } from 'clsx'
import { Clock } from 'lucide-react'
import { useEmojiPicker } from '../hooks/useEmojiPicker'
import { SearchBar } from './common/SearchBar'
import { SectionHeader } from './common/SectionHeader'
import type { Emoji } from '../services/emojiService'
import { PickerLayout } from './common/PickerLayout'
@@ -239,11 +240,8 @@ export function EmojiPicker({ isDark, opacity }: EmojiPickerProps) {
{/* Recent emojis (only show when not searching) */}
{!searchQuery && recentEmojis.length > 0 && (
<div className="px-3 pb-2 flex-shrink-0">
<div className="flex items-center gap-1.5 mb-1.5">
<Clock className="w-3 h-3 dark:text-win11-text-tertiary text-win11Light-text-secondary" />
<span className="text-xs dark:text-win11-text-tertiary text-win11Light-text-secondary">
Recently used
</span>
<div className="mb-1.5">
<SectionHeader icon={<Clock size={12} />} label="Recently used" />
</div>
<div
ref={recentGridRef}

View File

@@ -4,6 +4,7 @@ import { clsx } from 'clsx'
import { Search, RefreshCw, TrendingUp } from 'lucide-react'
import { useGifPicker } from '../hooks/useGifPicker'
import { SearchBar } from './common/SearchBar'
import { SectionHeader } from './common/SectionHeader'
import type { Gif } from '../types/gif'
import { getTertiaryBackgroundStyle } from '../utils/themeUtils'
@@ -320,19 +321,20 @@ export function GifPicker({ isDark, opacity }: GifPickerProps) {
/>
}
subHeader={
<div className="flex items-center gap-2 text-xs dark:text-win11-text-secondary text-win11Light-text-secondary">
<div className="px-3 pb-2 flex-shrink-0">
{searchQuery ? (
<>
<Search size={12} />
<span>Results for "{searchQuery}"</span>
</>
<SectionHeader
icon={<Search size={12} />}
label={`Results for "${searchQuery}"`}
rightContent={isLoading && <RefreshCw size={12} className="animate-spin" />}
/>
) : (
<>
<TrendingUp size={12} />
<span>Trending GIFs</span>
</>
<SectionHeader
icon={<TrendingUp size={12} />}
label="Trending GIFs"
rightContent={isLoading && <RefreshCw size={12} className="animate-spin" />}
/>
)}
{isLoading && <RefreshCw size={12} className="animate-spin ml-auto" />}
</div>
}
footer={

View File

@@ -4,6 +4,7 @@ import { clsx } from 'clsx'
import { Clock } from 'lucide-react'
import { useSymbolPicker } from '../hooks/useSymbolPicker'
import { SearchBar } from './common/SearchBar'
import { SectionHeader } from './common/SectionHeader'
import type { SymbolItem } from '../services/symbolService'
import { PickerLayout } from './common/PickerLayout'
@@ -229,11 +230,8 @@ export function SymbolPicker({ isDark, opacity }: SymbolPickerProps) {
{/* Recent symbols */}
{!searchQuery && !selectedCategory && recentSymbols.length > 0 && (
<div className="px-3 pb-2 flex-shrink-0">
<div className="flex items-center gap-1.5 mb-1.5">
<Clock className="w-3 h-3 dark:text-win11-text-tertiary text-win11Light-text-secondary" />
<span className="text-xs dark:text-win11-text-tertiary text-win11Light-text-secondary">
Recently used
</span>
<div className="mb-1.5">
<SectionHeader icon={<Clock size={12} />} label="Recently used" />
</div>
<div ref={recentGridRef} className="flex flex-wrap gap-1">
{recentSymbols.slice(0, 16).map((symbol, index) => (

View File

@@ -0,0 +1,32 @@
import { type ReactNode } from 'react'
import { clsx } from 'clsx'
export interface SectionHeaderProps {
/** Icon to display (e.g., <TrendingUp size={12} /> or <Clock size={12} />) */
icon?: ReactNode
/** Label content to display (supports text, styled elements, or localization components) */
label: ReactNode
/** Additional content to display on the right (e.g., loading spinner) */
rightContent?: ReactNode
/** Additional CSS classes */
className?: string
}
/**
* Shared component for section headers like "Trending GIFs" and "Recently used"
*/
export function SectionHeader({ icon, label, rightContent, className }: SectionHeaderProps) {
return (
<div
className={clsx(
'flex items-center gap-1.5 text-xs',
'dark:text-win11-text-tertiary text-win11Light-text-tertiary',
className
)}
>
{icon}
<span>{label}</span>
{rightContent && <div className="ml-auto">{rightContent}</div>}
</div>
)
}