Marketing

Hero

A landing page's opening: eyebrow, headline, lead, buttons, and a picture or code on the side.

#marketing#section#page#layout#no-js

Demo

Preview

Now in beta

Ship the whole app in one file

Routes, views and live components in a language made for the web. No build step, no framework to wire up.

See the code

A route, a view and a component: the whole page.

quillo
route GET / =    <html><body>        <Counter start={5}/>    </body></html>

Centred without a side; words left and the picture or code right with one. On a phone the side goes under.

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/hero.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/hero.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/hero.qwe
view HeroDemo() =    <div.demo-stack>        <Hero id="hero-demo-center" eyebrow="Now in beta" title="Ship the whole app in one file"              text="Routes, views and live components in a language made for the web. No build step, no framework to wire up.">            <Button size="lg" href="#hero">Get started</Button>            <Button size="lg" variant="outline" href="#hero">Read the docs</Button>        </Hero>        <Hero title="See the code" level={2} text="A route, a view and a component: the whole page."              side={<CodeBlock code={"route GET / =\n    <html><body>\n        <Counter start={5}/>\n    </body></html>"} language="quillo"/>}>            <Button href="#hero">Try it</Button>        </Hero>        <p.demo-note>Centred without a side; words left and the picture or code right with one. On a phone the side goes under.</p>    </div>

Source

ui/hero.qwe
// Hero: the first thing on a landing page: a small line above a big title, a// sentence or two, the buttons, and, beside them, a picture or a block of code.////   <Hero eyebrow="Now in beta" title="Ship the whole app in one file"//         text="Routes, views and live components in a language made for the web.">//       <Button size="lg" href="/start">Get started</Button>//       <Button size="lg" variant="outline" href="/docs">Read the docs</Button>//   </Hero>//   <Hero title="See it run" image="/img/screen.png" image_alt="The dashboard"> ... </Hero>//   <Hero title="Hello, world" side={<CodeBlock code={hello} language="quillo"/>}> ... </Hero>//// eyebrow: the small line above the title. title: the headline (an <h1>; level// changes the heading's level, 2 for a hero lower on the page). text: the lead// under it. children: what goes under the text, usually buttons, laid out in a row.// image and image_alt: a picture on the side; side: any HTML there instead (code,// a video, a form). With neither, the words are centred; with one, they sit on// the left and it on the right (the picture under them on a phone). align:// "start" or "center" to say so yourself. size: "md" (default) or "lg", a bigger// title and more room. id: the section's id.import ui/theme.qwe use ui_clslet hero_css = css`.ui-hero { display: grid; gap: 32px; align-items: center; padding: 56px 24px; font: 16px/1.6 var(--ui-font); color: var(--ui-fg); }.ui-hero-split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }.ui-hero-lg { padding: 88px 24px; gap: 48px; }.ui-hero-words { display: grid; gap: 14px; justify-items: start; text-align: left; }.ui-hero-center .ui-hero-words { justify-items: center; text-align: center; max-width: 720px; margin: 0 auto; }.ui-hero-eyebrow { margin: 0; color: var(--ui-accent); font-size: 13px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }.ui-hero-title { margin: 0; font-size: clamp(32px, 5vw, 48px); font-weight: 750; line-height: 1.1; letter-spacing: -.02em; }.ui-hero-lg .ui-hero-title { font-size: clamp(38px, 6.5vw, 64px); }.ui-hero-text { margin: 0; max-width: 58ch; color: var(--ui-muted); font-size: 18px; }.ui-hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 10px; }.ui-hero-center .ui-hero-actions { justify-content: center; }.ui-hero-side { min-width: 0; }.ui-hero-side > img { display: block; width: 100%; height: auto; border-radius: var(--ui-radius); box-shadow: var(--ui-shadow-lg); }.ui-hero-side > :first-child { margin-top: 0; }@media (max-width: 760px) {  .ui-hero { padding: 40px 16px; }  .ui-hero-split { grid-template-columns: minmax(0, 1fr); }}`view Hero(title: str, eyebrow: str? = null, text: str? = null, image: str? = null, image_alt: str = "",          side = null, align: str? = null, size: str = "md", level: int = 1, id: str? = null, class: str? = null, children) {    style global hero_css    let aside = side ?? (image != null ? <img src={image} alt={image_alt} loading="lazy"/> : null)    let how = align ?? (aside != null ? "start" : "center")    let heading = match level {        2 => <h2.ui-hero-title>{title}</h2>        3 => <h3.ui-hero-title>{title}</h3>        _ => <h1.ui-hero-title>{title}</h1>    }    <section id={id} class={ui_cls(["ui-hero", `ui-hero-${how}`, aside != null && "ui-hero-split", size == "lg" && "ui-hero-lg", class])}>        <div.ui-hero-words>            {eyebrow != null && <p.ui-hero-eyebrow>{eyebrow}</p>}            {heading}            {text != null && <p.ui-hero-text>{text}</p>}            {children != null && <div.ui-hero-actions>{children}</div>}        </div>        {aside != null && <div.ui-hero-side>{aside}</div>}    </section>}
Thread
67Useful? Like it, or add to its thread below.

Thread 0 posts

On Hero: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.