Skip to content

Commit 778b743

Browse files
shubham-padiaHiDeoodelucis
authored
Aside: Support custom icons (#2261)
Co-authored-by: HiDeoo <[email protected]> Co-authored-by: Chris Swithinbank <[email protected]>
1 parent 3917b20 commit 778b743

18 files changed

+200
-7
lines changed

.changeset/brave-apples-give.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@astrojs/starlight-markdoc': minor
3+
---
4+
5+
Adds support for the `icon` attribute in the `aside` tag, allowing the use of any of Starlight’s built-in icons.

.changeset/five-flowers-flash.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@astrojs/starlight': minor
3+
---
4+
5+
Adds support for using any of Starlight’s built-in icons in asides.

docs/src/content/docs/components/asides.mdx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,36 @@ A warning aside *with* a custom title.
132132

133133
</Preview>
134134

135+
### Use custom icons
136+
137+
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).
138+
139+
<Preview>
140+
141+
```mdx 'icon="starlight"'
142+
import { Aside } from '@astrojs/starlight/components';
143+
144+
<Aside type="tip" icon="starlight">
145+
A warning aside *with* a custom icon.
146+
</Aside>
147+
```
148+
149+
<Fragment slot="markdoc">
150+
151+
```markdoc 'icon="starlight"'
152+
{% aside type="tip" icon="starlight" %}
153+
A warning aside *with* a custom icon.
154+
{% /aside %}
155+
```
156+
157+
</Fragment>
158+
159+
<Aside slot="preview" type="tip" icon="starlight">
160+
A warning aside *with* a custom icon.
161+
</Aside>
162+
163+
</Preview>
164+
135165
## `<Aside>` Props
136166

137167
**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:
156186

157187
The title of the aside to display.
158188
If `title` is not set, the default title for the current aside `type` will be used.
189+
190+
### `icon`
191+
192+
**type:** [`StarlightIcon`](/reference/icons/#starlighticon-type)
193+
194+
An aside can include an `icon` attribute set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons).

docs/src/content/docs/guides/authoring-content.mdx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,21 @@ Astro helps you build faster websites with [“Islands Architecture”](https://
151151
:::
152152
```
153153

154+
### Custom aside icons
155+
156+
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.
157+
The icon name must be set to the name of [one of Starlight’s built-in icons](/reference/icons/#all-icons).
158+
159+
:::tip{icon="heart"}
160+
Astro helps you build faster websites with [“Islands Architecture”](https://docs.astro.build/en/concepts/islands/).
161+
:::
162+
163+
```md
164+
:::tip{icon="heart"}
165+
Astro helps you build faster websites with [“Islands Architecture”](https://docs.astro.build/en/concepts/islands/).
166+
:::
167+
```
168+
154169
### More aside types
155170

156171
Caution and danger asides are helpful for drawing a user’s attention to details that may trip them up.

packages/markdoc/index.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ export const StarlightMarkdocPreset = {
6767
aside: {
6868
render: component('@astrojs/starlight/components', 'Aside'),
6969
attributes: {
70+
icon: {
71+
type: String,
72+
required: false,
73+
},
7074
title: {
7175
type: String,
7276
required: false,

packages/markdoc/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
},
2424
"peerDependencies": {
2525
"@astrojs/markdoc": ">=0.12.1",
26-
"@astrojs/starlight": ">=0.34.0"
26+
"@astrojs/starlight": ">=0.35.0"
2727
},
2828
"publishConfig": {
2929
"provenance": true

packages/starlight/__tests__/remark-rehype/asides.test.ts

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createMarkdownProcessor, type MarkdownProcessor } from '@astrojs/markdown-remark';
22
import type { Root } from 'mdast';
33
import { visit } from 'unist-util-visit';
4-
import { describe, expect, test } from 'vitest';
4+
import { describe, expect, test, vi } from 'vitest';
55
import { starlightAsides, remarkDirectivesRestoration } from '../../integrations/asides';
66
import { createTranslationSystemFromFs } from '../../utils/translations-fs';
77
import { StarlightConfigSchema, type StarlightUserConfig } from '../../utils/user-config';
@@ -126,6 +126,80 @@ Some text
126126
);
127127
});
128128

129+
describe('custom icons', () => {
130+
test.each(['note', 'tip', 'caution', 'danger'])('%s with custom icon', async (type) => {
131+
const res = await renderMarkdown(`
132+
:::${type}{icon="heart"}
133+
Some text
134+
:::
135+
`);
136+
await expect(res.code).toMatchFileSnapshot(
137+
`./snapshots/generates-aside-${type}-custom-icon.html`
138+
);
139+
});
140+
141+
test.each(['note', 'tip', 'caution', 'danger'])('%s with invalid custom icon', async (type) => {
142+
// Temporarily mock console.error to avoid cluttering test output when the Astro Markdown
143+
// processor logs an error before rethrowing it.
144+
// https://github.com/withastro/astro/blob/98853ce7e31a8002fd7be83d7932a53cfec84d27/packages/markdown/remark/src/index.ts#L161
145+
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {});
146+
147+
await expect(async () =>
148+
renderMarkdown(
149+
`
150+
:::${type}{icon="invalid-icon-name"}
151+
Some text
152+
:::
153+
`
154+
)
155+
).rejects.toThrowError(
156+
// We are not relying on `toThrowErrorMatchingInlineSnapshot()` and our custom snapshot
157+
// serializer in this specific test as error thrown in a remark plugin includes a dynamic file
158+
// path.
159+
expect.objectContaining({
160+
type: 'AstroUserError',
161+
hint: expect.stringMatching(
162+
/An aside custom icon must be set to the name of one of Starlights built-in icons, but received `invalid-icon-name`/
163+
),
164+
})
165+
);
166+
167+
// Restore the original console.error implementation.
168+
consoleError.mockRestore();
169+
});
170+
171+
test('test custom icon with multiple paths inside the svg', async () => {
172+
const res = await renderMarkdown(`
173+
:::note{icon="external"}
174+
Some text
175+
:::
176+
`);
177+
await expect(res.code).toMatchFileSnapshot(
178+
`./snapshots/generates-aside-note-multiple-path-custom-icon.html`
179+
);
180+
const pathCount = (res.code.match(/path/g) || []).length;
181+
// If we have two pairs of opening and closing tags of path,
182+
// we will have 4 occurences of that word.
183+
expect(pathCount).eq(4);
184+
});
185+
});
186+
187+
describe('custom labels with custom icons', () => {
188+
test.each(['note', 'tip', 'caution', 'danger'])('%s with custom label', async (type) => {
189+
const label = 'Custom Label';
190+
const res = await renderMarkdown(`
191+
:::${type}[${label}]{icon="heart"}
192+
Some text
193+
:::
194+
`);
195+
expect(res.code).includes(`aria-label="${label}"`);
196+
expect(res.code).includes(`</svg>${label}</p>`);
197+
await expect(res.code).toMatchFileSnapshot(
198+
`./snapshots/generates-aside-${type}-custom-label-and-icon.html`
199+
);
200+
});
201+
});
202+
129203
test('ignores unknown directive variants', async () => {
130204
const res = await renderMarkdown(`
131205
:::unknown
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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>

0 commit comments

Comments
 (0)