Blocks / Marketing

Call to action band

A closing call to action: a big headline, one line, two actions and a row of supplier delivery tickets.

Width

Start with tomorrow's delivery.

Import your stock sheet tonight, connect the till, and check the 6am drop against what you ordered.

Free for 30 days, no card. Bring your spreadsheet and we will tidy it.

Install

Writes the block to components/blocks/cta-band.tsx and its .css, and every part it uses to components/equip/, with the parts those are built from.

npx https://equip.studio311.app/equip.tgz add block:cta-band

Built from 4 parts

Notes

  • The ticket row is one role=img with a sentence for a label; the tickets inside are inert, so nothing in it takes focus.
  • On a narrow container the tickets run off the panel's edge under a fade; from 60rem they share the row.
  • The actions are link Buttons with fragment hrefs; point them at your sign-up and booking pages.

Source

components/blocks/cta-band.tsx79 lines
import { Badge } from "@/components/equip/badge";
import { Button } from "@/components/equip/button";
import { Heading } from "@/components/equip/heading";
import { Text } from "@/components/equip/text";
import "./cta-band.css";

const tickets = [
  { supplier: "Natoora", time: "06:40", lines: "12 lines checked", status: "All in", tone: "ok", by: "Sam W." },
  { supplier: "Neal's Yard Dairy", time: "07:15", lines: "6 lines checked", status: "Butter 2kg short", tone: "warn", by: "Sam W." },
  { supplier: "Flock & Herd", time: "08:05", lines: "9 lines checked", status: "All in", tone: "ok", by: "Tom O." },
  { supplier: "Shellseekers", time: "09:30", lines: "4 lines checked", status: "All in", tone: "ok", by: "Tom O." },
  { supplier: "Wildfarmed", time: "10:10", lines: "3 lines checked", status: "All in", tone: "ok", by: "Kasia N." },
] as const;

/*
 * The closing call to action of a landing page: one big line, two ways in, and a morning's
 * deliveries pinned up like tickets on the pass.
 */
export default function CtaBand() {
  return (
    <section className="blk-cta-band" aria-labelledby="cta-band-title">
      <div className="blk-cta-band-inner">
        <div className="blk-cta-band-panel">
          <div className="blk-cta-band-copy">
            <Heading level={2} id="cta-band-title" className="blk-cta-band-title">
              Start with tomorrow&apos;s delivery.
            </Heading>
            <div className="blk-cta-band-side">
              <Text size="l" tone="quiet" className="blk-cta-band-line">
                Import your stock sheet tonight, connect the till, and check the 6am drop against what you ordered.
              </Text>
              <div className="blk-cta-band-actions">
                <Button href="#start" variant="accent" size="l">
                  Start a free kitchen
                </Button>
                <Button href="#walkthrough" variant="outline" size="l">
                  Book a walkthrough
                </Button>
              </div>
              <Text size="s" tone="faint">
                Free for 30 days, no card. Bring your spreadsheet and we will tidy it.
              </Text>
            </div>
          </div>

          <div
            className="blk-cta-band-tickets"
            role="img"
            aria-label="A Tuesday morning's five deliveries checked in, from Natoora at 06:40 to Wildfarmed at 10:10, with Neal's Yard Dairy 2kg short on butter"
          >
            <div className="blk-cta-band-row" inert>
              {tickets.map((ticket) => (
                <div key={ticket.supplier} className="blk-cta-band-ticket">
                  <div className="blk-cta-band-ticket-head">
                    <Text as="span" size="s" weight="strong">
                      {ticket.supplier}
                    </Text>
                    <span className="blk-cta-band-ticket-time">{ticket.time}</span>
                  </div>
                  <div className="blk-cta-band-ticket-body">
                    <Text size="s" tone="quiet">
                      {ticket.lines}
                    </Text>
                    <Badge tone={ticket.tone} dot>
                      {ticket.status}
                    </Badge>
                  </div>
                  <Text size="s" tone="faint" className="blk-cta-band-ticket-sign">
                    Signed in by {ticket.by}
                  </Text>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}
components/blocks/cta-band.css155 lines
@layer blocks {
  .blk-cta-band {
    container: blk-cta-band / inline-size;
    background: var(--eq-bg);
    color: var(--eq-ink);
  }

  .blk-cta-band-inner {
    max-width: 76rem;
    margin-inline: auto;
    padding: calc(var(--eq-space-6) * 1.5) var(--eq-space-4);
  }

  .blk-cta-band-panel {
    overflow: clip;
    border: 1px solid var(--eq-line);
    border-radius: var(--eq-radius-l);
    background: var(--eq-surface);
  }

  .blk-cta-band-copy {
    display: grid;
    gap: var(--eq-space-5);
    padding: calc(var(--eq-space-6) * 1.25) var(--eq-space-4) var(--eq-space-6);
  }

  .blk-cta-band-copy :is(h2, p) {
    margin: 0;
  }

  .blk-cta-band-title {
    max-width: 14ch;
    font-size: clamp(2.25rem, 9cqi, 4.5rem);
    line-height: 0.98;
    letter-spacing: -0.035em;
    text-wrap: balance;
  }

  .blk-cta-band-side {
    display: grid;
    justify-items: start;
    gap: var(--eq-space-4);
    max-width: 30rem;
  }

  .blk-cta-band-line {
    text-wrap: pretty;
  }

  .blk-cta-band-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--eq-space-2);
  }

  /* The pass: a morning of delivery tickets pinned in a row, running off the edge of the panel. */
  .blk-cta-band-tickets {
    border-top: 1px solid var(--eq-line);
    background:
      radial-gradient(circle at 1px 1px, var(--eq-line-strong) 1px, transparent 0) 0 0 / 18px 18px,
      color-mix(in oklab, var(--eq-tint) 60%, var(--eq-surface));
  }

  .blk-cta-band-row {
    display: flex;
    gap: var(--eq-space-3);
    padding: var(--eq-space-5) var(--eq-space-4) calc(var(--eq-space-5) + 4px);
    overflow: clip;
    mask-image: linear-gradient(to right, currentColor 78%, transparent);
  }

  .blk-cta-band-ticket {
    flex: 0 0 11.5rem;
    display: grid;
    gap: var(--eq-space-2);
    padding: var(--eq-space-3);
    border: 1px dashed var(--eq-line-strong);
    border-radius: var(--eq-radius-m);
    background: var(--eq-raised);
    rotate: -1.25deg;
  }

  .blk-cta-band-ticket:nth-child(even) {
    rotate: 1deg;
    translate: 0 4px;
  }

  .blk-cta-band-ticket:nth-child(3n) {
    rotate: -0.5deg;
  }

  .blk-cta-band-ticket p {
    margin: 0;
  }

  .blk-cta-band-ticket-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0 var(--eq-space-2);
    min-width: 0;
  }

  .blk-cta-band-ticket-time {
    flex: none;
    color: var(--eq-ink-3);
    font-family: var(--eq-font-mono);
    font-variation-settings: var(--eq-font-mono-settings);
    font-size: var(--eq-text-xs);
  }

  /* The tear line: where the driver's copy comes off. */
  .blk-cta-band-ticket-body {
    display: grid;
    justify-items: start;
    gap: var(--eq-space-2);
    padding-top: var(--eq-space-2);
    border-top: 1px dashed var(--eq-line-strong);
  }

  .blk-cta-band-ticket-sign {
    font-size: var(--eq-text-xs);
  }

  @container blk-cta-band (width >= 40rem) {
    .blk-cta-band-inner {
      padding-inline: var(--eq-space-5);
    }

    .blk-cta-band-copy,
    .blk-cta-band-row {
      padding-inline: var(--eq-space-6);
    }
  }

  @container blk-cta-band (width >= 60rem) {
    .blk-cta-band-copy {
      grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
      align-items: end;
      gap: calc(var(--eq-space-6) * 1.5);
      padding-block: calc(var(--eq-space-6) * 2) calc(var(--eq-space-6) * 1.25);
    }

    /* Wide enough for the whole morning: the tickets share the row and the fade goes. */
    .blk-cta-band-row {
      mask-image: none;
    }

    .blk-cta-band-ticket {
      flex: 1 1 0;
      min-width: 0;
    }
  }
}

EqUIp is in beta: free for non-commercial use, no warranty, and things can change. Terms

Nothing picked yet. Press A on a part, or use the plus on the board, and the install command builds here.

Loading the index.

Loading the index