BillTracker/client/components/brand/Brand.tsx

54 lines
1.6 KiB
TypeScript

import type { ComponentProps } from 'react';
import { cn } from '@/lib/utils';
import { BRAND, BRAND_GLYPHS, type BrandGlyphName } from '@/lib/brand';
type ImgProps = Omit<ComponentProps<'img'>, 'src' | 'alt'>;
export function BrandMark({ className, ...props }: ImgProps) {
return (
<img
src={BRAND.assets.logo}
alt={BRAND.name}
className={cn('object-contain', className)}
{...props}
/>
);
}
export function BrandWordmark({ compact = false, className }: { compact?: boolean; className?: string }) {
return (
<span className={cn('font-semibold tracking-tight text-foreground', className)}>
{compact ? BRAND.compactName : BRAND.name}
</span>
);
}
export function BrandGlyph({
name,
className,
iconClassName,
}: {
name: BrandGlyphName;
className?: string;
iconClassName?: string;
}) {
const glyph = BRAND_GLYPHS[name];
const Icon = glyph.icon;
return (
<span
className={cn(
'relative inline-grid h-10 w-10 shrink-0 place-items-center overflow-hidden rounded-xl',
'border border-primary/20 bg-primary/[0.08] text-primary shadow-sm shadow-primary/10',
'before:absolute before:inset-x-2 before:bottom-1.5 before:h-4 before:rounded-t-sm before:bg-gradient-to-t before:from-primary/25 before:to-primary/5',
'after:absolute after:inset-x-3 after:bottom-1.5 after:h-6 after:rounded-t-sm after:border-l after:border-r after:border-primary/15',
className,
)}
aria-label={glyph.label}
role="img"
>
<Icon className={cn('relative z-10 h-5 w-5', iconClassName)} />
</span>
);
}