diff options
author | Kevin | 2024-06-05 13:11:15 -0400 |
---|---|---|
committer | GitHub | 2024-06-05 19:11:15 +0200 |
commit | dd64836af45f33df4a99ab864eabb91fc9b8e204 (patch) | |
tree | 73e3e6ee7204577fb57773a7891d77a1bde4486c | |
parent | 15747325112c9fe43b8dfa4e986b95cf8e66af49 (diff) | |
download | IT.starlight-dd64836af45f33df4a99ab864eabb91fc9b8e204.tar.gz IT.starlight-dd64836af45f33df4a99ab864eabb91fc9b8e204.tar.bz2 IT.starlight-dd64836af45f33df4a99ab864eabb91fc9b8e204.zip |
Add `<Badge>` component (#1530)
Co-authored-by: HiDeoo <494699+HiDeoo@users.noreply.github.com>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
Co-authored-by: trueberryless <99918022+trueberryless@users.noreply.github.com>
Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com>
-rw-r--r-- | .changeset/wicked-melons-study.md | 6 | ||||
-rw-r--r-- | docs/src/content/docs/guides/components.mdx | 30 | ||||
-rw-r--r-- | docs/src/content/docs/guides/sidebar.mdx | 8 | ||||
-rw-r--r-- | docs/src/content/docs/reference/configuration.mdx | 3 | ||||
-rw-r--r-- | docs/src/content/docs/reference/frontmatter.md | 2 | ||||
-rw-r--r-- | packages/starlight/components.ts | 1 | ||||
-rw-r--r-- | packages/starlight/components/Badge.astro | 87 | ||||
-rw-r--r-- | packages/starlight/components/SidebarSublist.astro | 23 | ||||
-rw-r--r-- | packages/starlight/schemas/badge.ts | 9 | ||||
-rw-r--r-- | packages/starlight/user-components/Badge.astro | 141 |
10 files changed, 206 insertions, 104 deletions
diff --git a/.changeset/wicked-melons-study.md b/.changeset/wicked-melons-study.md new file mode 100644 index 00000000..9de08e60 --- /dev/null +++ b/.changeset/wicked-melons-study.md @@ -0,0 +1,6 @@ +--- +'@astrojs/starlight': minor +--- + +Adds a new `<Badge>` component + diff --git a/docs/src/content/docs/guides/components.mdx b/docs/src/content/docs/guides/components.mdx index 30178aec..95a5e30f 100644 --- a/docs/src/content/docs/guides/components.mdx +++ b/docs/src/content/docs/guides/components.mdx @@ -412,6 +412,36 @@ import { Steps } from '@astrojs/starlight/components'; </Steps> +### Badges + +import { Badge } from '@astrojs/starlight/components'; + +Use the `<Badge>` component to display small pieces of information, such as status or labels. + +Pass the content you want to display to the `text` attribute of the `<Badge>` component. + +By default, the badge will use the theme accent color of your site. To use a built-in badge color, set the `variant` attribute to one of the following values: `note` (blue), `tip` (purple), `danger` (red), `caution` (orange), or `success` (green). + +The `size` attribute (default: `small`) controls the size of the badge text. `medium` and `large` are also available options for displaying a larger badge. + +For further customization, use other `<span>` attributes such as `class` or `style` with custom CSS. + +```mdx title="src/content/docs/example.mdx" +import { Badge } from '@astrojs/starlight/components'; + +<Badge text="New" variant="tip" size="small" /> +<Badge text="Deprecated" variant="caution" size="medium" /> +<Badge text="Starlight" variant="note" size="large" /> +<Badge text="Custom" variant="success" style={{ fontStyle: 'italic' }} /> +``` + +The code above generates the following on the page: + +<Badge text="New" variant="tip" size="small" /> +<Badge text="Deprecated" variant="caution" size="medium" /> +<Badge text="Starlight" variant="note" size="large" /> +<Badge text="Custom" variant="success" style={{ fontStyle: 'italic' }} /> + ### Icon import { Icon } from '@astrojs/starlight/components'; diff --git a/docs/src/content/docs/guides/sidebar.mdx b/docs/src/content/docs/guides/sidebar.mdx index bf9d3605..0632b537 100644 --- a/docs/src/content/docs/guides/sidebar.mdx +++ b/docs/src/content/docs/guides/sidebar.mdx @@ -294,12 +294,14 @@ The configuration above generates the following sidebar: ]} /> -### Badge variants +### Badge variants and custom styling -Customize the badge styling using an object with `text` and `variant` properties. +Customize the badge styling using an object with `text`, `variant`, and `class` properties. The `text` represents the content to display (e.g. "New"). -Override the `default` styling, which uses the accent color of your site, by setting the `variant` property to one of the following values: `note`, `tip`, `danger`, `caution` or `success`. +By default, the badge will use the accent color of your site. To use a built-in badge style, set the `variant` property to one of the following values: `note`, `tip`, `danger`, `caution` or `success`. + +Optionally, you can create a custom badge style by setting the `class` property to a CSS class name. ```js {10} starlight({ diff --git a/docs/src/content/docs/reference/configuration.mdx b/docs/src/content/docs/reference/configuration.mdx index a940a844..59816e1a 100644 --- a/docs/src/content/docs/reference/configuration.mdx +++ b/docs/src/content/docs/reference/configuration.mdx @@ -214,7 +214,8 @@ type SidebarItem = { ```ts interface BadgeConfig { text: string; - variant: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; + variant?: 'note' | 'tip' | 'caution' | 'danger' | 'success' | 'default'; + class?: string; } ``` diff --git a/docs/src/content/docs/reference/frontmatter.md b/docs/src/content/docs/reference/frontmatter.md index 32ae46ca..41fc4a5b 100644 --- a/docs/src/content/docs/reference/frontmatter.md +++ b/docs/src/content/docs/reference/frontmatter.md @@ -355,7 +355,7 @@ sidebar: Add a badge to the page in the sidebar when displayed in an autogenerated group of links. When using a string, the badge will be displayed with a default accent color. -Optionally, pass a [`BadgeConfig` object](/reference/configuration/#badgeconfig) with `text` and `variant` fields to customize the badge. +Optionally, pass a [`BadgeConfig` object](/reference/configuration/#badgeconfig) with `text`, `variant`, and `class` fields to customize the badge. ```md --- diff --git a/packages/starlight/components.ts b/packages/starlight/components.ts index e564b62b..2935e9ff 100644 --- a/packages/starlight/components.ts +++ b/packages/starlight/components.ts @@ -1,4 +1,5 @@ export { default as Aside } from './user-components/Aside.astro'; +export { default as Badge } from './user-components/Badge.astro'; export { default as Card } from './user-components/Card.astro'; export { default as CardGrid } from './user-components/CardGrid.astro'; export { default as Icon } from './user-components/Icon.astro'; diff --git a/packages/starlight/components/Badge.astro b/packages/starlight/components/Badge.astro deleted file mode 100644 index 7e8c0da2..00000000 --- a/packages/starlight/components/Badge.astro +++ /dev/null @@ -1,87 +0,0 @@ ---- -import type { Badge } from '../schemas/badge'; - -interface Props { - variant?: Badge['variant'] | 'outline'; - text?: string; -} -const { variant = 'default', text } = Astro.props; ---- - -<span class:list={['sl-badge', variant]} set:html={text} /> - -<style> - .sl-badge { - display: inline-block; - border: 1px solid var(--sl-color-border-badge); - border-radius: 0.25rem; - font-family: var(--sl-font-system-mono); - font-size: var(--sl-text-xs); - font-weight: 400; - padding: 0.125rem 0.375rem; - line-height: 1; - color: #fff; - background-color: var(--sl-color-bg-badge); - overflow-wrap: anywhere; - } - - .outline { - --sl-color-bg-badge: transparent; - --sl-color-border-badge: currentColor; - color: inherit; - } - - .default { - --sl-color-bg-badge: var(--sl-color-accent-low); - --sl-color-border-badge: var(--sl-color-accent); - } - - .note { - --sl-color-bg-badge: var(--sl-color-blue-low); - --sl-color-border-badge: var(--sl-color-blue); - } - - .danger { - --sl-color-bg-badge: var(--sl-color-red-low); - --sl-color-border-badge: var(--sl-color-red); - } - - .success { - --sl-color-bg-badge: var(--sl-color-green-low); - --sl-color-border-badge: var(--sl-color-green); - } - - .caution { - --sl-color-bg-badge: var(--sl-color-orange-low); - --sl-color-border-badge: var(--sl-color-orange); - } - - .tip { - --sl-color-bg-badge: var(--sl-color-purple-low); - --sl-color-border-badge: var(--sl-color-purple); - } - - :global([data-theme='light']) .default { - --sl-color-bg-badge: var(--sl-color-accent-high); - } - - :global([data-theme='light']) .note { - --sl-color-bg-badge: var(--sl-color-blue-high); - } - - :global([data-theme='light']) .danger { - --sl-color-bg-badge: var(--sl-color-red-high); - } - - :global([data-theme='light']) .success { - --sl-color-bg-badge: var(--sl-color-green-high); - } - - :global([data-theme='light']) .caution { - --sl-color-bg-badge: var(--sl-color-orange-high); - } - - :global([data-theme='light']) .tip { - --sl-color-bg-badge: var(--sl-color-purple-high); - } -</style> diff --git a/packages/starlight/components/SidebarSublist.astro b/packages/starlight/components/SidebarSublist.astro index 399d191f..23252501 100644 --- a/packages/starlight/components/SidebarSublist.astro +++ b/packages/starlight/components/SidebarSublist.astro @@ -1,7 +1,7 @@ --- import { flattenSidebar, type SidebarEntry } from '../utils/navigation'; import Icon from '../user-components/Icon.astro'; -import Badge from './Badge.astro'; +import Badge from '../user-components/Badge.astro'; interface Props { sublist: SidebarEntry[]; @@ -24,13 +24,11 @@ const { sublist, nested } = Astro.props; > <span>{entry.label}</span> {entry.badge && ( - <> - {' '} - <Badge - text={entry.badge.text} - variant={entry.isCurrent ? 'outline' : entry.badge.variant} - /> - </> + <Badge + variant={entry.badge.variant} + class={entry.badge.class} + text={entry.badge.text} + /> )} </a> ) : ( @@ -41,10 +39,11 @@ const { sublist, nested } = Astro.props; <div class="group-label"> <span class="large">{entry.label}</span> {entry.badge && ( - <> - {' '} - <Badge text={entry.badge.text} variant={entry.badge.variant} /> - </> + <Badge + variant={entry.badge.variant} + class={entry.badge.class} + text={entry.badge.text} + /> )} </div> <Icon name="right-caret" class="caret" size="1.25rem" /> diff --git a/packages/starlight/schemas/badge.ts b/packages/starlight/schemas/badge.ts index dc6fdb67..a2cac1b1 100644 --- a/packages/starlight/schemas/badge.ts +++ b/packages/starlight/schemas/badge.ts @@ -4,8 +4,17 @@ const badgeSchema = () => z.object({ variant: z.enum(['note', 'danger', 'success', 'caution', 'tip', 'default']).default('default'), text: z.string(), + class: z.string().optional(), }); +export const BadgeComponentSchema = badgeSchema() + .extend({ + size: z.enum(['small', 'medium', 'large']).default('small'), + }) + .passthrough(); + +export type BadgeComponentProps = z.input<typeof BadgeComponentSchema>; + export const BadgeConfigSchema = () => z .union([z.string(), badgeSchema()]) diff --git a/packages/starlight/user-components/Badge.astro b/packages/starlight/user-components/Badge.astro new file mode 100644 index 00000000..821cd0a3 --- /dev/null +++ b/packages/starlight/user-components/Badge.astro @@ -0,0 +1,141 @@ +--- +import { BadgeComponentSchema, type BadgeComponentProps } from '../schemas/badge'; +import { parseWithFriendlyErrors } from '../utils/error-map'; +import type { HTMLAttributes } from 'astro/types'; + +type Props = BadgeComponentProps & HTMLAttributes<'span'>; + +const { + text, + variant, + size, + class: customClass, + ...attrs +} = parseWithFriendlyErrors( + BadgeComponentSchema, + Astro.props, + 'Invalid prop passed to the `<Badge/>` component.' +); +--- + +<span class:list={['sl-badge', variant, size, customClass]} {...attrs}>{text}</span> + +<style> + :global(:root) { + --sl-badge-default-border: var(--sl-color-accent); + --sl-badge-default-bg: var(--sl-color-accent-low); + --sl-badge-default-text: #fff; + + --sl-badge-note-border: var(--sl-color-blue); + --sl-badge-note-bg: var(--sl-color-blue-low); + --sl-badge-note-text: #fff; + + --sl-badge-danger-border: var(--sl-color-red); + --sl-badge-danger-bg: var(--sl-color-red-low); + --sl-badge-danger-text: #fff; + + --sl-badge-success-border: var(--sl-color-green); + --sl-badge-success-bg: var(--sl-color-green-low); + --sl-badge-success-text: #fff; + + --sl-badge-caution-border: var(--sl-color-orange); + --sl-badge-caution-bg: var(--sl-color-orange-low); + --sl-badge-caution-text: #fff; + + --sl-badge-tip-border: var(--sl-color-purple); + --sl-badge-tip-bg: var(--sl-color-purple-low); + --sl-badge-tip-text: #fff; + } + + :global([data-theme='light']:root) { + --sl-badge-default-bg: var(--sl-color-accent-high); + --sl-badge-note-bg: var(--sl-color-blue-high); + --sl-badge-danger-bg: var(--sl-color-red-high); + --sl-badge-success-bg: var(--sl-color-green-high); + --sl-badge-caution-bg: var(--sl-color-orange-high); + --sl-badge-tip-bg: var(--sl-color-purple-high); + } + + .sl-badge { + display: inline-block; + border: 1px solid var(--sl-color-border-badge); + border-radius: 0.25rem; + font-family: var(--sl-font-system-mono); + line-height: normal; + color: var(--sl-color-text-badge); + background-color: var(--sl-color-bg-badge); + overflow-wrap: anywhere; + } + + /* Sidebar overrides */ + :global(.sidebar-content) .sl-badge { + line-height: 1; + font-size: var(--sl-text-xs); + padding: 0.125rem 0.375rem; + } + + /* outline variant */ + :global(.sidebar-content a[aria-current='page']) > .sl-badge { + --sl-color-bg-badge: transparent; + --sl-color-border-badge: currentColor; + color: inherit; + } + + /* Color variants */ + .default { + --sl-color-bg-badge: var(--sl-badge-default-bg); + --sl-color-border-badge: var(--sl-badge-default-border); + --sl-color-text-badge: var(--sl-badge-default-text); + } + + .note { + --sl-color-bg-badge: var(--sl-badge-note-bg); + --sl-color-border-badge: var(--sl-badge-note-border); + --sl-color-text-badge: var(--sl-badge-note-text); + } + + .danger { + --sl-color-bg-badge: var(--sl-badge-danger-bg); + --sl-color-border-badge: var(--sl-badge-danger-border); + --sl-color-text-badge: var(--sl-badge-danger-text); + } + + .success { + --sl-color-bg-badge: var(--sl-badge-success-bg); + --sl-color-border-badge: var(--sl-badge-success-border); + --sl-color-text-badge: var(--sl-badge-success-text); + } + + .tip { + --sl-color-bg-badge: var(--sl-badge-tip-bg); + --sl-color-border-badge: var(--sl-badge-tip-border); + --sl-color-text-badge: var(--sl-badge-tip-text); + } + + .caution { + --sl-color-bg-badge: var(--sl-badge-caution-bg); + --sl-color-border-badge: var(--sl-badge-caution-border); + --sl-color-text-badge: var(--sl-badge-caution-text); + } + + /* Size variants */ + .small { + font-size: var(--sl-text-xs); + padding: 0.125rem 0.25rem; + } + + .medium { + font-size: var(--sl-text-sm); + padding: 0.175rem 0.35rem; + } + + .large { + font-size: var(--sl-text-base); + padding: 0.225rem 0.45rem; + } + + /* Badge in headings */ + :global(.sl-markdown-content :is(h1, h2, h3, h4, h5, h6)) .sl-badge { + vertical-align: middle; + } +</style> |