summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Swithinbank2023-06-02 17:37:31 +0200
committerGitHub2023-06-02 17:37:31 +0200
commitccb919d6580955e3428430a704f4a33fbc55a78d (patch)
treebd48d7612829d53454772c5fd78351dfeaf548d5
parent6a2c0df4d5586b70b46c854061df67b028e73630 (diff)
downloadIT.starlight-ccb919d6580955e3428430a704f4a33fbc55a78d.tar.gz
IT.starlight-ccb919d6580955e3428430a704f4a33fbc55a78d.tar.bz2
IT.starlight-ccb919d6580955e3428430a704f4a33fbc55a78d.zip
Add hero component support (#103)
-rw-r--r--.changeset/eighty-rats-pay.md5
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--docs/astro.config.mjs1
-rw-r--r--docs/src/assets/hero-star.webpbin0 -> 114506 bytes
-rw-r--r--docs/src/assets/landing.css25
-rw-r--r--docs/src/content/docs/de/index.mdx15
-rw-r--r--docs/src/content/docs/index.mdx15
-rw-r--r--docs/src/content/docs/reference/frontmatter.md70
-rw-r--r--packages/starlight/components/CallToAction.astro51
-rw-r--r--packages/starlight/components/Hero.astro136
-rw-r--r--packages/starlight/components/Icon.astro7
-rw-r--r--packages/starlight/components/Icons.ts2
-rw-r--r--packages/starlight/components/SkipLink.astro2
-rw-r--r--packages/starlight/index.astro38
-rw-r--r--packages/starlight/schema.ts141
-rw-r--r--packages/starlight/style/props.css1
16 files changed, 451 insertions, 60 deletions
diff --git a/.changeset/eighty-rats-pay.md b/.changeset/eighty-rats-pay.md
new file mode 100644
index 00000000..2d629065
--- /dev/null
+++ b/.changeset/eighty-rats-pay.md
@@ -0,0 +1,5 @@
+---
+"@astrojs/starlight": patch
+---
+
+Support adding a hero section to pages
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ee36920f..2435a8e9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -35,6 +35,8 @@ jobs:
- name: Build docs site
working-directory: ./docs
run: pnpm build
+ env:
+ NO_GRADIENTS: true
- name: Run accessibility audit
working-directory: ./docs
diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs
index 83b334fd..2c174122 100644
--- a/docs/astro.config.mjs
+++ b/docs/astro.config.mjs
@@ -29,6 +29,7 @@ export default defineConfig({
},
},
],
+ customCss: process.env.NO_GRADIENTS ? [] : ['/src/assets/landing.css'],
locales: {
root: { label: 'English', lang: 'en' },
de: { label: 'Deutsch', lang: 'de' },
diff --git a/docs/src/assets/hero-star.webp b/docs/src/assets/hero-star.webp
new file mode 100644
index 00000000..0d9ef67f
--- /dev/null
+++ b/docs/src/assets/hero-star.webp
Binary files differ
diff --git a/docs/src/assets/landing.css b/docs/src/assets/landing.css
new file mode 100644
index 00000000..244cbc53
--- /dev/null
+++ b/docs/src/assets/landing.css
@@ -0,0 +1,25 @@
+:root {
+ --purple-hsl: 255, 60%, 60%;
+ --overlay-blurple: hsla(var(--purple-hsl), 0.2);
+}
+
+:root[data-theme='light'] {
+ --purple-hsl: 255, 85%, 65%;
+}
+
+[data-has-hero] .page {
+ background: linear-gradient(215deg, var(--overlay-blurple), transparent 40%),
+ radial-gradient(var(--overlay-blurple), transparent 40%) no-repeat -60vw -40vh /
+ 105vw 200vh;
+}
+
+[data-has-hero] header {
+ border-bottom: 1px solid transparent;
+ background-color: transparent;
+ -webkit-backdrop-filter: blur(16px);
+ backdrop-filter: blur(16px);
+}
+
+[data-has-hero] .hero > img {
+ filter: drop-shadow(0 0 3rem hsla(var(--purple-hsl), 0.25));
+}
diff --git a/docs/src/content/docs/de/index.mdx b/docs/src/content/docs/de/index.mdx
index f710c658..9c1fea1e 100644
--- a/docs/src/content/docs/de/index.mdx
+++ b/docs/src/content/docs/de/index.mdx
@@ -1,7 +1,20 @@
---
-title: Wilkommen, Welt
+title: Starlight 🌟 Einfache Dokumentations-Websites mit Astro
description: Erstelle schöne, leistungsstarke Dokumentations-Websites mit Starlight und Astro.
template: splash
+hero:
+ title: Bringe deine Dokumentation mit Starlight zum Leuchten
+ tagline: Alles, was du brauchst, um eine erstklassige Dokumentations-Website zu erstellen. Schnell, barrierefrei und einfach zu bedienen.
+ image:
+ file: ../../../assets/hero-star.webp
+ actions:
+ - text: Los geht's
+ icon: right-arrow
+ variant: primary
+ link: /de/getting-started/
+ - text: Auf GitHub
+ icon: external
+ link: https://github.com/withastro/starlight
---
:::caution[Laufende Arbeiten]
diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx
index 56d15de8..6fd00133 100644
--- a/docs/src/content/docs/index.mdx
+++ b/docs/src/content/docs/index.mdx
@@ -1,7 +1,20 @@
---
-title: Welcome, world
+title: Starlight 🌟 Build documentation sites with Astro
description: Starlight helps you build beautiful, high-performance documentation websites with Astro.
template: splash
+hero:
+ title: Make your docs shine with Starlight
+ tagline: Everything you need to build a stellar documentation website. Fast, accessible, and easy-to-use.
+ image:
+ file: ../../assets/hero-star.webp
+ actions:
+ - text: Get started
+ icon: right-arrow
+ variant: primary
+ link: /getting-started/
+ - text: View on GitHub
+ icon: external
+ link: https://github.com/withastro/starlight
---
:::caution[Work in progress]
diff --git a/docs/src/content/docs/reference/frontmatter.md b/docs/src/content/docs/reference/frontmatter.md
index 4d947100..7d1f04cc 100644
--- a/docs/src/content/docs/reference/frontmatter.md
+++ b/docs/src/content/docs/reference/frontmatter.md
@@ -34,15 +34,6 @@ The page description is used for page metadata and will be picked up by search e
Overrides the [global `editLink` config](/reference/configuration/#editlink). Set to `false` to disable the “Edit page” link for a specific page or provide an alternative URL where the content of this page is editable.
-### `template`
-
-**type:** `'doc' | 'splash'`
-**default:** `'doc'`
-
-Set the layout template for this page.
-Pages use the `'doc'` layout by default.
-Set to `'splash'` to use a wider layout without any sidebars designed for landing pages.
-
### `head`
**type:** [`HeadConfig[]`](/reference/configuration/#headconfig)
@@ -65,3 +56,64 @@ head:
Overrides the [global `tableOfContents` config](/reference/configuration/#tableofcontents).
Customize the heading levels to be included or set to `false` to hide the table of contents on this page.
+
+### `template`
+
+**type:** `'doc' | 'splash'`
+**default:** `'doc'`
+
+Set the layout template for this page.
+Pages use the `'doc'` layout by default.
+Set to `'splash'` to use a wider layout without any sidebars designed for landing pages.
+
+### `hero`
+
+**type:** [`HeroConfig`](#heroconfig)
+
+Add a hero component to the top of this page. Works well with `template: splash`.
+
+For example, this config shows some common options, including loading an image from your repository.
+
+```md
+---
+title: My Home Page
+template: splash
+hero:
+ title: 'My Project: Stellar Stuff Sooner'
+ tagline: Take your stuff to the moon and back in the blink of an eye.
+ image:
+ alt: A glittering, brightly colored logo
+ file: ../../assets/logo.png
+ actions:
+ - text: Tell me more
+ link: /getting-started/
+ icon: right-arrow
+ variant: primary
+ - text: View on GitHub
+ link: https://github.com/astronaut/my-project
+ icon: external
+---
+```
+
+#### `HeroConfig`
+
+```ts
+interface HeroConfig {
+ title?: string;
+ tagline?: string;
+ image?: {
+ alt?: string;
+ // Relative path to an image in your repository.
+ file?: string;
+ // Raw HTML to use in the image slot.
+ // Could be a custom `<img>` tag or inline `<svg>`.
+ html?: string;
+ };
+ actions?: Array<{
+ text: string;
+ link: string;
+ variant: 'primary' | 'secondary' | 'minimal';
+ icon: string;
+ }>;
+}
+```
diff --git a/packages/starlight/components/CallToAction.astro b/packages/starlight/components/CallToAction.astro
new file mode 100644
index 00000000..977516ca
--- /dev/null
+++ b/packages/starlight/components/CallToAction.astro
@@ -0,0 +1,51 @@
+---
+import Icon from './Icon.astro';
+import type { Icons } from './Icons';
+
+interface Props {
+ variant: 'primary' | 'secondary' | 'minimal';
+ link: string;
+ icon?:
+ | undefined
+ | { type: 'icon'; name: keyof typeof Icons }
+ | { type: 'raw'; html: string };
+}
+
+const { link, variant, icon } = Astro.props;
+---
+
+<a class:list={['flex action', variant]} href={link}>
+ <slot />
+ {icon?.type === 'icon' && <Icon name={icon.name} size="1.5rem" />}
+ {icon?.type === 'raw' && <Fragment set:html={icon.html} />}
+</a>
+
+<style>
+ .action {
+ gap: 0.5em;
+ align-items: center;
+ border-radius: 999rem;
+ padding: 0.75rem 1.125rem;
+ color: var(--sl-color-white);
+ line-height: 1.1875;
+ text-decoration: none;
+ font-size: var(--sl-text-sm);
+ }
+ .action.primary {
+ background: var(--sl-color-text-accent);
+ color: var(--sl-color-black);
+ }
+ .action.secondary {
+ border: 1px solid;
+ }
+ .action.minimal {
+ padding-inline: 0;
+ }
+
+ @media (min-width: 50rem) {
+ .action {
+ font-size: var(--sl-text-base);
+ padding: 1rem 1.25rem;
+ }
+ }
+</style>
diff --git a/packages/starlight/components/Hero.astro b/packages/starlight/components/Hero.astro
new file mode 100644
index 00000000..36335b42
--- /dev/null
+++ b/packages/starlight/components/Hero.astro
@@ -0,0 +1,136 @@
+---
+import type { CollectionEntry } from 'astro:content';
+import { Image } from 'astro:assets';
+import CallToAction from './CallToAction.astro';
+
+interface Props {
+ fallbackTitle: string;
+ hero: NonNullable<CollectionEntry<'docs'>['data']['hero']>;
+}
+
+const {
+ title = Astro.props.fallbackTitle,
+ tagline,
+ image,
+ actions,
+} = Astro.props.hero;
+---
+
+<div class="hero">
+ {
+ image?.file ? (
+ <Image
+ src={image.file}
+ loading="eager"
+ width={400}
+ height={400}
+ alt={image.alt}
+ />
+ ) : (
+ image?.html && <div class="hero-html" set:html={image.html} />
+ )
+ }
+ <div class="flex stack">
+ <div class="flex copy">
+ <h1 id="starlight__overview" set:html={title} />
+ {tagline && <div class="tagline" set:html={tagline} />}
+ </div>
+ {
+ actions.length > 0 && (
+ <div class="flex actions">
+ {actions.map(({ text, ...attrs }) => (
+ <CallToAction {...attrs} set:html={text} />
+ ))}
+ </div>
+ )
+ }
+ </div>
+</div>
+
+<style>
+ .hero {
+ display: grid;
+ align-items: center;
+ gap: 1rem;
+ }
+
+ .hero > img,
+ .hero > .hero-html {
+ object-fit: contain;
+ width: min(70%, 20rem);
+ height: auto;
+ margin-inline: auto;
+ }
+
+ .hero-html {
+ display: flex;
+ }
+
+ .stack {
+ flex-direction: column;
+ gap: clamp(1.5rem, calc(1.5rem + 1vw), 2rem);
+ text-align: center;
+ }
+
+ .copy {
+ flex-direction: column;
+ gap: 1rem;
+ align-items: center;
+ }
+
+ .copy > * {
+ max-width: 50ch;
+ }
+
+ h1 {
+ font-size: clamp(
+ var(--sl-text-3xl),
+ calc(0.25rem + 5vw),
+ var(--sl-text-6xl)
+ );
+ line-height: var(--sl-line-height-headings);
+ font-weight: 600;
+ color: var(--sl-color-white);
+ }
+
+ .tagline {
+ font-size: clamp(
+ var(--sl-text-base),
+ calc(0.0625rem + 2vw),
+ var(--sl-text-xl)
+ );
+ color: var(--sl-color-gray-2);
+ }
+
+ .actions {
+ gap: 1rem 2rem;
+ flex-wrap: wrap;
+ justify-content: center;
+ }
+
+ @media (min-width: 50rem) {
+ .hero {
+ grid-template-columns: 7fr 4fr;
+ gap: 3%;
+ padding-block: clamp(2.5rem, calc(1rem + 10vmin), 10rem);
+ }
+
+ .hero > img,
+ .hero > .hero-html {
+ order: 2;
+ width: min(100%, 25rem);
+ }
+
+ .stack {
+ text-align: start;
+ }
+
+ .copy {
+ align-items: flex-start;
+ }
+
+ .actions {
+ justify-content: flex-start;
+ }
+ }
+</style>
diff --git a/packages/starlight/components/Icon.astro b/packages/starlight/components/Icon.astro
index a8a54c87..6fed52e4 100644
--- a/packages/starlight/components/Icon.astro
+++ b/packages/starlight/components/Icon.astro
@@ -9,7 +9,7 @@ interface Props {
class?: string;
}
-const { name, label, size = '1em', color = '' } = Astro.props;
+const { name, label, size = '1em', color } = Astro.props;
const a11yAttrs = label
? ({ 'aria-label': label } as const)
: ({ 'aria-hidden': 'true' } as const);
@@ -22,13 +22,12 @@ const a11yAttrs = label
height="16"
viewBox="0 0 24 24"
fill="currentColor"
- style={`--sl-icon-color: ${color}; --sl-icon-size: ${size};`}
set:html={Icons[name]}
/>
-<style>
+<style define:vars={{ 'sl-icon-color': color, 'sl-icon-size': size }}>
svg {
- color: var(--sl-icon-color, inherit);
+ color: var(--sl-icon-color);
font-size: var(--sl-icon-size, 1em);
width: 1em;
height: 1em;
diff --git a/packages/starlight/components/Icons.ts b/packages/starlight/components/Icons.ts
index 4aa2f179..3c5a0e22 100644
--- a/packages/starlight/components/Icons.ts
+++ b/packages/starlight/components/Icons.ts
@@ -14,6 +14,8 @@ export const Icons = {
'<path fill-rule="evenodd" clip-rule="evenodd" d="M8.51562 3C7.99605 3 7.57486 3.42119 7.57486 3.94076V5.09057H2.94076C2.42119 5.09057 2 5.51176 2 6.03133C2 6.5509 2.42119 6.97209 2.94076 6.97209H10.3025C10.1154 8.43628 9.49493 9.81581 8.51605 10.9298C7.89546 10.2235 7.41119 9.40161 7.09425 8.50519C6.92107 8.01534 6.38356 7.75864 5.89371 7.93183C5.40386 8.10501 5.14715 8.64252 5.32034 9.13237C5.71804 10.2572 6.32594 11.2885 7.10503 12.1745C5.88484 13.0016 4.43607 13.4529 2.94076 13.4529C2.42119 13.4529 2 13.8741 2 14.3936C2 14.9132 2.42119 15.3344 2.94076 15.3344C4.96251 15.3344 6.91641 14.6763 8.51606 13.4787C8.58325 13.529 8.65118 13.5784 8.71984 13.627C9.88827 14.4533 11.2259 14.995 12.6263 15.2183L11.8634 16.7441C11.8576 16.7552 11.8519 16.7665 11.8465 16.7779L10.4616 19.5478C10.2292 20.0125 10.4176 20.5776 10.8823 20.8099C11.347 21.0423 11.9121 20.8539 12.1445 20.3892L13.2782 18.1218H19.0839L20.2176 20.3892C20.45 20.8539 21.015 21.0423 21.4798 20.8099C21.9445 20.5776 22.1328 20.0125 21.9005 19.5478L20.5162 16.7792C20.5104 16.7669 20.5043 16.7548 20.498 16.7428L17.0225 9.79176C16.8631 9.47304 16.5374 9.27172 16.181 9.27172C15.8247 9.27172 15.4989 9.47304 15.3396 9.79176L13.52 13.4309C12.236 13.3317 10.9971 12.8998 9.92708 12.1745C11.2086 10.7172 12.0005 8.89713 12.1961 6.97209H14.0905C14.61 6.97209 15.0312 6.5509 15.0312 6.03133C15.0312 5.51176 14.61 5.09057 14.0905 5.09057H9.45638V3.94076C9.45638 3.42119 9.03519 3 8.51562 3ZM14.9419 14.7944C14.9357 14.8074 14.9293 14.8203 14.9226 14.833L14.2189 16.2403H18.1431L16.181 12.3161L14.9419 14.7944Z"></path>',
pencil:
'<path d="M22 7.24a1 1 0 0 0-.29-.71l-4.24-4.24a1 1 0 0 0-1.1-.22 1 1 0 0 0-.32.22l-2.83 2.83L2.29 16.05a1 1 0 0 0-.29.71V21a1 1 0 0 0 1 1h4.24a1 1 0 0 0 .76-.29l10.87-10.93L21.71 8c.1-.1.17-.2.22-.33a1 1 0 0 0 0-.24v-.14l.07-.05ZM6.83 20H4v-2.83l9.93-9.93 2.83 2.83L6.83 20ZM18.17 8.66l-2.83-2.83 1.42-1.41 2.82 2.82-1.41 1.42Z"/>',
+ external:
+ '<path d="M19.33 10.18a1 1 0 0 1-.77 0 1 1 0 0 1-.62-.93l.01-1.83-8.2 8.2a1 1 0 0 1-1.41-1.42l8.2-8.2H14.7a1 1 0 0 1 0-2h4.25a1 1 0 0 1 1 1v4.25a1 1 0 0 1-.62.93Z"/><path d="M11 4a1 1 0 1 1 0 2H7a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-4a1 1 0 1 1 2 0v4a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3h4Z"/>',
moon: '<path d="M21.64 13C21.4957 12.8807 21.3207 12.8043 21.1351 12.7796C20.9494 12.7548 20.7606 12.7827 20.59 12.86C19.5326 13.3439 18.3829 13.593 17.22 13.59C15.0689 13.5874 13.006 12.7345 11.4812 11.2171C9.95632 9.69979 9.09321 7.64114 9.08001 5.49003C9.08457 4.81586 9.16848 4.14458 9.33001 3.49003C9.36429 3.31557 9.35143 3.13512 9.29277 2.96728C9.2341 2.79944 9.13175 2.65028 8.99626 2.53516C8.86076 2.42004 8.69702 2.34313 8.52191 2.31234C8.3468 2.28156 8.16665 2.29802 8.00001 2.36003C6.43234 3.06494 5.06958 4.15679 4.03977 5.53301C3.00996 6.90924 2.34689 8.52465 2.11286 10.2275C1.87883 11.9304 2.08152 13.6648 2.70188 15.2678C3.32225 16.8708 4.33993 18.2898 5.65931 19.3915C6.9787 20.4932 8.55649 21.2414 10.2445 21.5658C11.9324 21.8903 13.6752 21.7803 15.309 21.2463C16.9428 20.7122 18.414 19.7716 19.5844 18.5128C20.7548 17.254 21.5861 15.7183 22 14.05C22.0504 13.859 22.0431 13.6574 21.9791 13.4705C21.915 13.2836 21.797 13.1199 21.64 13ZM12.14 19.69C10.4618 19.6782 8.82821 19.1479 7.46301 18.1718C6.0978 17.1956 5.06768 15.8214 4.5137 14.2372C3.95971 12.6529 3.90895 10.9362 4.36835 9.32203C4.82776 7.70785 5.77487 6.27513 7.08001 5.22003V5.49003C7.08266 8.17851 8.15183 10.7561 10.0529 12.6572C11.9539 14.5582 14.5315 15.6274 17.22 15.63C17.9259 15.6326 18.63 15.5589 19.32 15.41C18.6299 16.7155 17.5965 17.8079 16.3312 18.5692C15.0659 19.3305 13.6167 19.7319 12.14 19.73V19.69Z"></path>',
sun: '<path d="M5 12C5 11.7348 4.89464 11.4804 4.70711 11.2929C4.51957 11.1054 4.26522 11 4 11H3C2.73478 11 2.48043 11.1054 2.29289 11.2929C2.10536 11.4804 2 11.7348 2 12C2 12.2652 2.10536 12.5196 2.29289 12.7071C2.48043 12.8946 2.73478 13 3 13H4C4.26522 13 4.51957 12.8946 4.70711 12.7071C4.89464 12.5196 5 12.2652 5 12ZM5.64 17L4.93 17.71C4.74375 17.8974 4.63921 18.1508 4.63921 18.415C4.63921 18.6792 4.74375 18.9326 4.93 19.12C5.11736 19.3063 5.37081 19.4108 5.635 19.4108C5.89919 19.4108 6.15264 19.3063 6.34 19.12L7.05 18.41C7.21383 18.2187 7.29943 17.9726 7.28971 17.7209C7.27999 17.4693 7.17566 17.2305 6.99756 17.0524C6.81947 16.8743 6.58073 16.77 6.32905 16.7603C6.07738 16.7506 5.8313 16.8362 5.64 17ZM12 5C12.2652 5 12.5196 4.89464 12.7071 4.70711C12.8946 4.51957 13 4.26522 13 4V3C13 2.73478 12.8946 2.48043 12.7071 2.29289C12.5196 2.10536 12.2652 2 12 2C11.7348 2 11.4804 2.10536 11.2929 2.29289C11.1054 2.48043 11 2.73478 11 3V4C11 4.26522 11.1054 4.51957 11.2929 4.70711C11.4804 4.89464 11.7348 5 12 5ZM17.66 7.34C17.9223 7.3389 18.1737 7.23474 18.36 7.05L19.07 6.34C19.1747 6.25035 19.2597 6.14004 19.3197 6.01597C19.3797 5.89191 19.4135 5.75677 19.4188 5.61905C19.4241 5.48133 19.4009 5.344 19.3506 5.21568C19.3004 5.08735 19.2241 4.9708 19.1266 4.87335C19.0292 4.77589 18.9126 4.69964 18.7843 4.64936C18.656 4.59909 18.5187 4.57588 18.3809 4.5812C18.2432 4.58652 18.1081 4.62025 17.984 4.68027C17.86 4.7403 17.7496 4.82532 17.66 4.93L17 5.64C16.8137 5.82736 16.7092 6.08081 16.7092 6.345C16.7092 6.60919 16.8137 6.86264 17 7.05C17.1763 7.22536 17.4116 7.32875 17.66 7.34ZM5.66 7.05C5.84626 7.23474 6.09766 7.3389 6.36 7.34C6.49161 7.34076 6.62207 7.31554 6.74391 7.26577C6.86574 7.21601 6.97656 7.14268 7.07 7.05C7.25625 6.86264 7.36079 6.60919 7.36079 6.345C7.36079 6.08081 7.25625 5.82736 7.07 5.64L6.36 4.93C6.26742 4.8361 6.15725 4.76136 6.03578 4.71005C5.91432 4.65873 5.78393 4.63184 5.65207 4.63091C5.52021 4.62998 5.38946 4.65503 5.26728 4.70463C5.14511 4.75424 5.0339 4.82742 4.94 4.92C4.8461 5.01258 4.77136 5.12275 4.72005 5.24422C4.66873 5.36568 4.64184 5.49607 4.64091 5.62793C4.63903 5.89423 4.74302 6.15037 4.93 6.34L5.66 7.05ZM21 11H20C19.7348 11 19.4804 11.1054 19.2929 11.2929C19.1054 11.4804 19 11.7348 19 12C19 12.2652 19.1054 12.5196 19.2929 12.7071C19.4804 12.8946 19.7348 13 20 13H21C21.2652 13 21.5196 12.8946 21.7071 12.7071C21.8946 12.5196 22 12.2652 22 12C22 11.7348 21.8946 11.4804 21.7071 11.2929C21.5196 11.1054 21.2652 11 21 11ZM18.36 17C18.17 16.8943 17.9508 16.8534 17.7355 16.8835C17.5202 16.9136 17.3205 17.0131 17.1668 17.1668C17.0131 17.3205 16.9136 17.5202 16.8835 17.7355C16.8534 17.9508 16.8943 18.17 17 18.36L17.71 19.07C17.8974 19.2563 18.1508 19.3608 18.415 19.3608C18.6792 19.3608 18.9326 19.2563 19.12 19.07C19.3063 18.8826 19.4108 18.6292 19.4108 18.365C19.4108 18.1008 19.3063 17.8474 19.12 17.66L18.36 17ZM12 6.5C10.9122 6.5 9.84883 6.82257 8.94436 7.42692C8.03989 8.03126 7.33494 8.89025 6.91866 9.89524C6.50238 10.9002 6.39346 12.0061 6.60568 13.073C6.8179 14.1399 7.34172 15.1199 8.11091 15.8891C8.8801 16.6583 9.86011 17.1821 10.927 17.3943C11.9939 17.6065 13.0998 17.4976 14.1048 17.0813C15.1098 16.6651 15.9687 15.9601 16.5731 15.0556C17.1774 14.1512 17.5 13.0878 17.5 12C17.4974 10.5421 16.917 9.14471 15.8862 8.11383C14.8553 7.08295 13.4579 6.50264 12 6.5ZM12 15.5C11.3078 15.5 10.6311 15.2947 10.0555 14.9101C9.47993 14.5256 9.03133 13.9789 8.76642 13.3394C8.50151 12.6999 8.4322 11.9961 8.56725 11.3172C8.7023 10.6383 9.03564 10.0146 9.52513 9.52513C10.0146 9.03564 10.6383 8.7023 11.3172 8.56725C11.9961 8.4322 12.6999 8.50151 13.3394 8.76642C13.9789 9.03133 14.5256 9.47993 14.9101 10.0555C15.2947 10.6311 15.5 11.3078 15.5 12C15.5 12.9283 15.1313 13.8185 14.4749 14.4749C13.8185 15.1313 12.9283 15.5 12 15.5ZM12 19C11.7348 19 11.4804 19.1054 11.2929 19.2929C11.1054 19.4804 11 19.7348 11 20V21C11 21.2652 11.1054 21.5196 11.2929 21.7071C11.4804 21.8946 11.7348 22 12 22C12.2652 22 12.5196 21.8946 12.7071 21.7071C12.8946 21.5196 13 21.2652 13 21V20C13 19.7348 12.8946 19.4804 12.7071 19.2929C12.5196 19.1054 12.2652 19 12 19Z"></path>',
laptop:
diff --git a/packages/starlight/components/SkipLink.astro b/packages/starlight/components/SkipLink.astro
index 31b38e70..e4e88440 100644
--- a/packages/starlight/components/SkipLink.astro
+++ b/packages/starlight/components/SkipLink.astro
@@ -12,11 +12,13 @@ const t = useTranslations(Astro.props.locale);
<style>
a {
+ clip: rect(0, 0, 0, 0);
position: fixed;
top: 0.75rem;
inset-inline-start: 0.75rem;
}
a:focus {
+ clip: unset;
z-index: var(--sl-z-index-skiplink);
display: block;
padding: 0.5rem 1rem;
diff --git a/packages/starlight/index.astro b/packages/starlight/index.astro
index acbfdc1c..b3d5234a 100644
--- a/packages/starlight/index.astro
+++ b/packages/starlight/index.astro
@@ -24,6 +24,7 @@ import SkipLink from './components/SkipLink.astro';
import ThemeProvider from './components/ThemeProvider.astro';
import PageFrame from './layout/PageFrame.astro';
import TwoColumnContent from './layout/TwoColumnContent.astro';
+import Hero from './components/Hero.astro';
// Remark component CSS (needs to override `MarkdownContent.astro`)
import './style/asides.css';
@@ -48,9 +49,10 @@ const tocConfig = !hasSidebar
? entry.data.tableOfContents
: config.tableOfContents;
const hasToC = Boolean(tocConfig);
+const hasHero = Boolean(entry.data.hero);
---
-<html lang={lang} dir={dir} data-has-toc={hasToC} data-has-sidebar={hasSidebar}>
+<html lang={lang} dir={dir} data-has-toc={hasToC} data-has-sidebar={hasSidebar} data-has-hero={hasHero}>
<head>
<HeadSEO data={entry.data} lang={lang} />
<style>
@@ -88,19 +90,27 @@ const hasToC = Boolean(tocConfig);
<TwoColumnContent {hasToC}>
<RightSidebar slot="right-sidebar" {headings} {locale} {tocConfig} />
<main data-pagefind-body lang={entryMeta.lang} dir={entryMeta.dir}>
- <ContentPanel>
- <h1
- id="starlight__overview"
- style="font-size: var(--sl-text-h1); line-height: var(--sl-line-height-headings); font-weight: 600; color: var(--sl-color-white); margin-top: 1rem;"
- >
- {entry.data.title}
- </h1>
- {isFallback && <FallbackContentNotice {locale} />}
- </ContentPanel>
- <ContentPanel>
- <MarkdownContent><Content /></MarkdownContent>
- <Footer {...{ entry, dir, lang, locale, sidebar }} />
- </ContentPanel>
+ {/* TODO: Revisit how this logic flows. */}
+ {entry.data.hero ? (
+ <ContentPanel>
+ <Hero hero={entry.data.hero} fallbackTitle={entry.data.title} />
+ <MarkdownContent><Content /></MarkdownContent>
+ </ContentPanel>
+ ) : (
+ <ContentPanel>
+ <h1
+ id="starlight__overview"
+ style="font-size: var(--sl-text-h1); line-height: var(--sl-line-height-headings); font-weight: 600; color: var(--sl-color-white); margin-top: 1rem;"
+ >
+ {entry.data.title}
+ </h1>
+ {isFallback && <FallbackContentNotice {locale} />}
+ </ContentPanel>
+ <ContentPanel>
+ <MarkdownContent><Content /></MarkdownContent>
+ <Footer {...{ entry, dir, lang, locale, sidebar }} />
+ </ContentPanel>
+ )}
</main>
</TwoColumnContent>
</PageFrame>
diff --git a/packages/starlight/schema.ts b/packages/starlight/schema.ts
index 74c8843b..690e1555 100644
--- a/packages/starlight/schema.ts
+++ b/packages/starlight/schema.ts
@@ -1,38 +1,117 @@
import { z } from 'astro/zod';
import { HeadConfigSchema } from './schemas/head';
import { TableOfContentsSchema } from './schemas/tableOfContents';
+import { Icons } from './components/Icons';
export { i18nSchema } from './schemas/i18n';
+type IconName = keyof typeof Icons;
+const iconNames = Object.keys(Icons) as [IconName, ...IconName[]];
+
+type ImageFunction = () => z.ZodObject<{
+ src: z.ZodString;
+ width: z.ZodNumber;
+ height: z.ZodNumber;
+ format: z.ZodUnion<
+ [
+ z.ZodLiteral<'png'>,
+ z.ZodLiteral<'jpg'>,
+ z.ZodLiteral<'jpeg'>,
+ z.ZodLiteral<'tiff'>,
+ z.ZodLiteral<'webp'>,
+ z.ZodLiteral<'gif'>,
+ z.ZodLiteral<'svg'>
+ ]
+ >;
+}>;
+
export function docsSchema() {
- return z.object({
- /** The title of the current page. Required. */
- title: z.string(),
-
- /**
- * A short description of the current page’s content. Optional, but recommended.
- * A good description is 150–160 characters long and outlines the key content
- * of the page in a clear and engaging way.
- */
- description: z.string().optional(),
-
- /**
- * Custom URL where a reader can edit this page.
- * Overrides the `editLink.baseUrl` global config if set.
- *
- * Can also be set to `false` to disable showing an edit link on this page.
- */
- editUrl: z.union([z.string().url(), z.boolean()]).optional().default(true),
-
- /** Set custom `<head>` tags just for this page. */
- head: HeadConfigSchema(),
-
- /** Override global table of contents configuration for this page. */
- tableOfContents: TableOfContentsSchema().optional(),
-
- /**
- * Set the layout style for this page.
- * Can be `'doc'` (the default) or `'splash'` for a wider layout without any sidebars.
- */
- template: z.enum(['doc', 'splash']).default('doc'),
- });
+ return ({ image }: { image: ImageFunction }) =>
+ z.object({
+ /** The title of the current page. Required. */
+ title: z.string(),
+
+ /**
+ * A short description of the current page’s content. Optional, but recommended.
+ * A good description is 150–160 characters long and outlines the key content
+ * of the page in a clear and engaging way.
+ */
+ description: z.string().optional(),
+
+ /**
+ * Custom URL where a reader can edit this page.
+ * Overrides the `editLink.baseUrl` global config if set.
+ *
+ * Can also be set to `false` to disable showing an edit link on this page.
+ */
+ editUrl: z
+ .union([z.string().url(), z.boolean()])
+ .optional()
+ .default(true),
+
+ /** Set custom `<head>` tags just for this page. */
+ head: HeadConfigSchema(),
+
+ /** Override global table of contents configuration for this page. */
+ tableOfContents: TableOfContentsSchema().optional(),
+
+ /**
+ * Set the layout style for this page.
+ * Can be `'doc'` (the default) or `'splash'` for a wider layout without any sidebars.
+ */
+ template: z.enum(['doc', 'splash']).default('doc'),
+
+ /** Display a hero section on this page. */
+ hero: z
+ .object({
+ /**
+ * The large title text to show. If not provided, will default to the top-level `title`.
+ * Can include HTML.
+ */
+ title: z.string().optional(),
+ /**
+ * A short bit of text about your project.
+ * Will be displayed in a smaller size below the title.
+ */
+ tagline: z.string().optional(),
+ /** The image to use in the hero. You can provide either a relative `file` path or raw `html`. */
+ image: z
+ .object({
+ /** Alt text for screenreaders and other assistive technologies describing your hero image. */
+ alt: z.string().default(''),
+ /** Relative path to an image file in your repo, e.g. `../../assets/hero.png`. */
+ file: image().optional(),
+ /** Raw HTML string instead of an image file. Useful for inline SVGs or more complex hero content. */
+ html: z.string().optional(),
+ })
+ .optional(),
+ /** An array of call-to-action links displayed at the bottom of the hero. */
+ actions: z
+ .object({
+ /** Text label displayed in the link. */
+ text: z.string(),
+ /** Value for the link’s `href` attribute, e.g. `/page` or `https://mysite.com`. */
+ link: z.string(),
+ /** Button style to use. One of `primary`, `secondary`, or `minimal` (the default). */
+ variant: z
+ .enum(['primary', 'secondary', 'minimal'])
+ .default('minimal'),
+ /**
+ * An optional icon to display alongside the link text.
+ * Can be an inline `<svg>` or the name of one of Starlight’s built-in icons.
+ */
+ icon: z
+ .union([z.enum(iconNames), z.string().startsWith('<svg')])
+ .transform((icon) => {
+ const parsedIcon = z.enum(iconNames).safeParse(icon);
+ return parsedIcon.success
+ ? ({ type: 'icon', name: parsedIcon.data } as const)
+ : ({ type: 'raw', html: icon } as const);
+ })
+ .optional(),
+ })
+ .array()
+ .default([]),
+ })
+ .optional(),
+ });
}
diff --git a/packages/starlight/style/props.css b/packages/starlight/style/props.css
index 7c3081d1..aa0b45c6 100644
--- a/packages/starlight/style/props.css
+++ b/packages/starlight/style/props.css
@@ -90,6 +90,7 @@
--sl-text-3xl: 1.8125rem; /* 29px */
--sl-text-4xl: 2.1875rem; /* 35px */
--sl-text-5xl: 2.625rem; /* 42px */
+ --sl-text-6xl: 4rem; /* 64px */
--sl-text-body: var(--sl-text-base);
--sl-text-body-sm: var(--sl-text-xs);