Use WhyMyRatingLogo component with horizontal-full variant
- Copy logo component from brand site (standalone version) - Use horizontal-full variant in header - Tagline: 'Project Hub' Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Icon } from '@/components';
|
||||
import { Icon, WhyMyRatingLogo } from '@/components';
|
||||
|
||||
type TabId = 'home' | 'settings';
|
||||
|
||||
@@ -27,42 +27,7 @@ export default function Home() {
|
||||
<header className="sticky top-0 z-50 bg-white dark:bg-stone-950 border-b border-slate-200 dark:border-stone-800">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6">
|
||||
<div className="py-4 flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
{/* WhyRating Logo Icon */}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" width="44" height="44">
|
||||
<defs>
|
||||
<clipPath id="lens-clip">
|
||||
<circle cx="60" cy="62" r="21"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<polygon
|
||||
points="60,15 71.5,42 101,46 79.5,66 85,95 60,82 35,95 40.5,66 19,46 48.5,42"
|
||||
fill="#FBBC05"
|
||||
stroke="#FBBC05"
|
||||
strokeWidth="6"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<g>
|
||||
<circle cx="60" cy="62" r="27" fill="#1E293B"/>
|
||||
<line x1="83" y1="81" x2="95" y2="91" stroke="#1E293B" strokeWidth="9" strokeLinecap="round"/>
|
||||
<circle cx="60" cy="62" r="21" fill="#FEF3C7"/>
|
||||
<rect x="68" y="44" width="11" height="18" rx="1.5" fill="#15803D"/>
|
||||
<g clipPath="url(#lens-clip)">
|
||||
<rect x="42" y="58" width="11" height="35" rx="1.5" fill="#86EFAC"/>
|
||||
<rect x="55" y="51" width="11" height="42" rx="1.5" fill="#22C55E"/>
|
||||
<rect x="68" y="44" width="11" height="49" rx="1.5" fill="#15803D"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<div>
|
||||
<h1 className="font-bold text-xl text-slate-900 dark:text-stone-100">
|
||||
whyrating<span className="text-amber-500">.com</span>
|
||||
</h1>
|
||||
<p className="text-xs text-slate-500 dark:text-stone-500">
|
||||
The story behind your stars
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<WhyMyRatingLogo variant="horizontal-full" size={140} colorScheme="dark" />
|
||||
</div>
|
||||
|
||||
{/* Tabs */}
|
||||
|
||||
255
src/components/WhyMyRatingLogo.tsx
Normal file
255
src/components/WhyMyRatingLogo.tsx
Normal file
@@ -0,0 +1,255 @@
|
||||
'use client';
|
||||
|
||||
import { useId } from 'react';
|
||||
|
||||
export type LogoVariant = 'icon' | 'primary' | 'full' | 'horizontal' | 'horizontal-full' | 'horizontal-v2' | 'horizontal-full-v2';
|
||||
export type ColorScheme = 'light' | 'dark' | 'mono-dark' | 'mono-light';
|
||||
|
||||
interface WhyMyRatingLogoProps {
|
||||
size?: number;
|
||||
variant?: LogoVariant;
|
||||
colorScheme?: ColorScheme;
|
||||
tagline?: string;
|
||||
}
|
||||
|
||||
// Hub-specific defaults
|
||||
const config = {
|
||||
domain: 'whyrating',
|
||||
domainTLD: '.com',
|
||||
tagline: 'Project Hub',
|
||||
};
|
||||
|
||||
export function WhyMyRatingLogo({
|
||||
size = 120,
|
||||
variant = 'primary',
|
||||
colorScheme = 'light',
|
||||
tagline,
|
||||
}: WhyMyRatingLogoProps) {
|
||||
// Generate unique ID for clip paths
|
||||
const clipId = useId();
|
||||
|
||||
// Use custom tagline if provided
|
||||
const displayTagline = tagline || config.tagline;
|
||||
|
||||
// Enforce minimum sizes per guidelines
|
||||
const minSize = variant === 'icon' ? 32 : 120;
|
||||
const u = Math.max(size, minSize);
|
||||
|
||||
const calc = {
|
||||
icon: u,
|
||||
wordmarkFont: u * 0.15,
|
||||
taglineFont: u * 0.092,
|
||||
gapIconToWordmark: u * 0.02,
|
||||
gapWordmarkToTagline: u * 0.05,
|
||||
clearSpace: u * 0.12,
|
||||
horizontalIcon: u * 0.60,
|
||||
horizontalWordmarkFont: u * 0.233,
|
||||
horizontalTaglineFont: u * 0.13,
|
||||
horizontalGap: u * 0.176,
|
||||
horizontalClearSpace: u * 0.05,
|
||||
// V2: Tighter proportions - less gap, bigger text
|
||||
v2Icon: u * 0.50,
|
||||
v2Gap: u * 0.10,
|
||||
v2WordmarkFont: u * 0.28,
|
||||
v2TaglineFont: u * 0.15,
|
||||
v2ClearSpace: u * 0.02,
|
||||
};
|
||||
|
||||
const isDark = colorScheme === 'dark';
|
||||
const isMono = colorScheme === 'mono-dark' || colorScheme === 'mono-light';
|
||||
const monoColor = colorScheme === 'mono-light' ? '#FFFFFF' : '#1E293B';
|
||||
const monoContrast = colorScheme === 'mono-light' ? '#1E293B' : '#FFFFFF';
|
||||
|
||||
const colors = isMono ? {
|
||||
star: monoColor,
|
||||
magnifier: monoColor,
|
||||
lens: 'none',
|
||||
barLight: monoColor,
|
||||
barMid: monoColor,
|
||||
barDark: monoColor,
|
||||
wordmark: monoColor,
|
||||
accent: monoColor,
|
||||
tagline: monoColor,
|
||||
stroke: monoContrast,
|
||||
strokeWidth: 2,
|
||||
} : {
|
||||
star: '#FBBC05',
|
||||
magnifier: '#1E293B',
|
||||
lens: '#FEF3C7',
|
||||
barLight: '#86EFAC',
|
||||
barMid: '#22C55E',
|
||||
barDark: '#15803D',
|
||||
wordmark: isDark ? '#FAFAF9' : '#1E293B',
|
||||
accent: '#F59E0B',
|
||||
tagline: isDark ? '#A8A29E' : '#64748B',
|
||||
stroke: isDark ? '#78716C' : 'none',
|
||||
strokeWidth: isDark ? 1.5 : 0,
|
||||
};
|
||||
|
||||
const LogoIcon = ({ iconSize }: { iconSize?: number }) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 120 120"
|
||||
width={iconSize || calc.icon}
|
||||
height={iconSize || calc.icon}
|
||||
>
|
||||
<defs>
|
||||
<clipPath id={clipId}>
|
||||
<circle cx="60" cy="62" r="21"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
{isMono && (
|
||||
<polygon
|
||||
points="60,15 71.5,42 101,46 79.5,66 85,95 60,82 35,95 40.5,66 19,46 48.5,42"
|
||||
fill="none"
|
||||
stroke={colors.stroke}
|
||||
strokeWidth="8"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
)}
|
||||
<polygon
|
||||
points="60,15 71.5,42 101,46 79.5,66 85,95 60,82 35,95 40.5,66 19,46 48.5,42"
|
||||
fill={colors.star}
|
||||
stroke={colors.star}
|
||||
strokeWidth="6"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<g>
|
||||
{isDark && !isMono && (
|
||||
<line x1="83" y1="81" x2="95" y2="91" stroke="#78716C" strokeWidth="11" strokeLinecap="round"/>
|
||||
)}
|
||||
{isMono && (
|
||||
<line x1="83" y1="81" x2="95" y2="91" stroke={monoContrast} strokeWidth="12" strokeLinecap="round"/>
|
||||
)}
|
||||
{isMono && (
|
||||
<circle cx="60" cy="62" r="28" fill="none" stroke={monoContrast} strokeWidth="2"/>
|
||||
)}
|
||||
<circle cx="60" cy="62" r="27" fill={colors.magnifier}/>
|
||||
<line x1="83" y1="81" x2="95" y2="91" stroke={colors.magnifier} strokeWidth="9" strokeLinecap="round"/>
|
||||
{!isMono && <circle cx="60" cy="62" r="21" fill={colors.lens}/>}
|
||||
{isMono && (
|
||||
<circle cx="60" cy="62" r="21" fill={monoContrast} stroke={colors.stroke} strokeWidth="2"/>
|
||||
)}
|
||||
{isMono && (
|
||||
<rect x="68" y="62" width="11" height="21" rx="1.5" fill={colors.barDark} stroke={monoContrast} strokeWidth="2" clipPath={`url(#${clipId})`}/>
|
||||
)}
|
||||
{isMono && (
|
||||
<rect x="68" y="44" width="11" height="18" rx="1.5" fill={colors.barDark} stroke={monoContrast} strokeWidth="2"/>
|
||||
)}
|
||||
{isMono && <rect x="69" y="60" width="9" height="4" fill={colors.barDark}/>}
|
||||
{!isMono && <rect x="68" y="44" width="11" height="18" rx="1.5" fill={colors.barDark}/>}
|
||||
<g clipPath={`url(#${clipId})`}>
|
||||
<rect x="42" y="58" width="11" height="35" rx="1.5" fill={colors.barLight}/>
|
||||
<rect x="55" y="51" width="11" height="42" rx="1.5" fill={colors.barMid}/>
|
||||
{!isMono && <rect x="68" y="44" width="11" height="49" rx="1.5" fill={colors.barDark}/>}
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const Wordmark = ({ fontSize }: { fontSize?: number }) => (
|
||||
<span
|
||||
className="font-bold leading-tight tracking-tight"
|
||||
style={{ fontSize: fontSize || calc.wordmarkFont, color: colors.wordmark }}
|
||||
>
|
||||
{config.domain}<span style={{ color: colors.accent }}>{config.domainTLD}</span>
|
||||
</span>
|
||||
);
|
||||
|
||||
const Tagline = ({ fontSize }: { fontSize?: number }) => (
|
||||
<span
|
||||
style={{ fontSize: fontSize || calc.taglineFont, color: colors.tagline }}
|
||||
>
|
||||
{displayTagline}
|
||||
</span>
|
||||
);
|
||||
|
||||
if (variant === 'icon') {
|
||||
return (
|
||||
<div className="inline-flex" style={{ padding: calc.clearSpace }}>
|
||||
<LogoIcon />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (variant === 'primary') {
|
||||
return (
|
||||
<div className="inline-flex flex-col items-center" style={{ padding: calc.clearSpace }}>
|
||||
<LogoIcon />
|
||||
<div style={{ height: calc.gapIconToWordmark }} />
|
||||
<Wordmark />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (variant === 'full') {
|
||||
return (
|
||||
<div className="inline-flex flex-col items-center" style={{ padding: calc.clearSpace }}>
|
||||
<LogoIcon />
|
||||
<div style={{ height: calc.gapIconToWordmark }} />
|
||||
<Wordmark />
|
||||
<div style={{ height: calc.gapWordmarkToTagline }} />
|
||||
<Tagline />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (variant === 'horizontal') {
|
||||
return (
|
||||
<div className="inline-flex items-center" style={{ padding: calc.horizontalClearSpace }}>
|
||||
<div style={{ marginTop: calc.horizontalIcon * 0.02 }}>
|
||||
<LogoIcon iconSize={calc.horizontalIcon} />
|
||||
</div>
|
||||
<div style={{ width: calc.horizontalGap }} />
|
||||
<Wordmark fontSize={calc.horizontalWordmarkFont} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (variant === 'horizontal-full') {
|
||||
return (
|
||||
<div className="inline-flex items-center" style={{ padding: calc.horizontalClearSpace }}>
|
||||
<LogoIcon iconSize={calc.horizontalIcon} />
|
||||
<div style={{ width: calc.horizontalGap }} />
|
||||
<div className="flex flex-col">
|
||||
<Wordmark fontSize={calc.horizontalWordmarkFont} />
|
||||
<div style={{ height: calc.gapWordmarkToTagline * 0.5 }} />
|
||||
<Tagline fontSize={calc.horizontalTaglineFont} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (variant === 'horizontal-v2') {
|
||||
return (
|
||||
<div className="inline-flex items-center" style={{ padding: calc.v2ClearSpace }}>
|
||||
<LogoIcon iconSize={calc.v2Icon} />
|
||||
<div style={{ width: calc.v2Gap }} />
|
||||
<Wordmark fontSize={calc.v2WordmarkFont} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (variant === 'horizontal-full-v2') {
|
||||
const textGap = u * 0.02;
|
||||
const totalTextHeight = calc.v2WordmarkFont + textGap + calc.v2TaglineFont;
|
||||
const fullIconSize = totalTextHeight / 0.667;
|
||||
const iconOffset = fullIconSize * 0.12;
|
||||
|
||||
return (
|
||||
<div className="inline-flex items-center" style={{ padding: calc.v2ClearSpace }}>
|
||||
<div style={{ marginTop: iconOffset }}>
|
||||
<LogoIcon iconSize={fullIconSize} />
|
||||
</div>
|
||||
<div style={{ width: calc.v2Gap }} />
|
||||
<div className="flex flex-col">
|
||||
<Wordmark fontSize={calc.v2WordmarkFont} />
|
||||
<div style={{ height: textGap }} />
|
||||
<Tagline fontSize={calc.v2TaglineFont} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
export { Icon, icons } from './Icons';
|
||||
export { WhyMyRatingLogo } from './WhyMyRatingLogo';
|
||||
|
||||
Reference in New Issue
Block a user