Files
kaiser-natron/src/design-system/components/WaveDivider.vue
Dorian ab0f7da50d feat: crimson CTA accents, white surfaces, Zeitung font, diagonal dividers
- Add --color-accent-fill (#cc0230) / -hover / -ink tokens; repoint all
  solid yellow "button" surfaces (Button accent, IconButton accent,
  language-selector active pill, Navbar cart CTA, Kaiserhacks chip,
  accent Badge) to crimson fill + white ink. Yellow --color-accent kept
  for functional text accents.
- Secondary button: transparent fill, white border, white text/icons,
  translucent-white hover (no longer mimics the primary default).
- Surfaces to pure white: --color-cream and --color-surface -> #ffffff
  (cream-toned logo follows via text-cream); theme-color -> #ffffff.
- Self-host Zeitung (Regular/Bold woff2, mirrored from production);
  point --font-sans/--font-serif at Zeitung; drop Google Fonts CDN.
- Remove yellow highlighting on hero/title emphasis and hero eyebrows
  (text-accent-soft -> text-cream, eyebrows -> text-cream/75).
- WaveDivider + homepage section dividers: straight diagonal (low-left,
  high-right) at double height for ~2x the right-to-left difference.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 09:47:06 +01:00

75 lines
2.4 KiB
Vue

<script setup>
/**
* WaveDivider — the signature diagonal transition between two
* full-bleed coloured sections. The boundary is a straight diagonal
* that sits low on the left and high on the right. Extracted from
* HomePage.vue so the shop page (and any future sections page) can
* reuse the same visual grammar instead of duplicating the SVG.
*
* The SVG is fully opaque by design: a `to` rect fills the whole
* viewBox so the bottom row is solid destination colour (matches
* the section below → no seam), and a `from` path paints the wavy
* top portion (matches the section above → no seam). Leaving the
* top half transparent caused browsers to anti-alias the path's
* top/bottom edges against the parent and produce hairline
* artefacts.
*
* Tone names (`brand`, `cream`, `surface`, `paper`) mirror the
* surface tokens used across Hero / About / Bundles etc. so calls
* read as "from X to Y" without the caller knowing the underlying
* CSS-variable names.
*/
import { computed } from 'vue'
const props = defineProps({
/** Colour of the section above the wave — painted on the wavy top. */
from: {
type: String,
default: 'brand',
validator: (v) => ['brand', 'cream', 'surface', 'paper'].includes(v),
},
/** Colour of the section below the wave — fills the solid bottom. */
to: {
type: String,
default: 'cream',
validator: (v) => ['brand', 'cream', 'surface', 'paper'].includes(v),
},
})
const toneVar = {
brand: 'var(--color-brand)',
cream: 'var(--color-cream)',
surface: 'var(--color-surface)',
paper: 'var(--color-paper)',
}
const toneBg = {
brand: 'bg-brand',
cream: 'bg-cream',
surface: 'bg-surface',
paper: 'bg-paper',
}
// The wrapping bg-* class paints any 1-device-pixel gap that could
// otherwise show up between the SVG's bottom and the next section
// during subpixel rounding — matches the `from` tone so the wave
// rests flush on the section above.
const wrapperClass = computed(() => toneBg[props.from])
const fromFill = computed(() => toneVar[props.from])
const toFill = computed(() => toneVar[props.to])
</script>
<template>
<svg
aria-hidden="true"
:class="['block w-full h-24 md:h-32 shrink-0 -mb-px', wrapperClass]"
viewBox="0 0 1440 128"
preserveAspectRatio="none"
>
<rect width="1440" height="128" :fill="toFill" />
<path
d="M0,0 L0,116 L1440,12 L1440,0 Z"
:fill="fromFill"
/>
</svg>
</template>