frontend.blogwoman.de/src/components/ui/SeriesPill.tsx
CCS Admin 75f31b1cb8 Fix design errors, UX issues, and improve accessibility
Critical fixes:
- Add group class to Card component for image zoom on hover
- Create Skeleton, EmptyState, and Pagination UI components
- Add proper empty state to PostsListBlock instead of returning null

Visual consistency:
- Fix Button hover states (subtler secondary/tertiary transitions)
- Add badge variants for FavoritesBlock with German labels
- Increase overlay opacity in HeroBlock/VideoBlock for better contrast

Accessibility improvements:
- Add skip-to-content link in layout for keyboard navigation
- Add focus-visible states to FAQ accordion and Testimonials carousel
- Implement focus trap in MobileMenu with proper ARIA attributes
- Enhance 404 page with helpful navigation links

Polish:
- Fix DividerBlock text contrast
- Fix lint errors (Link component, const declaration)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 15:16:17 +00:00

107 lines
2.5 KiB
TypeScript

import { cn } from '@/lib/utils'
type SeriesType =
| 'grfi'
| 'investment'
| 'pl'
| 'spark'
| 'inner-circle'
| 'reset'
| 'decision'
| 'regeneration'
| 'm2m'
| 'backstage'
type PillSize = 'sm' | 'md' | 'lg'
interface SeriesPillProps {
series: SeriesType | string
children: React.ReactNode
size?: PillSize
className?: string
}
const seriesColors: Record<string, { bg: string; text: string }> = {
grfi: { bg: 'bg-sand', text: 'text-espresso' },
investment: { bg: 'bg-brass', text: 'text-soft-white' },
pl: { bg: 'bg-bordeaux', text: 'text-soft-white' },
spark: { bg: 'bg-rose', text: 'text-espresso' },
'inner-circle': { bg: 'bg-gold', text: 'text-espresso' },
reset: { bg: 'bg-sand', text: 'text-espresso' },
decision: { bg: 'bg-sand', text: 'text-espresso' },
regeneration: { bg: 'bg-sand', text: 'text-espresso' },
m2m: { bg: 'bg-sand', text: 'text-espresso' },
backstage: { bg: 'bg-warm-gray', text: 'text-espresso' },
}
const sizeClasses: Record<PillSize, string> = {
sm: 'px-2 py-1 text-[10px]',
md: 'px-3.5 py-1.5 text-[11px]',
lg: 'px-6 py-2.5 text-[13px]',
}
export function SeriesPill({
series,
children,
size = 'md',
className,
}: SeriesPillProps) {
const seriesKey = series.toLowerCase().replace(/\s+/g, '-')
const colors = seriesColors[seriesKey] || seriesColors.grfi
return (
<span
className={cn(
'inline-flex items-center',
sizeClasses[size],
colors.bg,
colors.text,
'font-bold tracking-[0.08em] uppercase',
'rounded-full',
className
)}
>
{children}
</span>
)
}
// Generic badge component for other use cases
interface BadgeProps {
variant?: 'default' | 'new' | 'popular' | 'success' | 'warning' | 'error' | 'investment' | 'daily' | 'grfi'
children: React.ReactNode
className?: string
}
const badgeVariants: Record<string, string> = {
default: 'bg-sand text-espresso',
new: 'bg-brass text-soft-white',
popular: 'bg-bordeaux text-soft-white',
success: 'bg-success text-soft-white',
warning: 'bg-warning text-espresso',
error: 'bg-error text-soft-white',
investment: 'bg-gold text-espresso',
daily: 'bg-sand text-espresso',
grfi: 'bg-rose text-espresso',
}
export function Badge({
variant = 'default',
children,
className,
}: BadgeProps) {
return (
<span
className={cn(
'inline-flex items-center',
'px-2.5 py-1',
'text-xs font-semibold',
'rounded-md',
badgeVariants[variant],
className
)}
>
{children}
</span>
)
}