mirror of
https://github.com/hanzoai/design.git
synced 2026-10-30 14:58:37 +00:00
An agent had no way to LEARN this design system. prompts/ was material for a human to paste, so every generated surface re-derived the rules from scratch — and got them wrong the same ways each time: 117 all-caps labels, 586 inline-styled buttons, 25 z-index literals, a menu painting with tokens nothing declares. So: skills/design-system/SKILL.md, one file, one author. It states the derivation chain (@hanzo/brand + @hanzo/logo -> @hanzo/design -> component) and the rule that follows from it — a component reads the token layer and never reaches past it; a missing token is a NEW TOKEN, not a local constant. Guidance nothing enforces is advice. scripts/lint.mjs is the gate the skill must run before returning, and it reads CONSUMER code, not just this repo: unresolved var(), raw colour, magic z-index, px font-size, non-eyebrow caps, literal-valued inline style, a second icon set, and the wrong package name. None of those fail loudly on their own. That is exactly why they ship. Run against this repo it found nine violations in the design system's OWN components — Dialog and Sheet hardcoded zIndex:80 and rgb(0 0 0 / .8) while publishing --z-modal to everyone else. Fixed at source, and the two scrims that disagreed are now one --surface-scrim token. npm test runs both gates. Also: every doc told agents to import @hanzoai/design. That package does not exist; the import resolves to nothing and an unresolved token layer paints nothing. It is @hanzo/design, in all ten places. Co-authored-by: Hanzo Dev <[email protected]>
29 lines
1.6 KiB
React
29 lines
1.6 KiB
React
import React from 'react'
|
|
|
|
/** The Hanzo mark, exactly as shipped in the press kit (assets/logo.svg).
|
|
* Path data is the press-kit source; the light seams stay #DDDDDD. */
|
|
export function HanzoLogo({ size = 22, variant = 'white', title = 'Hanzo', style, ...rest }) {
|
|
const fill = variant === 'white' ? '#ffffff' : variant === 'black' ? 'var(--hanzo-black)' : 'currentColor'
|
|
return (
|
|
<svg viewBox="0 0 67 67" width={size} height={size} xmlns="http://www.w3.org/2000/svg" role="img" aria-label={title} style={{ display: 'block', flexShrink: 0, ...style }} {...rest}>
|
|
<path d="M22.21 67V44.6369H0V67H22.21Z" fill={fill}></path>
|
|
<path d="M0 44.6369L22.21 46.8285V44.6369H0Z" fill="#DDDDDD"></path>
|
|
<path d="M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z" fill={fill}></path>
|
|
<path d="M22.21 0H0V22.3184H22.21V0Z" fill={fill}></path>
|
|
<path d="M66.7198 0H44.5098V22.3184H66.7198V0Z" fill={fill}></path>
|
|
<path d="M66.6753 22.3185L44.5098 20.0822V22.3185H66.6753Z" fill="#DDDDDD"></path>
|
|
<path d="M66.7198 67V44.6369H44.5098V67H66.7198Z" fill={fill}></path>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
/** Mark + wordmark lockup, as used in the nav and footer. */
|
|
export function HanzoWordmark({ size = 22, label = 'Hanzo AI', variant = 'white', style }) {
|
|
return (
|
|
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 8, ...style }}>
|
|
<HanzoLogo size={size} variant={variant} />
|
|
<span style={{ fontSize: 'var(--text-sm)', fontWeight: 600, letterSpacing: 'var(--tracking-tight)', color: 'var(--text-primary)' }}>{label}</span>
|
|
</span>
|
|
)
|
|
}
|