diff options
author | Shubham Padia | 2025-07-16 20:33:15 +0700 |
---|---|---|
committer | GitHub | 2025-07-16 15:33:15 +0200 |
commit | 778b743cdb832551ed576c745728358d8bbf9d7a (patch) | |
tree | a3e9d3c6f51c86b43a53ed7dd1f69e36497357d8 | |
parent | 3917b206da26522f73bbe0c1120de9acae5972c5 (diff) | |
download | IT.starlight-778b743cdb832551ed576c745728358d8bbf9d7a.tar.gz IT.starlight-778b743cdb832551ed576c745728358d8bbf9d7a.tar.bz2 IT.starlight-778b743cdb832551ed576c745728358d8bbf9d7a.zip |
Aside: Support custom icons (#2261)
Co-authored-by: HiDeoo <494699+HiDeoo@users.noreply.github.com>
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
18 files changed, 200 insertions, 7 deletions
diff --git a/.changeset/brave-apples-give.md b/.changeset/brave-apples-give.md new file mode 100644 index 00000000..4963ac42 --- /dev/null +++ b/.changeset/brave-apples-give.md @@ -0,0 +1,5 @@ +--- +'@astrojs/starlight-markdoc': minor +--- + +Adds support for the `icon` attribute in the `aside` tag, allowing the use of any of Starlight’s built-in icons. diff --git a/.changeset/five-flowers-flash.md b/.changeset/five-flowers-flash.md new file mode 100644 index 00000000..6e5763bb --- /dev/null +++ b/.changeset/five-flowers-flash.md @@ -0,0 +1,5 @@ +--- +'@astrojs/starlight': minor +--- + +Adds support for using any of Starlight’s built-in icons in asides. diff --git a/docs/src/content/docs/components/asides.mdx b/docs/src/content/docs/components/asides.mdx index a28375b0..e3c0ac8c 100644 --- a/docs/src/content/docs/components/asides.mdx +++ b/docs/src/content/docs/components/asides.mdx @@ -132,6 +132,36 @@ A warning aside *with* a custom title. </Preview> +### Use custom icons + +Override the default aside icons by using the [`icon`](#icon) attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons). + +<Preview> + +```mdx 'icon="starlight"' +import { Aside } from '@astrojs/starlight/components'; + +<Aside type="tip" icon="starlight"> + A warning aside *with* a custom icon. +</Aside> +``` + +<Fragment slot="markdoc"> + +```markdoc 'icon="starlight"' +{% aside type="tip" icon="starlight" %} +A warning aside *with* a custom icon. +{% /aside %} +``` + +</Fragment> + +<Aside slot="preview" type="tip" icon="starlight"> + A warning aside *with* a custom icon. +</Aside> + +</Preview> + ## `<Aside>` Props **Implementation:** [`Aside.astro`](https://github.com/withastro/starlight/blob/main/packages/starlight/user-components/Aside.astro) @@ -156,3 +186,9 @@ The type of aside to display: The title of the aside to display. If `title` is not set, the default title for the current aside `type` will be used. + +### `icon` + +**type:** [`StarlightIcon`](/reference/icons/#starlighticon-type) + +An aside can include an `icon` attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons). diff --git a/docs/src/content/docs/guides/authoring-content.mdx b/docs/src/content/docs/guides/authoring-content.mdx index be27ca80..9c6a2ad7 100644 --- a/docs/src/content/docs/guides/authoring-content.mdx +++ b/docs/src/content/docs/guides/authoring-content.mdx @@ -151,6 +151,21 @@ Astro helps you build faster websites with [“Islands Architecture”](https:// ::: ``` +### Custom aside icons + +You can specify a custom icon for the aside in curly brackets following the aside type or [custom title](#custom-aside-titles), e.g. `:::tip{icon="heart"}` or `:::tip[Did you know?]{icon="heart"}` respectively. +The icon name must be set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons). + +:::tip{icon="heart"} +Astro helps you build faster websites with [“Islands Architecture”](https://docs.astro.build/en/concepts/islands/). +::: + +```md +:::tip{icon="heart"} +Astro helps you build faster websites with [“Islands Architecture”](https://docs.astro.build/en/concepts/islands/). +::: +``` + ### More aside types Caution and danger asides are helpful for drawing a user’s attention to details that may trip them up. diff --git a/packages/markdoc/index.mjs b/packages/markdoc/index.mjs index 82a472f4..32f19ecf 100644 --- a/packages/markdoc/index.mjs +++ b/packages/markdoc/index.mjs @@ -67,6 +67,10 @@ export const StarlightMarkdocPreset = { aside: { render: component('@astrojs/starlight/components', 'Aside'), attributes: { + icon: { + type: String, + required: false, + }, title: { type: String, required: false, diff --git a/packages/markdoc/package.json b/packages/markdoc/package.json index 1d60681d..e949671f 100644 --- a/packages/markdoc/package.json +++ b/packages/markdoc/package.json @@ -23,7 +23,7 @@ }, "peerDependencies": { "@astrojs/markdoc": ">=0.12.1", - "@astrojs/starlight": ">=0.34.0" + "@astrojs/starlight": ">=0.35.0" }, "publishConfig": { "provenance": true diff --git a/packages/starlight/__tests__/remark-rehype/asides.test.ts b/packages/starlight/__tests__/remark-rehype/asides.test.ts index 35ad73fb..04ab62cf 100644 --- a/packages/starlight/__tests__/remark-rehype/asides.test.ts +++ b/packages/starlight/__tests__/remark-rehype/asides.test.ts @@ -1,7 +1,7 @@ import { createMarkdownProcessor, type MarkdownProcessor } from '@astrojs/markdown-remark'; import type { Root } from 'mdast'; import { visit } from 'unist-util-visit'; -import { describe, expect, test } from 'vitest'; +import { describe, expect, test, vi } from 'vitest'; import { starlightAsides, remarkDirectivesRestoration } from '../../integrations/asides'; import { createTranslationSystemFromFs } from '../../utils/translations-fs'; import { StarlightConfigSchema, type StarlightUserConfig } from '../../utils/user-config'; @@ -126,6 +126,80 @@ Some text ); }); +describe('custom icons', () => { + test.each(['note', 'tip', 'caution', 'danger'])('%s with custom icon', async (type) => { + const res = await renderMarkdown(` +:::${type}{icon="heart"} +Some text +::: + `); + await expect(res.code).toMatchFileSnapshot( + `./snapshots/generates-aside-${type}-custom-icon.html` + ); + }); + + test.each(['note', 'tip', 'caution', 'danger'])('%s with invalid custom icon', async (type) => { + // Temporarily mock console.error to avoid cluttering test output when the Astro Markdown + // processor logs an error before rethrowing it. + // https://github.com/withastro/astro/blob/98853ce7e31a8002fd7be83d7932a53cfec84d27/packages/markdown/remark/src/index.ts#L161 + const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {}); + + await expect(async () => + renderMarkdown( + ` +:::${type}{icon="invalid-icon-name"} +Some text +::: + ` + ) + ).rejects.toThrowError( + // We are not relying on `toThrowErrorMatchingInlineSnapshot()` and our custom snapshot + // serializer in this specific test as error thrown in a remark plugin includes a dynamic file + // path. + expect.objectContaining({ + type: 'AstroUserError', + hint: expect.stringMatching( + /An aside custom icon must be set to the name of one of Starlight’s built-in icons, but received `invalid-icon-name`/ + ), + }) + ); + + // Restore the original console.error implementation. + consoleError.mockRestore(); + }); + + test('test custom icon with multiple paths inside the svg', async () => { + const res = await renderMarkdown(` +:::note{icon="external"} +Some text +::: + `); + await expect(res.code).toMatchFileSnapshot( + `./snapshots/generates-aside-note-multiple-path-custom-icon.html` + ); + const pathCount = (res.code.match(/path/g) || []).length; + // If we have two pairs of opening and closing tags of path, + // we will have 4 occurences of that word. + expect(pathCount).eq(4); + }); +}); + +describe('custom labels with custom icons', () => { + test.each(['note', 'tip', 'caution', 'danger'])('%s with custom label', async (type) => { + const label = 'Custom Label'; + const res = await renderMarkdown(` +:::${type}[${label}]{icon="heart"} +Some text +::: + `); + expect(res.code).includes(`aria-label="${label}"`); + expect(res.code).includes(`</svg>${label}</p>`); + await expect(res.code).toMatchFileSnapshot( + `./snapshots/generates-aside-${type}-custom-label-and-icon.html` + ); + }); +}); + test('ignores unknown directive variants', async () => { const res = await renderMarkdown(` :::unknown diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-icon.html new file mode 100644 index 00000000..564ad6cd --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-icon.html @@ -0,0 +1 @@ +<aside aria-label="Caution" class="starlight-aside starlight-aside--caution"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Caution</p><div class="starlight-aside__content"><p>Some text</p></div></aside>
\ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-label-and-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-label-and-icon.html new file mode 100644 index 00000000..c6075535 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-caution-custom-label-and-icon.html @@ -0,0 +1 @@ +<aside aria-label="Custom Label" class="starlight-aside starlight-aside--caution"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Custom Label</p><div class="starlight-aside__content"><p>Some text</p></div></aside>
\ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-icon.html new file mode 100644 index 00000000..c276e379 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-icon.html @@ -0,0 +1 @@ +<aside aria-label="Danger" class="starlight-aside starlight-aside--danger"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Danger</p><div class="starlight-aside__content"><p>Some text</p></div></aside>
\ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-label-and-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-label-and-icon.html new file mode 100644 index 00000000..fc8c46ae --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-danger-custom-label-and-icon.html @@ -0,0 +1 @@ +<aside aria-label="Custom Label" class="starlight-aside starlight-aside--danger"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Custom Label</p><div class="starlight-aside__content"><p>Some text</p></div></aside>
\ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-icon.html new file mode 100644 index 00000000..5727e7be --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-icon.html @@ -0,0 +1 @@ +<aside aria-label="Note" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Note</p><div class="starlight-aside__content"><p>Some text</p></div></aside>
\ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-label-and-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-label-and-icon.html new file mode 100644 index 00000000..506831fc --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-custom-label-and-icon.html @@ -0,0 +1 @@ +<aside aria-label="Custom Label" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Custom Label</p><div class="starlight-aside__content"><p>Some text</p></div></aside>
\ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-multiple-path-custom-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-multiple-path-custom-icon.html new file mode 100644 index 00000000..35cd1b77 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-note-multiple-path-custom-icon.html @@ -0,0 +1 @@ +<aside aria-label="Note" class="starlight-aside starlight-aside--note"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><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><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"></path></svg>Note</p><div class="starlight-aside__content"><p>Some text</p></div></aside>
\ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-icon.html new file mode 100644 index 00000000..6f6e1eb9 --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-icon.html @@ -0,0 +1 @@ +<aside aria-label="Tip" class="starlight-aside starlight-aside--tip"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Tip</p><div class="starlight-aside__content"><p>Some text</p></div></aside>
\ No newline at end of file diff --git a/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-label-and-icon.html b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-label-and-icon.html new file mode 100644 index 00000000..b263140d --- /dev/null +++ b/packages/starlight/__tests__/remark-rehype/snapshots/generates-aside-tip-custom-label-and-icon.html @@ -0,0 +1 @@ +<aside aria-label="Custom Label" class="starlight-aside starlight-aside--tip"><p class="starlight-aside__title" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="starlight-aside__icon"><path d="M20.16 5A6.29 6.29 0 0 0 12 4.36a6.27 6.27 0 0 0-8.16 9.48l6.21 6.22a2.78 2.78 0 0 0 3.9 0l6.21-6.22a6.27 6.27 0 0 0 0-8.84m-1.41 7.46-6.21 6.21a.76.76 0 0 1-1.08 0l-6.21-6.24a4.29 4.29 0 0 1 0-6 4.27 4.27 0 0 1 6 0 1 1 0 0 0 1.42 0 4.27 4.27 0 0 1 6 0 4.29 4.29 0 0 1 .08 6Z"></path></svg>Custom Label</p><div class="starlight-aside__content"><p>Some text</p></div></aside>
\ No newline at end of file diff --git a/packages/starlight/integrations/asides.ts b/packages/starlight/integrations/asides.ts index 85334d70..42e6098d 100644 --- a/packages/starlight/integrations/asides.ts +++ b/packages/starlight/integrations/asides.ts @@ -1,7 +1,7 @@ /// <reference types="mdast-util-directive" /> import type { AstroConfig, AstroIntegration, AstroUserConfig } from 'astro'; -import { h as _h, s as _s, type Properties } from 'hastscript'; +import { h as _h, s as _s, type Properties, type Result } from 'hastscript'; import type { Node, Paragraph as P, Parent, PhrasingContent, Root } from 'mdast'; import { type Directives, @@ -14,8 +14,12 @@ import { toString } from 'mdast-util-to-string'; import remarkDirective from 'remark-directive'; import type { Plugin, Transformer } from 'unified'; import { visit } from 'unist-util-visit'; -import type { HookParameters, StarlightConfig } from '../types'; +import type { HookParameters, StarlightConfig, StarlightIcon } from '../types'; import { getRemarkRehypeDocsCollectionPath, shouldTransformFile } from './remark-rehype-utils'; +import { Icons } from '../components/Icons'; +import { fromHtml } from 'hast-util-from-html'; +import type { Element } from 'hast'; +import { AstroError } from 'astro/errors'; interface AsidesOptions { starlightConfig: Pick<StarlightConfig, 'defaultLocale' | 'locales'>; @@ -88,6 +92,20 @@ function transformUnhandledDirective( } } +/** Hacky function that generates the children of an mdast SVG tree. */ +function makeSvgChildNodes(children: Result['children']): any[] { + const nodes: P[] = []; + for (const child of children) { + if (child.type !== 'element') continue; + nodes.push({ + type: 'paragraph', + data: { hName: child.tagName, hProperties: child.properties }, + children: makeSvgChildNodes(child.children), + }); + } + return nodes; +} + /** * remark plugin that converts blocks delimited with `:::` into styled * asides (a.k.a. “callouts”, “admonitions”, etc.). Depends on the @@ -164,6 +182,7 @@ function remarkAsides(options: AsidesOptions): Plugin<[], Root> { return; } const variant = node.name; + const attributes = node.attributes; if (!isAsideVariant(variant)) return; // remark-directive converts a container’s “label” to a paragraph added as the head of its @@ -185,6 +204,19 @@ function remarkAsides(options: AsidesOptions): Plugin<[], Root> { node.children.splice(0, 1); } + let iconPath = iconPaths[variant]; + + if (attributes?.['icon']) { + const iconName = attributes['icon'] as StarlightIcon; + const icon = Icons[iconName]; + if (!icon) throwInvalidAsideIconError(iconName); + // Omit the root node and return only the first child which is the SVG element. + const iconHastTree = fromHtml(`<svg>${icon}</svg>`, { fragment: true, space: 'svg' }) + .children[0] as Element; + // Render all SVG child nodes. + iconPath = makeSvgChildNodes(iconHastTree.children); + } + const aside = h( 'aside', { @@ -202,7 +234,7 @@ function remarkAsides(options: AsidesOptions): Plugin<[], Root> { fill: 'currentColor', class: 'starlight-aside__icon', }, - iconPaths[variant] + iconPath ), ...titleNode, ]), @@ -221,6 +253,14 @@ function remarkAsides(options: AsidesOptions): Plugin<[], Root> { type RemarkPlugins = NonNullable<NonNullable<AstroUserConfig['markdown']>['remarkPlugins']>; +export function throwInvalidAsideIconError(icon: string) { + throw new AstroError( + 'Invalid aside icon', + `An aside custom icon must be set to the name of one of Starlight\’s built-in icons, but received \`${icon}\`.\n\n` + + 'See https://starlight.astro.build/reference/icons/#all-icons for a list of available icons.' + ); +} + export function starlightAsides(options: AsidesOptions): RemarkPlugins { return [remarkDirective, remarkAsides(options)]; } diff --git a/packages/starlight/user-components/Aside.astro b/packages/starlight/user-components/Aside.astro index 785a4f20..1a1ab00d 100644 --- a/packages/starlight/user-components/Aside.astro +++ b/packages/starlight/user-components/Aside.astro @@ -1,6 +1,8 @@ --- import { AstroError } from 'astro/errors'; import Icon from './Icon.astro'; +import { Icons, type StarlightIcon } from '../components/Icons'; +import { throwInvalidAsideIconError } from '../integrations/asides'; const asideVariants = ['note', 'tip', 'caution', 'danger'] as const; const icons = { note: 'information', tip: 'rocket', caution: 'warning', danger: 'error' } as const; @@ -8,9 +10,10 @@ const icons = { note: 'information', tip: 'rocket', caution: 'warning', danger: interface Props { type?: (typeof asideVariants)[number]; title?: string; + icon?: StarlightIcon; } -let { type = 'note', title } = Astro.props; +let { type = 'note', title, icon } = Astro.props; if (!asideVariants.includes(type)) { throw new AstroError( @@ -20,6 +23,8 @@ if (!asideVariants.includes(type)) { ); } +if (icon && !Icons[icon]) throwInvalidAsideIconError(icon); + if (!title) { title = Astro.locals.t(`aside.${type}`); } @@ -27,7 +32,7 @@ if (!title) { <aside aria-label={title} class={`starlight-aside starlight-aside--${type}`}> <p class="starlight-aside__title" aria-hidden="true"> - <Icon name={icons[type]} class="starlight-aside__icon" />{title} + <Icon name={icon || icons[type]} class="starlight-aside__icon" />{title} </p> <div class="starlight-aside__content"> <slot /> |