@grove-dev/starlight 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Turtuvshin Byambaa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,83 +1,49 @@
1
- # @grove-dev/starlight
1
+ # `@grove-dev/starlight`
2
2
 
3
- Grove Starlight is a theme plugin for Astro Starlight that powers the
4
- Grove documentation site (`apps/docs/`). It ships component overrides,
5
- a layered CSS theme, and an Expressive Code integration so that
6
- Starlight renders pages in the same visual language as Grove-powered
7
- directories.
3
+ The Starlight theme and documentation integration used by Grove.
4
+ It powers the Grove documentation site (`apps/docs/`) and is
5
+ available as a Starlight plugin for any documentation project that
6
+ wants the same visual language as Grove-powered sites.
8
7
 
9
- ## Features
8
+ The plugin registers component overrides for the header, sidebar,
9
+ page frame, hero, footer, search, table of contents, pagination,
10
+ and Markdown content. It appends a layered CSS theme with light and
11
+ dark mode values and configures Expressive Code so code blocks
12
+ match the rest of the site.
10
13
 
11
- - Starlight plugin API integration.
12
- - Custom overrides for header, sidebar, page frame, hero, footer, search, table of contents, pagination, and Markdown content.
13
- - Token-based, layered CSS theme with light and dark mode values.
14
- - Styled built-in Starlight components including hero splashes, cards, link cards, asides, badges, tabs, steps, file trees, and link buttons.
15
-
16
- ## Installation
14
+ ## Install
17
15
 
18
16
  ```bash
19
- npm install @grove-dev/starlight
17
+ pnpm add @grove-dev/starlight
20
18
  ```
21
19
 
22
- With Bun:
23
-
24
- ```bash
25
- bun add @grove-dev/starlight
26
- ```
20
+ Requires Node.js `>=22.12.0`, Astro `>=5.0.0`, and
21
+ `@astrojs/starlight >=0.38.3`.
27
22
 
28
- ## Usage
23
+ ## Use the plugin
29
24
 
30
25
  Add the plugin inside the Starlight integration:
31
26
 
32
27
  ```js
33
28
  // astro.config.mjs
34
- import { defineConfig } from 'astro/config';
35
- import starlight from '@astrojs/starlight';
36
- import grove from '@grove-dev/starlight';
29
+ import { defineConfig } from "astro/config";
30
+ import starlight from "@astrojs/starlight";
31
+ import grove from "@grove-dev/starlight";
37
32
 
38
33
  export default defineConfig({
39
34
  integrations: [
40
35
  starlight({
41
- title: 'My Docs',
36
+ title: "My Docs",
42
37
  plugins: [grove()],
43
38
  }),
44
39
  ],
45
40
  });
46
41
  ```
47
42
 
48
- The plugin registers Grove's component overrides, appends the theme
49
- CSS files, and configures Expressive Code.
50
-
51
- ## Attribution
52
-
53
- This theme recreates the design of the documentation site for
54
- [shadcn/ui](https://ui.shadcn.com/).
43
+ The plugin registers Grove's component overrides, appends the
44
+ theme CSS files, and configures Expressive Code.
55
45
 
56
- It uses [adrian-ub/starlight-theme-black](https://github.com/adrian-ub/starlight-theme-black)
57
- as a base, which brought an earlier shadcn/ui-inspired design to Astro
58
- Starlight.
59
-
60
- ## Docs Schema
61
-
62
- To use Grove's splash-page frontmatter fields with type checking,
63
- extend the Starlight docs schema:
64
-
65
- ```ts
66
- // src/content.config.ts
67
- import { defineCollection } from 'astro:content';
68
- import { docsLoader } from '@astrojs/starlight/loaders';
69
- import { docsSchema } from '@astrojs/starlight/schema';
70
- import { ExtendDocsSchema } from '@grove-dev/starlight/schema';
71
-
72
- export const collections = {
73
- docs: defineCollection({
74
- loader: docsLoader(),
75
- schema: docsSchema({ extend: ExtendDocsSchema }),
76
- }),
77
- };
78
- ```
79
-
80
- ## Plugin Options
46
+ ## Plugin options
81
47
 
82
48
  ```ts
83
49
  type GroveStarlightUserConfig = {
@@ -93,20 +59,38 @@ type Link = {
93
59
  };
94
60
  ```
95
61
 
96
- Example:
97
-
98
62
  ```js
99
63
  grove({
100
64
  navLinks: [
101
- { label: 'Docs', link: '/introduction/' },
102
- { label: 'GitHub', link: 'https://github.com/tortuvshin/grove' },
65
+ { label: "Docs", link: "/introduction/" },
66
+ { label: "GitHub", link: "https://github.com/tortuvshin/grove" },
103
67
  ],
104
68
  footerText:
105
- 'Built with [Grove Starlight](https://github.com/tortuvshin/grove/tree/main/packages/starlight).',
69
+ "Built with [Grove Starlight](https://github.com/tortuvshin/grove/tree/main/packages/starlight).",
106
70
  });
107
71
  ```
108
72
 
109
- ## Splash Pages
73
+ ## Extend the docs schema
74
+
75
+ To use Grove's splash-page frontmatter fields with type checking,
76
+ extend the Starlight docs schema:
77
+
78
+ ```ts
79
+ // src/content.config.ts
80
+ import { defineCollection } from "astro:content";
81
+ import { docsLoader } from "@astrojs/starlight/loaders";
82
+ import { docsSchema } from "@astrojs/starlight/schema";
83
+ import { ExtendDocsSchema } from "@grove-dev/starlight/schema";
84
+
85
+ export const collections = {
86
+ docs: defineCollection({
87
+ loader: docsLoader(),
88
+ schema: docsSchema({ extend: ExtendDocsSchema }),
89
+ }),
90
+ };
91
+ ```
92
+
93
+ ## Splash pages
110
94
 
111
95
  Use Starlight's `template: splash` and set `hero.layout`:
112
96
 
@@ -141,7 +125,7 @@ Import user-facing components from `@grove-dev/starlight/components`:
141
125
 
142
126
  ```astro
143
127
  ---
144
- import { ContainerSection, Dropdown, LinkButton } from '@grove-dev/starlight/components';
128
+ import { ContainerSection, Dropdown, LinkButton } from "@grove-dev/starlight/components";
145
129
  ---
146
130
 
147
131
  <ContainerSection width="lg">
@@ -167,30 +151,29 @@ import { ContainerSection, Dropdown, LinkButton } from '@grove-dev/starlight/com
167
151
 
168
152
  ### `LinkButton`
169
153
 
170
- Props:
171
-
172
- - `href`: anchor destination.
173
- - `variant`: `primary`, `secondary`, or `minimal`.
174
- - `size`: `2xs`, `xs`, `sm`, `md`, or `lg`.
154
+ - `href` — anchor destination.
155
+ - `variant` — `primary`, `secondary`, or `minimal`.
156
+ - `size` — `2xs`, `xs`, `sm`, `md`, or `lg`.
175
157
  - Other anchor attributes are forwarded.
176
158
 
177
159
  ### `ContainerSection`
178
160
 
179
- Props:
180
-
181
- - `width`: `sm`, `md`, `lg`, or `xl`.
161
+ - `width` — `sm`, `md`, `lg`, or `xl`.
182
162
 
183
163
  ### `Dropdown`
184
164
 
185
- Compound menu component exported as `Dropdown.Root`, `Dropdown.Trigger`, `Dropdown.Content`, `Dropdown.Item`, `Dropdown.Label`, `Dropdown.Separator`, and `Dropdown.Shortcut`.
165
+ Compound menu component exported as `Dropdown.Root`,
166
+ `Dropdown.Trigger`, `Dropdown.Content`, `Dropdown.Item`,
167
+ `Dropdown.Label`, `Dropdown.Separator`, and `Dropdown.Shortcut`.
186
168
 
187
169
  Useful props:
188
170
 
189
- - `Dropdown.Root`: `openOnHover`, `closeDelay`.
190
- - `Dropdown.Trigger`: `asChild`, `variant`, `size`.
191
- - `Dropdown.Content`: `side`, `align`, `sideOffset`, `animationDuration`.
192
- - `Dropdown.Item`: `as`, `inset`, `disabled`.
193
- - `Dropdown.Label`: `inset`.
171
+ - `Dropdown.Root` — `openOnHover`, `closeDelay`.
172
+ - `Dropdown.Trigger` — `asChild`, `variant`, `size`.
173
+ - `Dropdown.Content` — `side`, `align`, `sideOffset`,
174
+ `animationDuration`.
175
+ - `Dropdown.Item` — `as`, `inset`, `disabled`.
176
+ - `Dropdown.Label` — `inset`.
194
177
 
195
178
  ## Styling
196
179
 
@@ -204,6 +187,22 @@ Override theme tokens from your app CSS:
204
187
  }
205
188
  ```
206
189
 
190
+ ## Attribution
191
+
192
+ This theme recreates the design of the documentation site for
193
+ [shadcn/ui](https://ui.shadcn.com/).
194
+
195
+ It uses
196
+ [adrian-ub/starlight-theme-black](https://github.com/adrian-ub/starlight-theme-black)
197
+ as a base, which brought an earlier shadcn/ui-inspired design to
198
+ Astro Starlight.
199
+
200
+ ## Develop Starlight
201
+
202
+ ```bash
203
+ pnpm --filter @grove-dev/starlight test
204
+ ```
205
+
207
206
  ## License
208
207
 
209
- MIT
208
+ [MIT](../../LICENSE) © Grove contributors.
@@ -1,141 +1,186 @@
1
1
  ---
2
2
  import type { HTMLAttributes } from 'astro/types';
3
3
 
4
+ export type ButtonVariant = 'default' | 'link' | 'secondary' | 'outline' | 'ghost' | 'destructive';
5
+
6
+ /**
7
+ * Starlight's own hero action variants. Kept as aliases of their shadcn equivalents so existing
8
+ * frontmatter and `<LinkButton>` usage keeps working.
9
+ */
10
+ export type LegacyButtonVariant = 'primary' | 'minimal';
11
+
12
+ const LEGACY_VARIANTS = {
13
+ primary: 'default',
14
+ minimal: 'ghost',
15
+ } as const satisfies Record<LegacyButtonVariant, ButtonVariant>;
16
+
4
17
  type Props = (Omit<HTMLAttributes<'a'>, 'href'> | HTMLAttributes<'button'>) & {
18
+ /** Renders an `<a>` when set, a `<button>` otherwise. */
5
19
  href?: string | URL | null | undefined;
6
- variant?: 'primary' | 'secondary' | 'minimal';
20
+ variant?: ButtonVariant | LegacyButtonVariant;
7
21
  size?: '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'icon-sm' | 'icon-md' | 'icon-lg';
8
22
  };
9
23
 
10
- const { class: className, variant = 'primary', size = 'md', ...attrs } = Astro.props;
24
+ const { class: className, variant = 'default', size = 'md', ...attrs } = Astro.props;
25
+
26
+ // Normalise so the stylesheet only ever has to know about the canonical variant names.
27
+ const resolvedVariant: ButtonVariant =
28
+ LEGACY_VARIANTS[variant as LegacyButtonVariant] ?? (variant as ButtonVariant);
11
29
 
12
30
  const Tag = attrs.href ? 'a' : 'button';
13
31
  ---
14
32
 
15
33
  <Tag
16
34
  data-slot="button"
17
- class:list={['link-button', variant, className]}
35
+ data-variant={resolvedVariant}
18
36
  data-size={size}
37
+ class:list={['link-button', className]}
19
38
  {...attrs as any}
20
39
  >
21
40
  <slot />
22
41
  </Tag>
23
42
 
24
43
  <style>
25
- [data-slot='button'],
44
+ /*
45
+ * Styling is anchored on `.link-button`, never on `data-slot`. Consumers are allowed to replace
46
+ * `data-slot` with their own value — `DropdownTrigger` does, because `Dropdown.astro` queries
47
+ * `[data-slot='dropdown-trigger']` — so keying styles off it would silently unstyle them.
48
+ */
26
49
  .link-button {
50
+ display: inline-flex;
51
+ align-items: center;
52
+ justify-content: center;
53
+ white-space: nowrap;
54
+ gap: 0.5rem;
55
+ font-weight: var(--button-font-weight, 500);
56
+ border: none;
57
+ text-decoration: inherit;
27
58
  transition-property:
28
59
  color, background-color, border-color, text-decoration-color, fill, stroke;
29
60
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
30
61
  transition-duration: 0.15s;
31
- color: var(--primary-foreground);
32
- white-space: nowrap;
33
- gap: 0.5rem;
34
- justify-content: center;
35
- align-items: center;
36
- display: inline-flex;
37
- text-decoration: inherit;
38
- border: none;
39
-
62
+ border-radius: var(--button-radius, var(--radius));
40
63
  height: var(--button-height, calc(var(--spacing) * 8));
41
64
  width: var(--button-width, auto);
42
- font-weight: var(--button-font-weight, 500);
43
- font-size: var(--button-font-size, 0.875rem);
44
- line-height: var(--button-line-height, 1rem);
45
65
  padding-left: var(--button-padding-l, var(--button-padding-x, calc(var(--spacing) * 2.5)));
46
66
  padding-right: var(--button-padding-r, var(--button-padding-x, calc(var(--spacing) * 2.5)));
47
- border-radius: var(--button-radius, var(--radius));
67
+ font-size: var(--button-font-size, 0.875rem);
68
+ line-height: var(--button-line-height, 1rem);
69
+ }
48
70
 
49
- &[data-size='2xs'] {
50
- --button-height: calc(var(--spacing) * 5.5);
51
- --button-padding-l: calc(var(--spacing) * 2);
52
- --button-padding-r: var(--spacing);
53
- --button-font-size: 0.75rem;
54
- --border-radius: 100%;
55
- }
71
+ [data-size='2xs'] {
72
+ --button-height: calc(var(--spacing) * 5.5);
73
+ --button-padding-l: calc(var(--spacing) * 2);
74
+ --button-padding-r: var(--spacing);
75
+ --button-font-size: 0.75rem;
76
+ }
56
77
 
57
- &[data-size='xs'] {
58
- --button-radius: calc(var(--radius) - 2px);
59
- --button-height: calc(var(--spacing) * 6);
60
- --button-padding-x: calc(var(--spacing) * 2);
61
- --button-font-size: 0.75rem;
62
- }
78
+ [data-size='xs'] {
79
+ --button-radius: calc(var(--radius) - 2px);
80
+ --button-height: calc(var(--spacing) * 6);
81
+ --button-padding-x: calc(var(--spacing) * 2);
82
+ --button-font-size: 0.75rem;
83
+ }
63
84
 
64
- &[data-size='sm'] {
65
- --button-height: calc(var(--spacing) * 7);
66
- --button-padding-x: calc(var(--spacing) * 2.5);
67
- --button-font-size: 0.8rem;
68
- }
85
+ [data-size='sm'] {
86
+ --button-height: calc(var(--spacing) * 7);
87
+ --button-padding-x: calc(var(--spacing) * 2.5);
88
+ --button-font-size: 0.8rem;
89
+ }
69
90
 
70
- &[data-size='lg'] {
71
- --button-height: calc(var(--spacing) * 8.5);
72
- --button-padding-x: calc(var(--spacing) * 2.5);
73
- --button-font-size: 0.875rem;
74
- }
91
+ [data-size='lg'] {
92
+ --button-height: calc(var(--spacing) * 8.5);
93
+ --button-padding-x: calc(var(--spacing) * 2.5);
94
+ --button-font-size: 0.875rem;
95
+ }
96
+
97
+ [data-size='icon-sm'],
98
+ [data-size='icon-md'],
99
+ [data-size='icon-lg'] {
100
+ --button-padding-x: 0;
101
+ --button-font-size: 0;
102
+ }
103
+
104
+ [data-size='icon-sm'] {
105
+ --button-radius: calc(var(--radius) - 3px);
106
+ --button-height: calc(var(--spacing) * 6);
107
+ --button-width: calc(var(--spacing) * 6);
75
108
 
76
- &[data-size='icon-sm'] {
77
- --button-height: calc(var(--spacing) * 6);
78
- --button-width: calc(var(--spacing) * 6);
79
- --button-padding-x: 0;
80
- --button-font-size: 0;
81
- --button-radius: calc(var(--radius) - 3px);
82
-
83
- svg {
84
- width: 1rem;
85
- height: 1rem;
86
- }
109
+ svg {
110
+ width: 1rem;
111
+ height: 1rem;
87
112
  }
113
+ }
114
+
115
+ [data-size='icon-md'] {
116
+ --button-radius: calc(var(--radius) - 2px);
117
+ --button-height: calc(var(--spacing) * 7);
118
+ --button-width: calc(var(--spacing) * 7);
88
119
 
89
- &[data-size='icon-md'] {
90
- --button-height: calc(var(--spacing) * 7);
91
- --button-width: calc(var(--spacing) * 7);
92
- --button-padding-x: 0;
93
- --button-font-size: 0;
94
- --button-radius: calc(var(--radius) - 2px);
95
-
96
- svg {
97
- width: 1.25rem;
98
- height: 1.25rem;
99
- }
120
+ svg {
121
+ width: 1.25rem;
122
+ height: 1.25rem;
100
123
  }
124
+ }
125
+
126
+ [data-size='icon-lg'] {
127
+ --button-radius: calc(var(--radius) - 1px);
128
+ --button-height: calc(var(--spacing) * 8);
129
+ --button-width: calc(var(--spacing) * 8);
101
130
 
102
- &[data-size='icon-lg'] {
103
- --button-height: calc(var(--spacing) * 8);
104
- --button-width: calc(var(--spacing) * 8);
105
- --button-padding-x: 0;
106
- --button-font-size: 0;
107
- --button-radius: calc(var(--radius) - 1px);
108
-
109
- svg {
110
- width: 1.5rem;
111
- height: 1.5rem;
112
- }
131
+ svg {
132
+ width: 1.5rem;
133
+ height: 1.5rem;
113
134
  }
114
135
  }
115
136
 
116
- .primary {
117
- background-color: var(--primary);
137
+ [data-variant='secondary'] {
138
+ background: var(--secondary);
139
+ color: var(--secondary-foreground);
140
+ }
141
+ [data-variant='secondary']:hover {
142
+ background: color-mix(in oklab, var(--secondary) 80%, transparent);
118
143
  }
119
144
 
120
- .primary:hover {
121
- background-color: color-mix(in oklab, var(--primary) 90%, transparent);
145
+ [data-variant='default'] {
146
+ background: var(--primary);
147
+ color: var(--primary-foreground);
148
+ }
149
+ [data-variant='default']:hover {
150
+ background: color-mix(in oklab, var(--primary) 90%, transparent);
122
151
  }
123
152
 
124
- .secondary {
125
- background-color: var(--secondary);
126
- color: var(--secondary-foreground);
153
+ [data-variant='outline'] {
154
+ border: 1px solid var(--border);
155
+ background: var(--background);
156
+ color: var(--foreground);
157
+ }
158
+ [data-variant='outline']:hover {
159
+ background: var(--muted);
127
160
  }
128
161
 
129
- .secondary:hover {
130
- background-color: color-mix(in oklab, var(--secondary) 80%, transparent);
162
+ [data-variant='ghost'] {
163
+ background: transparent;
164
+ color: var(--foreground);
165
+ }
166
+ [data-variant='ghost']:hover {
167
+ background: var(--muted);
131
168
  }
132
169
 
133
- .minimal {
134
- color: var(--accent-foreground);
170
+ [data-variant='destructive'] {
171
+ background: color-mix(in oklab, var(--destructive) 10%, transparent);
172
+ color: var(--destructive);
173
+ }
174
+ [data-variant='destructive']:hover {
175
+ background: color-mix(in oklab, var(--destructive) 20%, transparent);
135
176
  }
136
177
 
137
- .minimal:hover {
138
- color: var(--accent-foreground);
139
- background-color: var(--accent);
178
+ [data-variant='link'] {
179
+ background: none;
180
+ color: var(--primary);
181
+ text-underline-offset: 4px;
182
+ }
183
+ [data-variant='link']:hover {
184
+ text-decoration: underline;
140
185
  }
141
186
  </style>
@@ -59,7 +59,7 @@ const {
59
59
  <style>
60
60
  div[data-slot='dropdown-content'] {
61
61
  background-color: var(--popover-background, var(--muted));
62
- color: var(var(--popover-foreground), var(--foreground));
62
+ color: var(--popover-foreground, var(--foreground));
63
63
  z-index: 50;
64
64
  min-width: 9rem;
65
65
  overflow-x: hidden;
@@ -134,46 +134,46 @@ const {
134
134
  &[data-side='right'][data-align='end'] {
135
135
  bottom: 0;
136
136
  }
137
+ }
138
+
139
+ /* animations */
140
+ @keyframes fade-in {
141
+ from {
142
+ opacity: 0;
143
+ }
144
+ to {
145
+ opacity: 1;
146
+ }
147
+ }
148
+
149
+ @keyframes fade-out {
150
+ from {
151
+ opacity: 1;
152
+ }
153
+ to {
154
+ opacity: 0;
155
+ }
156
+ }
137
157
 
138
- /* animations */
139
- @keyframes fade-in {
140
- from {
141
- opacity: 0;
142
- }
143
- to {
144
- opacity: 1;
145
- }
146
- }
147
-
148
- @keyframes fade-out {
149
- from {
150
- opacity: 1;
151
- }
152
- to {
153
- opacity: 0;
154
- }
155
- }
156
-
157
- @keyframes zoom-in-95 {
158
- from {
159
- opacity: 0;
160
- transform: scale(0.95);
161
- }
162
- to {
163
- opacity: 1;
164
- transform: scale(1);
165
- }
166
- }
167
-
168
- @keyframes zoom-out-95 {
169
- from {
170
- opacity: 1;
171
- transform: scale(1);
172
- }
173
- to {
174
- opacity: 0;
175
- transform: scale(0.95);
176
- }
158
+ @keyframes zoom-in-95 {
159
+ from {
160
+ opacity: 0;
161
+ transform: scale(0.95);
162
+ }
163
+ to {
164
+ opacity: 1;
165
+ transform: scale(1);
166
+ }
167
+ }
168
+
169
+ @keyframes zoom-out-95 {
170
+ from {
171
+ opacity: 1;
172
+ transform: scale(1);
173
+ }
174
+ to {
175
+ opacity: 0;
176
+ transform: scale(0.95);
177
177
  }
178
178
  }
179
179
  </style>
@@ -53,7 +53,12 @@ const { class: className, inset = false, disabled = false, as: Tag = 'div', ...r
53
53
  color: var(--accent-foreground);
54
54
  }
55
55
 
56
- > svg {
56
+ /*
57
+ * `:global` because the icon is slotted in by the consumer, so it carries that component's
58
+ * scope class rather than this one's. Astro 7 scopes descendant selectors that Astro 6 left
59
+ * alone, which would otherwise leave slotted icons unsized.
60
+ */
61
+ > :global(svg) {
57
62
  width: 1rem;
58
63
  height: 1rem;
59
64
  flex-shrink: 0;
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  import type { HTMLAttributes } from 'astro/types';
3
- import LinkButton from '../LinkButton.astro';
3
+ import LinkButton, { type ButtonVariant, type LegacyButtonVariant } from '../LinkButton.astro';
4
4
 
5
5
  type Props = Omit<HTMLAttributes<'button'>, 'role' | 'type'> & {
6
6
  /**
@@ -8,7 +8,7 @@ type Props = Omit<HTMLAttributes<'button'>, 'role' | 'type'> & {
8
8
  */
9
9
  asChild?: boolean;
10
10
 
11
- variant?: 'primary' | 'secondary' | 'minimal';
11
+ variant?: ButtonVariant | LegacyButtonVariant;
12
12
  size?: '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'icon-sm' | 'icon-md' | 'icon-lg';
13
13
  };
14
14