Skip to content
Sign inJoin waitlist

Kalme Design System (Astro)

Reusable tokens and components for every page of the Kalme template. The published Framer template is the reference for look and behavior; component names follow the Framer components, and every component has the same name, props and classes as in the Next.js version (../nextjs), so both render the same DOM. Import components by path (../../design-system/components/cards/ProjectCard.astro); pages map content to props in src/lib/to-ui.ts. Every component is shown on /style-guide.

File Holds
theme.css Colours (ink, grey, line, background, red, danger), breakpoints md 810 / lg 1200, the ticker animation
tokens/text.ts Text styles: display, h1–h6, number, bigParagraph, paragraph, smallParagraph, menu, button, subtitle
tokens/motion.ts springSoft (bounce 0, 0.4 s), springButton (bounce 0.2, 0.4 s), reveal (height), transitions (names for data-transition)

Framer’s translucent colours are opacity modifiers: Black 20 → ink/20, Black 05 → ink/5. Font: Inter (Astro Fonts API, --font-inter), letter spacing −0.03em on every style (−0.02em on button labels).

Group Component Framer
actions Button (primary, secondary) Button/Primary
actions ArrowLink (with or without icon), ArrowFlip Button/Secondary
actions TextLink Button/Text Link
brand Logo (black, white) Misc/Logo
cards FactCard Fact Number
cards ProjectCard Card/Project/Primary
cards PostCard Card/Post
cards TestimonialCard (dark, light × simple, full) Card/Testimonial
cards ValueCard, TeamCard Card/Value, Card/Team
cards ServiceRow, ServiceCard Card/Service/Secondary, Card/Service/Simple
data CheckList, HighlightList, PricingCard (weekly / monthly switch) lists in Services, CMS rich text, Card/Pricing + Misc/Switch
forms Form, FormField / FieldControl, RadioGroup, SubmitButton Form
icons Icon (Phosphor paths in paths.ts) Phosphor
layout Section, SectionLabel, SectionTitle (split, center), PageTitle, Divider Title Section, page Title, Misc/Subtitle
media LoopVideo, ScrollVideo, Showreel, FillImage Video, Page Video, Showreel
navigation Navigation, Hamburger Button/Menu, Button/Hamburger
patterns ServiceAccordion Services, Card/Service/List
patterns Ticker, RichText Ticker, CMS rich text
text InlineText (**bold**, [links](/path), line breaks from content) —
utils CurrentYear —
  • Hover = data attributes. Mark the hoverable element data-hover; every element that changes on hover gets data-motion (motionStates(rest, hover) from utils/motion.ts) and, unless it uses the default spring (springButton), data-transition="soft". Write the rest state inline (style="transform: scale(1.05)") so the page looks right before the script runs. scripts/hover.ts animates them; touch devices and reduced motion are respected.
  • State = a script per component. Interactive components (ServiceAccordion, PricingCard, Showreel, LoopVideo, ScrollVideo, forms, the header menu) hold a <script> that calls an init…() function from scripts/. Scripts find their elements by data-* attributes and skip ones already set up.
  • Slots render once. A component that shows its slot twice (the button label flip, the ticker’s second copy) renders it to a string with Astro.slots.render("default") first. Ticker takes its items as <li> elements.
  • Hidden panels use the hidden attribute on elements without a display class, and inline display: none on the rest (a Tailwind flex would override hidden).
  • Text that Framer puts in its own element (a stat, a button label) gets its own <span> here too, so the layout check (tools/qa/layout-diff) measures the same boxes; borders Framer draws inside an element use an after: border, never border.
  • Images: content refers to /images/<file>; FillImage finds the file in src/assets/images and serves resized WebP.