Skip to content

Commit 903a579

Browse files
HiDeoodelucis
andauthored
Add support for custom HTML attributes to sidebar links (#774)
Co-authored-by: Chris Swithinbank <[email protected]>
1 parent b7b23a2 commit 903a579

21 files changed

+390
-88
lines changed

.changeset/fuzzy-foxes-confess.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@astrojs/starlight': minor
3+
---
4+
5+
Support adding HTML attributes to sidebar links from config and frontmatter

docs/src/components/sidebar-preview.astro

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
import type { AutoSidebarGroup, SidebarItem } from '../../../packages/starlight/utils/user-config';
2+
import type { AutoSidebarGroup, SidebarItem } from '../../../packages/starlight/schemas/sidebar';
33
import SidebarSublist from '../../../packages/starlight/components/SidebarSublist.astro';
44
import type { SidebarEntry } from '../../../packages/starlight/utils/navigation';
55
@@ -20,11 +20,10 @@ function makeEntries(items: SidebarConfig): SidebarEntry[] {
2020
href: item.link,
2121
isCurrent: false,
2222
badge: item.badge,
23+
attrs: item.attrs ?? {},
2324
};
2425
}
2526
26-
item;
27-
2827
return {
2928
type: 'group',
3029
label: item.label,

docs/src/content/docs/guides/sidebar.mdx

+44
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,50 @@ The configuration above generates the following sidebar:
316316
]}
317317
/>
318318

319+
## Custom HTML attributes
320+
321+
Links can also include an `attrs` property to add custom HTML attributes to the link element.
322+
323+
In the following example, `attrs` is used to add a `target="_blank"` attribute, so that the link opens in a new tab, and to apply a custom `style` attribute to italicize the link label:
324+
325+
```js
326+
starlight({
327+
sidebar: [
328+
{
329+
label: 'Guides',
330+
items: [
331+
// An external link to the Astro docs opening in a new tab.
332+
{
333+
label: 'Astro Docs',
334+
link: 'https://docs.astro.build/',
335+
attrs: { target: '_blank', style: 'font-style: italic' },
336+
},
337+
],
338+
},
339+
],
340+
});
341+
```
342+
343+
The configuration above generates the following sidebar:
344+
345+
<SidebarPreview
346+
config={[
347+
{
348+
label: 'Guides',
349+
items: [
350+
{
351+
label: 'Astro Docs',
352+
link: 'https://docs.astro.build/',
353+
attrs: {
354+
target: '_blank',
355+
style: 'font-style: italic',
356+
},
357+
},
358+
],
359+
},
360+
]}
361+
/>
362+
319363
## Internationalization
320364

321365
Use the `translations` property on link and group entries to translate the link or group label for each supported language.

docs/src/content/docs/reference/configuration.md

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ type SidebarItem = {
187187
| {
188188
link: string;
189189
badge?: string | BadgeConfig;
190+
attrs?: Record<string, string | number | boolean | undefined>;
190191
}
191192
| { items: SidebarItem[]; collapsed?: boolean }
192193
| {

docs/src/content/docs/reference/frontmatter.md

+29-1
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,22 @@ pagefind: false
224224

225225
### `sidebar`
226226

227-
**type:** `{ label?: string; order?: number; hidden?: boolean; badge?: string | BadgeConfig }`
227+
**type:** [`SidebarConfig`](#sidebarconfig)
228228

229229
Control how this page is displayed in the [sidebar](/reference/configuration/#sidebar), when using an autogenerated link group.
230230

231+
#### `SidebarConfig`
232+
233+
```ts
234+
interface SidebarConfig {
235+
label?: string;
236+
order?: number;
237+
hidden?: boolean;
238+
badge?: string | BadgeConfig;
239+
attrs?: Record<string, string | number | boolean | undefined>;
240+
}
241+
```
242+
231243
#### `label`
232244

233245
**type:** `string`
@@ -299,3 +311,19 @@ sidebar:
299311
variant: caution
300312
---
301313
```
314+
315+
#### `attrs`
316+
317+
**type:** `Record<string, string | number | boolean | undefined>`
318+
319+
HTML attributes to add to the page link in the sidebar when displayed in an autogenerated group of links.
320+
321+
```md
322+
---
323+
title: Page opening in a new tab
324+
sidebar:
325+
# Opens the page in a new tab
326+
attrs:
327+
target: _blank
328+
---
329+
```

packages/starlight/__tests__/basics/navigation-labels.test.ts

+4
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ describe('getSidebar', () => {
2020
expect(getSidebar('/', undefined)).toMatchInlineSnapshot(`
2121
[
2222
{
23+
"attrs": {},
2324
"badge": undefined,
2425
"href": "/",
2526
"isCurrent": true,
2627
"label": "Home Page",
2728
"type": "link",
2829
},
2930
{
31+
"attrs": {},
3032
"badge": undefined,
3133
"href": "/environmental-impact/",
3234
"isCurrent": false,
@@ -37,13 +39,15 @@ describe('getSidebar', () => {
3739
"collapsed": false,
3840
"entries": [
3941
{
42+
"attrs": {},
4043
"badge": undefined,
4144
"href": "/guides/authoring-content/",
4245
"isCurrent": false,
4346
"label": "Authoring Markdown",
4447
"type": "link",
4548
},
4649
{
50+
"attrs": {},
4751
"badge": undefined,
4852
"href": "/guides/components/",
4953
"isCurrent": false,

packages/starlight/__tests__/basics/navigation-order.test.ts

+4
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ describe('getSidebar', () => {
2020
"collapsed": false,
2121
"entries": [
2222
{
23+
"attrs": {},
2324
"badge": undefined,
2425
"href": "/guides/components/",
2526
"isCurrent": false,
2627
"label": "Components",
2728
"type": "link",
2829
},
2930
{
31+
"attrs": {},
3032
"badge": undefined,
3133
"href": "/guides/authoring-content/",
3234
"isCurrent": false,
@@ -38,13 +40,15 @@ describe('getSidebar', () => {
3840
"type": "group",
3941
},
4042
{
43+
"attrs": {},
4144
"badge": undefined,
4245
"href": "/environmental-impact/",
4346
"isCurrent": false,
4447
"label": "Eco-friendly docs",
4548
"type": "link",
4649
},
4750
{
51+
"attrs": {},
4852
"badge": undefined,
4953
"href": "/",
5054
"isCurrent": true,

packages/starlight/__tests__/basics/navigation.test.ts

+11
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ describe('getSidebar', () => {
1818
expect(getSidebar('/', undefined)).toMatchInlineSnapshot(`
1919
[
2020
{
21+
"attrs": {},
2122
"badge": undefined,
2223
"href": "/",
2324
"isCurrent": true,
2425
"label": "Home Page",
2526
"type": "link",
2627
},
2728
{
29+
"attrs": {},
2830
"badge": undefined,
2931
"href": "/environmental-impact/",
3032
"isCurrent": false,
@@ -35,13 +37,15 @@ describe('getSidebar', () => {
3537
"collapsed": false,
3638
"entries": [
3739
{
40+
"attrs": {},
3841
"badge": undefined,
3942
"href": "/guides/authoring-content/",
4043
"isCurrent": false,
4144
"label": "Authoring Markdown",
4245
"type": "link",
4346
},
4447
{
48+
"attrs": {},
4549
"badge": undefined,
4650
"href": "/guides/components/",
4751
"isCurrent": false,
@@ -103,27 +107,31 @@ describe('flattenSidebar', () => {
103107
expect(flattened).toMatchInlineSnapshot(`
104108
[
105109
{
110+
"attrs": {},
106111
"badge": undefined,
107112
"href": "/",
108113
"isCurrent": true,
109114
"label": "Home Page",
110115
"type": "link",
111116
},
112117
{
118+
"attrs": {},
113119
"badge": undefined,
114120
"href": "/environmental-impact/",
115121
"isCurrent": false,
116122
"label": "Eco-friendly docs",
117123
"type": "link",
118124
},
119125
{
126+
"attrs": {},
120127
"badge": undefined,
121128
"href": "/guides/authoring-content/",
122129
"isCurrent": false,
123130
"label": "Authoring Markdown",
124131
"type": "link",
125132
},
126133
{
134+
"attrs": {},
127135
"badge": undefined,
128136
"href": "/guides/components/",
129137
"isCurrent": false,
@@ -142,13 +150,15 @@ describe('getPrevNextLinks', () => {
142150
expect(links).toMatchInlineSnapshot(`
143151
{
144152
"next": {
153+
"attrs": {},
145154
"badge": undefined,
146155
"href": "/guides/authoring-content/",
147156
"isCurrent": false,
148157
"label": "Authoring Markdown",
149158
"type": "link",
150159
},
151160
"prev": {
161+
"attrs": {},
152162
"badge": undefined,
153163
"href": "/",
154164
"isCurrent": false,
@@ -235,6 +245,7 @@ describe('getPrevNextLinks', () => {
235245
href: '/x/',
236246
label: 'X',
237247
isCurrent: false,
248+
attrs: {},
238249
});
239250
});
240251

packages/starlight/__tests__/i18n/navigation-order.test.ts

+10
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ describe('getSidebar', () => {
3030
expect(getSidebar('/en/', 'en')).toMatchInlineSnapshot(`
3131
[
3232
{
33+
"attrs": {},
3334
"badge": undefined,
3435
"href": "/en/",
3536
"isCurrent": true,
3637
"label": "Home page",
3738
"type": "link",
3839
},
3940
{
41+
"attrs": {},
4042
"badge": undefined,
4143
"href": "/en/404/",
4244
"isCurrent": false,
@@ -47,6 +49,7 @@ describe('getSidebar', () => {
4749
"collapsed": false,
4850
"entries": [
4951
{
52+
"attrs": {},
5053
"badge": undefined,
5154
"href": "/en/guides/authoring-content/",
5255
"isCurrent": false,
@@ -65,13 +68,15 @@ describe('getSidebar', () => {
6568
expect(getSidebar('/fr/', 'fr')).toMatchInlineSnapshot(`
6669
[
6770
{
71+
"attrs": {},
6872
"badge": undefined,
6973
"href": "/fr/",
7074
"isCurrent": true,
7175
"label": "Accueil",
7276
"type": "link",
7377
},
7478
{
79+
"attrs": {},
7580
"badge": undefined,
7681
"href": "/fr/404/",
7782
"isCurrent": false,
@@ -82,6 +87,7 @@ describe('getSidebar', () => {
8287
"collapsed": false,
8388
"entries": [
8489
{
90+
"attrs": {},
8591
"badge": undefined,
8692
"href": "/fr/guides/authoring-content/",
8793
"isCurrent": false,
@@ -96,13 +102,15 @@ describe('getSidebar', () => {
96102
"collapsed": false,
97103
"entries": [
98104
{
105+
"attrs": {},
99106
"badge": undefined,
100107
"href": "/fr/référence/bénéfice/",
101108
"isCurrent": false,
102109
"label": "Bénéfice",
103110
"type": "link",
104111
},
105112
{
113+
"attrs": {},
106114
"badge": undefined,
107115
"href": "/fr/référence/bricolage/",
108116
"isCurrent": false,
@@ -117,13 +125,15 @@ describe('getSidebar', () => {
117125
"collapsed": false,
118126
"entries": [
119127
{
128+
"attrs": {},
120129
"badge": undefined,
121130
"href": "/fr/route/décoder/",
122131
"isCurrent": false,
123132
"label": "Décoder",
124133
"type": "link",
125134
},
126135
{
136+
"attrs": {},
127137
"badge": undefined,
128138
"href": "/fr/route/distribuer/",
129139
"isCurrent": false,

0 commit comments

Comments
 (0)