mirror of
https://github.com/gustavosett/Windows-11-Clipboard-History-For-Linux
synced 2026-04-25 17:15:35 +02:00
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:
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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={
|
||||
|
||||
@@ -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) => (
|
||||
|
||||
32
src/components/common/SectionHeader.tsx
Normal file
32
src/components/common/SectionHeader.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user