Skip to content

Commit

Permalink
Expose StarlightIcon type (#2805)
Browse files Browse the repository at this point in the history
Co-authored-by: Chris Swithinbank <357379+delucis@users.noreply.github.com>
  • Loading branch information
HiDeoo and delucis authored Jan 17, 2025
1 parent 893be3b commit ed6f9fd
Show file tree
Hide file tree
Showing 16 changed files with 46 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changeset/unlucky-items-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/starlight': minor
---

Exposes the [`StarlightIcon`](https://starlight.astro.build/reference/icons/#starlighticon-type) TypeScript type referencing the names of Starlight’s built-in icons.
4 changes: 2 additions & 2 deletions docs/src/components/icons-list.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
import { Icon } from '@astrojs/starlight/components';
import { Icons } from '../../../packages/starlight/components/Icons';
import { Icons, type StarlightIcon } from '../../../packages/starlight/components/Icons';
interface Props {
labels?: {
Expand All @@ -10,7 +10,7 @@ interface Props {
const { copied = 'Copied!' } = Astro.props.labels ?? {};
const icons = Object.keys(Icons) as (keyof typeof Icons)[];
const icons = Object.keys(Icons) as StarlightIcon[];
---

<div class="icons-grid" data-label-copied={copied}>
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/components/icons.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ The `<Icon>` component accepts the following props:
### `name`

**required**
**type:** `string`
**type:** [`StarlightIcon`](/reference/icons/#starlighticon-type)

The name of the icon to display set to [one of Starlight’s built-in icons](/reference/icons/#all-icons).

Expand Down
6 changes: 3 additions & 3 deletions docs/src/content/docs/components/using-components.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ If these styles conflict with your component’s appearance, set the `not-conten
Use the [`ComponentProps`](https://docs.astro.build/en/guides/typescript/#componentprops-type) type from `astro/types` to reference the `Props` accepted by a component even if they are not exported by the component itself.
This can be helpful when wrapping or extending an existing component.

The following example uses `ComponentProps` to get the type of the props accepted by Starlight’s built-in `Icon` component:
The following example uses `ComponentProps` to get the type of the props accepted by Starlight’s built-in `Badge` component:

```astro
---
// src/components/Example.astro
import type { ComponentProps } from 'astro/types';
import { Icon } from '@astrojs/starlight/components';
import { Badge } from '@astrojs/starlight/components';
type IconProps = ComponentProps<typeof Icon>;
type BadgeProps = ComponentProps<typeof Badge>;
---
```
13 changes: 13 additions & 0 deletions docs/src/content/docs/reference/icons.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ Starlight provides a set of built-in icons that you can display in your content
Icons can be displayed using the [`<Icon>`](/components/icons/) component.
They are also often used in other components, such as [cards](/components/cards/) or settings like [hero actions](/reference/frontmatter/#hero).

## `StarlightIcon` type

Use the `StarlightIcon` TypeScript type to reference the names of [Starlight’s built-in icons](#all-icons).

```ts {2} /icon: (StarlightIcon)/
// src/icon.ts
import type { StarlightIcon } from '@astrojs/starlight/types';

function getIconLabel(icon: StarlightIcon) {
//
}
```

## All icons

A list of all available icons is shown below with their associated names. Click an icon to copy its name to your clipboard.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, test } from 'vitest';
import { processFileTree } from '../../user-components/rehype-file-tree';
import { Icons } from '../../components/Icons';
import { Icons, type StarlightIcon } from '../../components/Icons';

describe('validation', () => {
test('throws an error with no content', () => {
Expand Down Expand Up @@ -176,6 +176,6 @@ function extractFileTree(html: string, stripIcons = true) {
return tree;
}

function expectHtmlToIncludeIcon(html: string, icon: (typeof Icons)[keyof typeof Icons]) {
function expectHtmlToIncludeIcon(html: string, icon: (typeof Icons)[StarlightIcon]) {
return expect(extractFileTree(html, false)).toContain(icon.replace('/>', '>'));
}
4 changes: 2 additions & 2 deletions packages/starlight/components/ContentNotice.astro
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
import { Icons } from '../components/Icons';
import type { StarlightIcon } from '../components/Icons';
import Icon from '../user-components/Icon.astro';
interface Props {
icon: keyof typeof Icons;
icon: StarlightIcon;
label: string;
}
Expand Down
2 changes: 2 additions & 0 deletions packages/starlight/components/Icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,5 @@ export const Icons = {
...BuiltInIcons,
...FileIcons,
};

export type StarlightIcon = keyof typeof Icons;
5 changes: 2 additions & 3 deletions packages/starlight/schemas/hero.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { z } from 'astro/zod';
import type { SchemaContext } from 'astro:content';
import { Icons } from '../components/Icons';
import { Icons, type StarlightIcon } from '../components/Icons';

type IconName = keyof typeof Icons;
const iconNames = Object.keys(Icons) as [IconName, ...IconName[]];
const iconNames = Object.keys(Icons) as [StarlightIcon, ...StarlightIcon[]];

export const HeroSchema = ({ image }: SchemaContext) =>
z.object({
Expand Down
1 change: 1 addition & 0 deletions packages/starlight/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export type {
StarlightPlugin,
StarlightUserConfigWithPlugins as StarlightUserConfig,
} from './utils/plugins';
export type { StarlightIcon } from './components/Icons';
4 changes: 2 additions & 2 deletions packages/starlight/user-components/Card.astro
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
import Icon from './Icon.astro';
import type { Icons } from '../components/Icons';
import type { StarlightIcon } from '../components/Icons';
interface Props {
icon?: keyof typeof Icons;
icon?: StarlightIcon;
title: string;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/starlight/user-components/Icon.astro
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
import { Icons } from '../components/Icons';
import { Icons, type StarlightIcon } from '../components/Icons';
interface Props {
name: keyof typeof Icons;
name: StarlightIcon;
label?: string;
color?: string;
size?: string;
Expand Down
4 changes: 2 additions & 2 deletions packages/starlight/user-components/LinkButton.astro
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
import type { HTMLAttributes } from 'astro/types';
import { Icons } from '../components/Icons';
import type { StarlightIcon } from '../components/Icons';
import Icon from './Icon.astro';
interface Props extends Omit<HTMLAttributes<'a'>, 'href'> {
href: string | URL;
icon?: keyof typeof Icons | undefined;
icon?: StarlightIcon | undefined;
iconPlacement?: 'start' | 'end' | undefined;
variant?: 'primary' | 'secondary' | 'minimal';
}
Expand Down
4 changes: 2 additions & 2 deletions packages/starlight/user-components/TabItem.astro
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
import { TabItemTagname } from './rehype-tabs';
import type { Icons } from '../components/Icons';
import type { StarlightIcon } from '../components/Icons';
interface Props {
icon?: keyof typeof Icons;
icon?: StarlightIcon;
label: string;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/starlight/user-components/rehype-file-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { fromHtml } from 'hast-util-from-html';
import { toString } from 'hast-util-to-string';
import { rehype } from 'rehype';
import { CONTINUE, SKIP, visit } from 'unist-util-visit';
import { Icons } from '../components/Icons';
import { Icons, type StarlightIcon } from '../components/Icons';
import { definitions } from './file-tree-icons';

declare module 'vfile' {
Expand Down Expand Up @@ -160,7 +160,7 @@ function getFileIcon(fileName: string) {
const name = getFileIconName(fileName);
if (!name) return defaultFileIcon;
if (name in Icons) {
const path = Icons[name as keyof typeof Icons];
const path = Icons[name as StarlightIcon];
return makeSVGIcon(path);
}
return defaultFileIcon;
Expand Down
6 changes: 3 additions & 3 deletions packages/starlight/user-components/rehype-tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import type { Element } from 'hast';
import { select } from 'hast-util-select';
import { rehype } from 'rehype';
import { CONTINUE, SKIP, visit } from 'unist-util-visit';
import { Icons } from '../components/Icons';
import type { StarlightIcon } from '../components/Icons';

interface Panel {
panelId: string;
tabId: string;
label: string;
icon?: keyof typeof Icons;
icon?: StarlightIcon;
}

declare module 'vfile' {
Expand Down Expand Up @@ -67,7 +67,7 @@ const tabsProcessor = rehype()
...ids,
label: String(dataLabel),
};
if (dataIcon) panel.icon = String(dataIcon) as keyof typeof Icons;
if (dataIcon) panel.icon = String(dataIcon) as StarlightIcon;
file.data.panels?.push(panel);

// Remove `<TabItem>` props
Expand Down

0 comments on commit ed6f9fd

Please sign in to comment.