Section Header
Free · MITEyebrow, title, subtitle, and optional trailing action block with a required explicit heading level prop.
- Category
- Bento & Layout
- Framework
- astro
- Version
- 1.0.0
- Peer deps
- none
Install
velocityx add section-header
Free and MIT licensed — no account needed. The file lands under src/components/velocity/section-header/ by default (override with --dest), and it's yours to edit from the moment it's written.
Demo
View the live demo on the showcase site ↗
Source
Pulled live from the registry — this is the exact file velocityx add section-header writes into your project right now.
components/velocity/section-header/SectionHeader.astro
---
// VELOCITY COMPONENT · theming
//
// Colours here are Tailwind `primary-*` / `accent-*`, which resolve through
// the Velocity preset. Out of the box they are a neutral indigo — NOT the
// Aidxn brand — so this drops into your project without dragging our look in.
//
// ⚡ NOT USING VELOCITY? Run this once, in your project root:
//
// velocityx theme
//
// It writes velocity-preset.cjs + velocity-theme.css. Add the preset to your
// tailwind.config, import the css, then set your whole brand in ONE place:
//
// :root {
// --vx-brand: custom;
// --vx-primary-600: 220 38 38; <- your action colour
// --vx-primary-700: 185 28 28;
// }
//
// ⚠️ Raw RGB channels, space separated — NOT hex. `#DC2626` here silently
// breaks every /opacity variant in the library (bg-primary-600/20 etc).
//
// Prefer not to install anything? Find-and-replace `primary-` with your own
// scale name. Nothing else in this file depends on Velocity.
/**
* SectionHeader — Eyebrow + title + sub + optional trailing action, the
* most common section-opening block in any marketing page. Heading level
* is a REQUIRED prop (no hardcoded h1/h2) so this is safe to reuse at any
* depth in the document outline.
*
* `align` controls text alignment for the eyebrow/title/sub stack;
* the optional action always sits to the right on desktop (stacks below,
* centred/left per `align`, on mobile).
*/
export interface Props {
eyebrow?: string;
title: string;
sub?: string;
headingLevel: 1 | 2 | 3 | 4 | 5 | 6;
align?: 'left' | 'center';
className?: string;
}
const {
eyebrow,
title,
sub,
headingLevel,
align = 'left',
className = '',
} = Astro.props;
const Heading = `h${headingLevel}`;
const hasAction = Astro.slots.has('action');
const ALIGN_TEXT = align === 'center' ? 'text-center items-center' : 'text-left items-start';
---
<div
class:list={[
'flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between',
className,
]}
>
<div class:list={['flex max-w-2xl flex-col gap-2', ALIGN_TEXT]}>
{eyebrow && <p class="h-eyebrow text-primary-600 dark:text-primary-300">{eyebrow}</p>}
<Heading class="h-section font-semibold text-secondary-900 dark:text-white text-balance">
{title}
</Heading>
{sub && <p class="body-lg text-secondary-600 dark:text-secondary-300 text-balance">{sub}</p>}
</div>
{hasAction && (
<div class="shrink-0">
<slot name="action" />
</div>
)}
</div>
Theming
Uses the shared primary-* / accent-* scale — see Theming if colours look unstyled after install.