Skip to content
BaseLayer Themes

Elements

Buttons, typography, and icons — UI atoms used inside blocks and pages.

Live preview

Button

Link

Text

Display SM

Eyebrow

Lead paragraph

Icon

Powered by Lucide. Pass any kebab-case icon name to <Icon name="…" />.

OptimizedImage

Photos from src/assets/images/ via astro:assets — resized WebP + srcset at build time.

Optimized demo portrait

Folder: src/components/elements/

Low-level components used inside blocks and pages. No config slice — import directly and pass props.

Button

---
import Button from "@/components/elements/Button.astro";
---

<Button variant="brand" size="lg" href="/contact/">Get in touch</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost" type="button">Dismiss</Button>
<Button variant="link" href="/docs/">Plain text link</Button>
Prop Values
variant brand | secondary | tertiary | outline | ghost | link
size sm | md | lg (link ignores size padding)
href Renders <a> when set, <button> otherwise
type button | submit | reset

link is medium weight and underlined — use for editorial CTAs inside Content / FAQ blocks.

Text

Typography wrapper with semantic size tokens:

---
import Text from "@/components/elements/Text.astro";
---

<Text tag="h2" variant="displaySm" class="text-strong">Heading</Text>
<Text tag="p" variant="lg" class="text-soft">Body copy</Text>
variant Tailwind class
display text-display
displaySm text-display-sm
eyebrow text-eyebrow
lg text-lg md:text-xl
base text-base
sm text-sm
xs text-xs

Icon

Inline SVG icons powered by Lucide via @lucide/astro. Pass any Lucide kebab-case name (e.g. zap, layout-template, shield-check).

---
import Icon from "@/components/elements/Icon.astro";
---

<Icon name="arrow-right" size={18} />
<Icon name="sparkles" size={20} class="text-brand" />
Prop Notes
name Lucide kebab-case icon id — browse lucide.dev/icons
size Pixel size (default 18)
stroke Stroke width (default 1.75)
class Extra classes (color via text-*)

Legacy aliases (still work): boltzap, stacklayers, layoutlayout-template.

Helper: src/lib/icons.ts resolves names to Lucide components. Used by Services, Hero08 feature boxes, FAQ, navbar, and banners.

OptimizedImage

Wrapper around Astro’s astro:assets <Image /> for photography. Accepts ImageMetadata from src/assets/images/ (optimized WebP + srcset) or a string path for public SVGs/logos.

---
import OptimizedImage from "@/components/elements/OptimizedImage.astro";
import { photos } from "@/assets/images";
---

<OptimizedImage
  src={photos.karla}
  alt="Portrait"
  widths={[480, 768, 1024]}
  sizes="(max-width: 768px) 100vw, 40vw"
  class="rounded-xl object-cover"
/>
Prop Notes
src ImageMetadata or string
alt Required
widths / sizes Responsive srcset
quality Default 75
loading lazy (default) or eager for LCP

Full workflow: Images.

Adding to a page

Elements are always inline — no blocks.ts entry. Import where needed:

---
import Button from "@/components/elements/Button.astro";
import Text from "@/components/elements/Text.astro";
---

<Text tag="h2" variant="displaySm">Custom heading</Text>
<Button href="/contact/" class="mt-6">Contact</Button>

← Components overview