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';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Icon } from '@/components';
|
import { Icon, WhyMyRatingLogo } from '@/components';
|
||||||
|
|
||||||
type TabId = 'home' | 'settings';
|
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">
|
<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="max-w-4xl mx-auto px-4 sm:px-6">
|
||||||
<div className="py-4 flex items-center justify-between">
|
<div className="py-4 flex items-center justify-between">
|
||||||
<div className="flex items-center gap-3">
|
<WhyMyRatingLogo variant="horizontal-full" size={140} colorScheme="dark" />
|
||||||
{/* 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>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tabs */}
|
{/* 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 { Icon, icons } from './Icons';
|
||||||
|
export { WhyMyRatingLogo } from './WhyMyRatingLogo';
|
||||||
|
|||||||
Reference in New Issue
Block a user