Files
Wabenhain/src/components/honeycomb.tsx
T
Nick SzaunigandClaude Opus 5.5 3cb639c154 feat(ui): Fundament und Einkaufserlebnis visuell aufgewertet
- Fundament: feine Papierkoernung, Scrollbar/Cursor/Fokusring/Markierung in
  Markenfarben, gleich breite Ziffern fuer Preise, einlaufende Unterstriche
- Knoepfe fuellen sich beim Hover von unten wie ein Glas (Honig/Waldgruen),
  geben beim Klick nach
- Wabenmotiv aus dem Logo als Komponente (Raster, Markierung, Haekchen)
- In den Warenkorb: ein Honigtropfen fliegt im Bogen zum Korb, der Korb
  wippt, der Zaehler springt, erst dann oeffnet die Schublade; Knopf zeigt
  gezeichnetes Haekchen. Reduzierte Bewegung: Schublade oeffnet sofort.
- Produktkarten: Honigschimmer, Anheben, Serifen-Preis, gestaffeltes
  Erscheinen, Pfeil-Links
- Produktseite: mitlaufendes Bild auf Wabenraster, groesserer Titel und
  Preis, sich fuellende Geschmacksskala, Waben-Haekchen statt "✓"
- Shop-Filter als einheitliche Werkzeugleiste mit Schalter
- Warenkorb-Schublade: Dialog-Semantik, animierte Positionen, tickende
  Summe, gestalteter leerer Zustand

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-25 04:56:03 +02:00

90 lines
3.2 KiB
TypeScript

import { useId } from "react";
/**
* Wabenraster als Markensignatur: dieselbe spitz stehende Sechseckform wie
* im Logomark, als feines Linienmuster. Liegt absolut im naechsten
* relativen Elternteil, ist rein dekorativ (aria-hidden) und laeuft ueber
* eine Maske zu den Raendern hin aus, damit es nie als harte Kachelkante
* endet.
*
* Farbe ueber currentColor (text-*-Klasse am Aufrufer), Staerke ueber
* opacity — so passt dasselbe Muster auf Creme wie auf Waldgruen.
*/
export function HoneycombPattern({
className = "",
size = 22,
fade = "radial",
}: {
className?: string;
/** Radius eines Sechsecks in px. */
size?: number;
/** Wohin das Muster auslaeuft. */
fade?: "radial" | "right" | "bottom" | "none";
}) {
const id = useId().replace(/:/g, "");
const r = size;
const w = Math.sqrt(3) * r;
const tileH = 3 * r;
// Zwei Sechsecke je Kachel (versetzte Reihen), spitz nach oben wie im Logo.
const hex = (cx: number, cy: number) =>
Array.from({ length: 6 }, (_, i) => {
const angle = (Math.PI / 3) * i - Math.PI / 2;
return `${(cx + r * Math.cos(angle)).toFixed(2)},${(cy + r * Math.sin(angle)).toFixed(2)}`;
}).join(" ");
const masks: Record<typeof fade, string | undefined> = {
radial: "radial-gradient(ellipse at center, black 20%, transparent 75%)",
right: "linear-gradient(to left, black, transparent 80%)",
bottom: "linear-gradient(to top, black, transparent 85%)",
none: undefined,
};
return (
<svg
aria-hidden="true"
className={`pointer-events-none absolute inset-0 h-full w-full ${className}`}
style={masks[fade] ? { maskImage: masks[fade], WebkitMaskImage: masks[fade] } : undefined}
>
<defs>
<pattern id={`wabe-${id}`} width={w} height={tileH} patternUnits="userSpaceOnUse">
<polygon points={hex(w / 2, r)} fill="none" stroke="currentColor" strokeWidth="1" />
<polygon points={hex(0, r * 2.5)} fill="none" stroke="currentColor" strokeWidth="1" />
<polygon points={hex(w, r * 2.5)} fill="none" stroke="currentColor" strokeWidth="1" />
</pattern>
</defs>
<rect width="100%" height="100%" fill={`url(#wabe-${id})`} />
</svg>
);
}
/** Kleines Sechseck als Aufzaehlungs- und Statuszeichen (statt Unicode-Glyphen). */
export function HexMark({ className = "h-3 w-3", filled = true }: { className?: string; filled?: boolean }) {
return (
<svg viewBox="0 0 24 24" className={className} aria-hidden="true">
<polygon
points="12,2 20.66,7 20.66,17 12,22 3.34,17 3.34,7"
fill={filled ? "currentColor" : "none"}
stroke="currentColor"
strokeWidth="2"
strokeLinejoin="round"
/>
</svg>
);
}
/** Haekchen im Sechseck — fuer Vorteilslisten (ersetzt das Textzeichen "✓"). */
export function HexCheck({ className = "h-4 w-4" }: { className?: string }) {
return (
<svg viewBox="0 0 24 24" className={className} fill="none" aria-hidden="true">
<polygon
points="12,2 20.66,7 20.66,17 12,22 3.34,17 3.34,7"
stroke="currentColor"
strokeWidth="1.5"
strokeLinejoin="round"
/>
<path d="M8.2 12.3l2.5 2.5 5-5.3" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
</svg>
);
}