Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add <Badge> component #1530

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c63a6c3
Move <Badge> to user components
kevinzunigacuellar Feb 18, 2024
41dad00
testing page
kevinzunigacuellar Feb 18, 2024
a1761f5
add changeset
kevinzunigacuellar Feb 18, 2024
80ad0ae
copilot bad!
kevinzunigacuellar Feb 18, 2024
cf8a9a6
new light themes, expose css variables, override themes for md content
kevinzunigacuellar Feb 22, 2024
480b08b
more examples
kevinzunigacuellar Feb 22, 2024
9383dce
add `class` for defining custom badges
kevinzunigacuellar Feb 22, 2024
7e726d7
switch set:html for slot
kevinzunigacuellar Feb 22, 2024
22a517e
add class to badge schema and sidebar
kevinzunigacuellar Feb 22, 2024
d915e4f
add docs!
kevinzunigacuellar Feb 26, 2024
14d84cf
Merge branch 'main' into kevin/badge
kevinzunigacuellar Apr 15, 2024
9a64a0f
Wip: badge
kevinzunigacuellar Apr 16, 2024
7c98bad
Update badge component and related schemas
kevinzunigacuellar Apr 16, 2024
94c6d8e
remove unused exports
kevinzunigacuellar Apr 16, 2024
4e9256d
docs: add class override
kevinzunigacuellar Apr 16, 2024
d2e05f1
Merge branch 'main' into kevin/badge
kevinzunigacuellar Apr 16, 2024
ec2afcc
Remove test file
kevinzunigacuellar Apr 16, 2024
a62ead3
move badge docs before icon section
kevinzunigacuellar Apr 16, 2024
263f0cc
feat: tweak badge appearance in headings
HiDeoo Apr 29, 2024
3926ac4
export and use BadgeComponent type for badge component
kevinzunigacuellar May 1, 2024
b77871d
update docs 💜
kevinzunigacuellar May 1, 2024
474395b
rfc: BadgeComponent to support `attrs`
kevinzunigacuellar May 7, 2024
7acfb8e
chore: Update badge component documentation
kevinzunigacuellar May 7, 2024
d1ce134
remove attrs from schema
kevinzunigacuellar May 7, 2024
9bce965
update docs
kevinzunigacuellar May 7, 2024
de49e5c
remove comma
kevinzunigacuellar May 7, 2024
4cbf409
Apply suggestions from code review
kevinzunigacuellar May 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/wicked-melons-study.md
@@ -0,0 +1,6 @@
---
'@astrojs/starlight': minor
---

Adds the `<Badge>` component

51 changes: 50 additions & 1 deletion docs/src/content/docs/guides/components.mdx
Expand Up @@ -368,6 +368,55 @@ import { Steps } from '@astrojs/starlight/components';

</Steps>

### Badge

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. Optionally, you can specify a `variant` attribute with values like `tip`, `note`, `caution`, `danger`, `success` or `default` to adjust the badge's appearance. If no variant is specified, the default variant is `default` which uses the theme accent color.

You can also specify a `size` attribute with values like `small`, `medium`, or `large` to adjust the badge's size. If no size is specified, the default size is `small`.

```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" />

```

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" />

#### Custom badges

To create a custom badge, create a new CSS class and set the `--sl-color-bg-badge`, `--sl-color-border-badge`, and `--sl-color-text-badge` CSS variables to the desired colors.

```css
.new-badge-variant {
--sl-color-bg-badge: XXX;
--sl-color-border-badge: XXX;
--sl-color-text-badge: XXX;
}

[data-theme='light'] .new-badge-variant {
--sl-color-bg-badge: YYY;
--sl-color-border-badge: YYY;
--sl-color-text-badge: YYY;
}
```

Then, apply the new class to the `<Badge>` component.

```mdx title="src/content/docs/example.mdx"
<Badge text="Custom" class="new-badge-variant" />
```

### Icon

import { Icon } from '@astrojs/starlight/components';
Expand All @@ -393,4 +442,4 @@ The code above generates the following on the page:

A list of all available icons is shown below with their associated names. Click an icon to copy the component code for it.

<IconsList />
<IconsList />
1 change: 1 addition & 0 deletions 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';
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
@@ -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
5 changes: 5 additions & 0 deletions packages/starlight/schemas/badge.ts
Expand Up @@ -4,8 +4,13 @@ const badgeSchema = () =>
z.object({
variant: z.enum(['note', 'danger', 'success', 'caution', 'tip', 'default']).default('default'),
text: z.string(),
class: z.string().optional(),
kevinzunigacuellar marked this conversation as resolved.
Show resolved Hide resolved
});

export const BadgeComponentSchema = badgeSchema().extend({
size: z.enum(['small', 'medium', 'large']).default('small'),
});

export const BadgeConfigSchema = () =>
z
.union([z.string(), badgeSchema()])
Expand Down
139 changes: 139 additions & 0 deletions packages/starlight/user-components/Badge.astro
@@ -0,0 +1,139 @@
---
import { type Badge, BadgeComponentSchema } from '../schemas/badge';
import { parseWithFriendlyErrors } from '../utils/error-map';

type Props = Badge;
Copy link
Member

@HiDeoo HiDeoo Apr 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, this is equivalent to z.output<ReturnType<typeof badgeSchema>> but I guess we would want the props to be z.input<typeof BadgeComponentSchema> instead so we may need to create a type for this new component schema.


const {
text,
variant,
class: className,
size,
} = parseWithFriendlyErrors(
BadgeComponentSchema,
Astro.props,
'Invalid prop passed to the `<Badge/>` component.'
);
---

<span class:list={['sl-badge', variant, size, className]} set:html={text} />

<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;
}
Copy link
Member

@martrapp martrapp Apr 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After having looked into this PR as the perfect solution for #1764 and martrapp/astro-vtbot#77, I would like to suggest to move the sidebar specific styling to

. There it would be a neighbor of the other aria-current='page'-styling, and you would get rid of the references to sidebar-content here.


/* 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>