Skip to content

Commit

Permalink
Add <Badge> component (#1530)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
6 people committed Jun 5, 2024
1 parent 1574732 commit dd64836
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 104 deletions.
6 changes: 6 additions & 0 deletions .changeset/wicked-melons-study.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@astrojs/starlight': minor
---

Adds a new `<Badge>` component

30 changes: 30 additions & 0 deletions docs/src/content/docs/guides/components.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
8 changes: 5 additions & 3 deletions docs/src/content/docs/guides/sidebar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
3 changes: 2 additions & 1 deletion docs/src/content/docs/reference/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
```

Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/reference/frontmatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
---
Expand Down
1 change: 1 addition & 0 deletions packages/starlight/components.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
87 changes: 0 additions & 87 deletions packages/starlight/components/Badge.astro

This file was deleted.

23 changes: 11 additions & 12 deletions packages/starlight/components/SidebarSublist.astro
Original file line number Diff line number Diff line change
@@ -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[];
Expand All @@ -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>
) : (
Expand All @@ -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" />
Expand Down
9 changes: 9 additions & 0 deletions packages/starlight/schemas/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()])
Expand Down
141 changes: 141 additions & 0 deletions packages/starlight/user-components/Badge.astro
Original file line number Diff line number Diff line change
@@ -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>

0 comments on commit dd64836

Please sign in to comment.