@grove-dev/astro 0.2.18 → 0.2.20

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.
Files changed (48) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +44 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/theme.test.d.ts +2 -0
  6. package/dist/theme.test.d.ts.map +1 -0
  7. package/dist/theme.test.js +55 -0
  8. package/dist/theme.test.js.map +1 -0
  9. package/package.json +1 -1
  10. package/src/components/CategoryGrid.astro +2 -11
  11. package/src/components/ContributorsGrid.astro +2 -11
  12. package/src/components/CurationGrid.astro +1 -1
  13. package/src/components/DecisionRow.astro +1 -1
  14. package/src/components/ExploreByCategory.astro +3 -3
  15. package/src/components/ExploreByStack.astro +3 -3
  16. package/src/components/FilterGroupMenu.astro +5 -5
  17. package/src/components/Hero.astro +11 -11
  18. package/src/components/Icon.astro +6 -33
  19. package/src/components/IndexRow.astro +5 -5
  20. package/src/components/ItemCard.astro +5 -16
  21. package/src/components/MinimalAbout.astro +2 -2
  22. package/src/components/OriginalCollection.astro +4 -4
  23. package/src/components/Pagination.astro +2 -2
  24. package/src/components/RecordSection.astro +1 -1
  25. package/src/components/RefinePanel.astro +1 -1
  26. package/src/components/SmartLensTabs.astro +3 -3
  27. package/src/components/StackGrid.astro +6 -15
  28. package/src/components/WhyThisExists.astro +3 -3
  29. package/src/index.ts +52 -1
  30. package/src/layouts/BaseLayout.astro +1 -1
  31. package/src/layouts/Container.astro +4 -4
  32. package/src/layouts/Footer.astro +3 -3
  33. package/src/layouts/Header.astro +5 -5
  34. package/src/layouts/ThemeToggle.astro +1 -1
  35. package/src/styles.css +217 -408
  36. package/src/theme.test.ts +67 -0
  37. package/templates/default/package.json +1 -1
  38. package/templates/default/public/icons/stacks/rag.svg +7 -0
  39. package/templates/default/public/llms-full.txt +1 -1
  40. package/templates/default/public/sitemap.xml +10 -10
  41. package/templates/default/src/pages/404.astro +5 -5
  42. package/templates/default/src/pages/[slug]/[recordSlug].astro +27 -31
  43. package/templates/default/src/pages/[slug]/index.astro +8 -37
  44. package/templates/default/src/pages/about.astro +9 -9
  45. package/templates/default/src/pages/contributors.astro +8 -17
  46. package/templates/default/src/pages/submit.astro +23 -31
  47. package/templates/default/src/styles/global.css +14 -39
  48. package/templates/default/tailwind.config.mjs +0 -130
@@ -60,7 +60,7 @@ const pleaseAvoid = [
60
60
  ["2", "Edit the draft", "Fix the category, stack, platforms, and notes."],
61
61
  ["3", "Open a pull request", "Reviewers will validate and merge the record."],
62
62
  ].map(([number, heading, copy]) => (
63
- <li class="card flex items-start gap-2 p-3">
63
+ <li class="rounded-[calc(var(--radius)+0.25rem)] border-0 bg-muted shadow-none transition-colors flex items-start gap-2 p-3">
64
64
  <span class="mt-0.5 inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full border border-ink-300 font-mono font-semibold text-ink-700 dark:border-ink-700 dark:text-ink-300">{number}</span>
65
65
  <div>
66
66
  <div class="font-medium text-ink-900 dark:text-ink-100">{heading}</div>
@@ -71,43 +71,43 @@ const pleaseAvoid = [
71
71
  </ol>
72
72
 
73
73
  <div class="mt-8 grid grid-cols-1 gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(360px,0.8fr)]">
74
- <form id="submit-form" class="card p-5">
74
+ <form id="submit-form" class="rounded-[calc(var(--radius)+0.25rem)] border-0 bg-muted shadow-none transition-colors p-5">
75
75
  <div class="grid gap-5">
76
76
  <label class="grid gap-1.5">
77
- <span class="label">GitHub URL</span>
77
+ <span class="text-2xs font-medium uppercase tracking-[.05em] text-muted-foreground">GitHub URL</span>
78
78
  <div class="flex flex-col gap-2 sm:flex-row">
79
- <input id="repo-url" type="url" required placeholder="https://github.com/owner/repo" class="field flex-1" />
80
- <button id="fetch-repo" type="button" class="btn-primary min-h-10 justify-center">Generate draft</button>
79
+ <input id="repo-url" type="url" required placeholder="https://github.com/owner/repo" class="min-h-10 flex-1 rounded-[var(--radius)] border border-input bg-background px-3 py-2 text-sm text-foreground outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35" />
80
+ <button id="fetch-repo" type="button" class="inline-flex h-8 cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap rounded-[var(--radius)] border border-transparent bg-primary px-3 text-sm font-medium leading-none text-primary-foreground no-underline outline-none transition-colors hover:bg-primary/90 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35 min-h-10 justify-center">Generate draft</button>
81
81
  </div>
82
- <span class="help">The repository must be public. We never write to it.</span>
82
+ <span class="text-2xs text-muted-foreground">The repository must be public. We never write to it.</span>
83
83
  </label>
84
84
 
85
85
  <div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
86
- <label class="grid gap-1.5"><span class="label">Name</span><input id="item-name" type="text" class="field" /></label>
87
- <label class="grid gap-1.5"><span class="label">Slug</span><input id="item-slug" type="text" class="field font-mono" /><span class="help">URL fragment, auto-filled from the repository name.</span></label>
86
+ <label class="grid gap-1.5"><span class="text-2xs font-medium uppercase tracking-[.05em] text-muted-foreground">Name</span><input id="item-name" type="text" class="min-h-10 rounded-[var(--radius)] border border-input bg-background px-3 py-2 text-sm text-foreground outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35" /></label>
87
+ <label class="grid gap-1.5"><span class="text-2xs font-medium uppercase tracking-[.05em] text-muted-foreground">Slug</span><input id="item-slug" type="text" class="min-h-10 rounded-[var(--radius)] border border-input bg-background px-3 py-2 font-mono text-sm text-foreground outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35" /><span class="text-2xs text-muted-foreground">URL fragment, auto-filled from the repository name.</span></label>
88
88
  </div>
89
89
 
90
90
  <label class="grid gap-1.5">
91
- <span class="label">Description</span>
92
- <textarea id="item-description" rows="3" class="field resize-y"></textarea>
93
- <span class="help">One or two sentences in plain language.</span>
91
+ <span class="text-2xs font-medium uppercase tracking-[.05em] text-muted-foreground">Description</span>
92
+ <textarea id="item-description" rows="3" class="min-h-10 resize-y rounded-[var(--radius)] border border-input bg-background px-3 py-2 text-sm text-foreground outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35"></textarea>
93
+ <span class="text-2xs text-muted-foreground">One or two sentences in plain language.</span>
94
94
  </label>
95
95
 
96
96
  <div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
97
97
  <label class="grid gap-1.5">
98
- <span class="label">Category</span>
99
- <input id="item-category" list="category-options" class="field" />
98
+ <span class="text-2xs font-medium uppercase tracking-[.05em] text-muted-foreground">Category</span>
99
+ <input id="item-category" list="category-options" class="min-h-10 rounded-[var(--radius)] border border-input bg-background px-3 py-2 text-sm text-foreground outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35" />
100
100
  <datalist id="category-options">{categories.map((value) => <option value={value} />)}</datalist>
101
101
  </label>
102
102
  <label class="grid gap-1.5">
103
- <span class="label">Primary stack</span>
104
- <input id="primary-stack" list="stack-options" class="field" />
103
+ <span class="text-2xs font-medium uppercase tracking-[.05em] text-muted-foreground">Primary stack</span>
104
+ <input id="primary-stack" list="stack-options" class="min-h-10 rounded-[var(--radius)] border border-input bg-background px-3 py-2 text-sm text-foreground outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35" />
105
105
  <datalist id="stack-options">{stacks.map((value) => <option value={value} />)}</datalist>
106
106
  </label>
107
107
  </div>
108
108
 
109
109
  <fieldset class="grid gap-2">
110
- <legend class="label">Platforms</legend>
110
+ <legend class="text-2xs font-medium uppercase tracking-[.05em] text-muted-foreground">Platforms</legend>
111
111
  <div class="grid grid-cols-2 gap-2 sm:grid-cols-3">
112
112
  {platformOptions.map((platform) => (
113
113
  <label class="flex min-h-9 items-center gap-2 rounded-md border border-ink-200 px-2 text-sm dark:border-ink-800">
@@ -118,14 +118,14 @@ const pleaseAvoid = [
118
118
  </div>
119
119
  </fieldset>
120
120
 
121
- <label class="grid gap-1.5"><span class="label">Tags</span><input id="item-tags" type="text" placeholder="self-hosted, developer-tools, offline-first" class="field" /></label>
122
- <label class="grid gap-1.5"><span class="label">Website</span><input id="item-website" type="url" placeholder="https://example.com" class="field" /></label>
123
- <label class="grid gap-1.5"><span class="label">Best for</span><textarea id="best-for" rows="3" class="field resize-y" placeholder="One use case per line"></textarea></label>
121
+ <label class="grid gap-1.5"><span class="text-2xs font-medium uppercase tracking-[.05em] text-muted-foreground">Tags</span><input id="item-tags" type="text" placeholder="self-hosted, developer-tools, offline-first" class="min-h-10 rounded-[var(--radius)] border border-input bg-background px-3 py-2 text-sm text-foreground outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35" /></label>
122
+ <label class="grid gap-1.5"><span class="text-2xs font-medium uppercase tracking-[.05em] text-muted-foreground">Website</span><input id="item-website" type="url" placeholder="https://example.com" class="min-h-10 rounded-[var(--radius)] border border-input bg-background px-3 py-2 text-sm text-foreground outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35" /></label>
123
+ <label class="grid gap-1.5"><span class="text-2xs font-medium uppercase tracking-[.05em] text-muted-foreground">Best for</span><textarea id="best-for" rows="3" class="min-h-10 resize-y rounded-[var(--radius)] border border-input bg-background px-3 py-2 text-sm text-foreground outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35" placeholder="One use case per line"></textarea></label>
124
124
  </div>
125
125
  </form>
126
126
 
127
127
  <aside class="flex flex-col gap-4">
128
- <div class="card p-5">
128
+ <div class="rounded-[calc(var(--radius)+0.25rem)] border-0 bg-muted shadow-none transition-colors p-5">
129
129
  <h2 class="m-0 text-[0.9375rem] font-semibold text-ink-900 dark:text-ink-100">Submission criteria</h2>
130
130
  <p class="m-0 mt-1 text-2xs text-ink-500 dark:text-ink-400">Use this checklist before opening the draft.</p>
131
131
  <div class="mt-4 grid grid-cols-1 gap-4 text-2xs sm:grid-cols-2 lg:grid-cols-1 xl:grid-cols-2">
@@ -140,12 +140,12 @@ const pleaseAvoid = [
140
140
  </div>
141
141
  </div>
142
142
 
143
- <div class="card flex min-h-[420px] flex-col p-5">
143
+ <div class="rounded-[calc(var(--radius)+0.25rem)] border-0 bg-muted shadow-none transition-colors flex min-h-[420px] flex-col p-5">
144
144
  <div class="flex flex-wrap items-center justify-between gap-3">
145
145
  <h2 class="m-0 text-base font-semibold text-ink-900 dark:text-ink-100">YAML draft</h2>
146
146
  <div class="flex items-center gap-2">
147
- <button id="copy-yaml" type="button" class="btn-outline pointer-events-none opacity-50" disabled>Copy YAML</button>
148
- <a id="open-pr-link" href="#" target="_blank" rel="noopener noreferrer" class="btn-outline pointer-events-none opacity-50">Open PR draft</a>
147
+ <button id="copy-yaml" type="button" class="inline-flex h-8 cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap rounded-[var(--radius)] border border-border bg-secondary px-3 text-sm font-medium leading-none text-foreground no-underline outline-none transition-colors hover:bg-accent focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35 pointer-events-none opacity-50" disabled>Copy YAML</button>
148
+ <a id="open-pr-link" href="#" target="_blank" rel="noopener noreferrer" class="inline-flex h-8 cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap rounded-[var(--radius)] border border-border bg-secondary px-3 text-sm font-medium leading-none text-foreground no-underline outline-none transition-colors hover:bg-accent focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35 pointer-events-none opacity-50">Open PR draft</a>
149
149
  </div>
150
150
  </div>
151
151
  <pre class="mt-4 min-h-0 flex-1 overflow-auto rounded-md border border-ink-200 bg-ink-50 p-3 text-xs leading-relaxed text-ink-800 dark:border-ink-800 dark:bg-ink-900/60 dark:text-ink-200"><code id="yaml-preview">Paste a GitHub URL to generate a draft.</code></pre>
@@ -156,14 +156,6 @@ const pleaseAvoid = [
156
156
  </section>
157
157
  </Container>
158
158
 
159
- <style>
160
- .field { min-height: 2.5rem; border-radius: .375rem; border: 1px solid var(--color-ink-200); background: white; padding: .5rem .75rem; color: var(--color-ink-900); font-size: .875rem; outline: none; }
161
- .field:focus { border-color: var(--color-ink-500); }
162
- :global(.dark) .field { border-color: var(--color-ink-800); background: var(--color-ink-950); color: var(--color-ink-100); }
163
- .label { font-size: var(--text-2xs); font-weight: 500; text-transform: uppercase; letter-spacing: .05em; color: var(--color-ink-500); }
164
- .help { font-size: var(--text-2xs); color: var(--color-ink-500); }
165
- </style>
166
-
167
159
  <script is:inline define:vars={{ existingSlugs, existingFullNames, repoUrl }}>
168
160
  // @ts-nocheck
169
161
  const $ = (selector) => document.querySelector(selector);
@@ -5,26 +5,22 @@
5
5
  * at scaffold time; we expose the same names as CSS variables so
6
6
  * consumers can layer their own brand colors in without forking.
7
7
  *
8
- * The `ink-*` color scale is preserved from the V0 template because
9
- * the page-level classes (`text-ink-900`, `bg-ink-50`, ...) still
10
- * reference it. New pages should prefer the default Tailwind
11
- * `gray-*` / `slate-*` palettes; the ink scale exists for
12
- * back-compat with the V1 minimal template.
8
+ * The package owns the Starlight-aligned palette, semantic theme tokens,
9
+ * font stacks, and light/dark base styles. This consumer sheet contains
10
+ * only scaffold-level overrides so those foundations cannot drift when
11
+ * the package theme changes.
12
+ *
13
+ * NOTE: do NOT add `@custom-variant dark` here. `@grove-dev/astro`'s
14
+ * `styles.css` already declares the `.dark`-class variant, and
15
+ * Tailwind v4 only honors one definition per build — adding a
16
+ * second one in this consumer file has been observed to confuse
17
+ * the variant resolution and produce utilities that key off
18
+ * `prefers-color-scheme` instead of the `.dark` class on <html>.
19
+ * The net effect: `<html class="dark">` is set but the page stays
20
+ * in light mode because the `dark:` utilities never match.
13
21
  */
14
22
  @theme {
15
- --color-ink-50: #fafafa;
16
- --color-ink-100: #f4f4f5;
17
- --color-ink-200: #e4e4e7;
18
- --color-ink-300: #d4d4d8;
19
- --color-ink-400: #a1a1aa;
20
- --color-ink-500: #71717a;
21
- --color-ink-600: #52525b;
22
- --color-ink-700: #3f3f46;
23
- --color-ink-800: #27272a;
24
- --color-ink-900: #18181b;
25
- --color-ink-950: #09090b;
26
-
27
- --color-grove-primary: #16a34a;
23
+ --color-grove-primary: var(--color-foreground);
28
24
  }
29
25
 
30
26
  @layer base {
@@ -33,26 +29,5 @@
33
29
  --grove-radius: 0.5rem;
34
30
  --grove-container-width: 72rem;
35
31
 
36
- color-scheme: light dark;
37
- }
38
-
39
- html {
40
- -webkit-text-size-adjust: 100%;
41
- -webkit-font-smoothing: antialiased;
42
- -moz-osx-font-smoothing: grayscale;
43
- }
44
-
45
- body {
46
- background: #ffffff;
47
- color: var(--color-ink-900);
48
- font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
49
- "Helvetica Neue", Arial, sans-serif;
50
- font-size: 15px;
51
- line-height: 1.55;
52
- }
53
-
54
- body.dark {
55
- background: var(--color-ink-950);
56
- color: var(--color-ink-100);
57
32
  }
58
33
  }
@@ -1,130 +0,0 @@
1
- /** @type {import('tailwindcss').Config} */
2
- export default {
3
- content: ['./src/**/*.{astro,html,js,jsx,ts,tsx,md,mdx}'],
4
- // Use a `.dark` class on <html> (toggled by the theme script in
5
- // the document head) rather than the OS media query, so a manual
6
- // theme switcher can override the user's system preference.
7
- darkMode: 'class',
8
- theme: {
9
- // Disable default palette so we only ship our own neutral / accent
10
- // tokens. Keeps the bundle small and forces a unified look.
11
- colors: {
12
- transparent: 'transparent',
13
- current: 'currentColor',
14
- white: '#ffffff',
15
- black: '#000000',
16
- ink: {
17
- 50: '#fafafa',
18
- 100: '#f4f4f5',
19
- 200: '#e4e4e7',
20
- 300: '#d4d4d8',
21
- 400: '#a1a1aa',
22
- 500: '#71717a',
23
- 600: '#52525b',
24
- 700: '#3f3f46',
25
- 800: '#27272a',
26
- 900: '#18181b',
27
- 950: '#09090b',
28
- },
29
- accent: {
30
- DEFAULT: '#1f6feb',
31
- muted: '#388bfd1a',
32
- },
33
- emerald: {
34
- 50: '#ecfdf5',
35
- 300: '#6ee7b7',
36
- 400: '#34d399',
37
- 700: '#047857',
38
- 800: '#065f46',
39
- 950: '#022c22',
40
- },
41
- orange: {
42
- 50: '#fff7ed',
43
- 300: '#fdba74',
44
- 400: '#fb923c',
45
- 700: '#c2410c',
46
- 800: '#9a3412',
47
- 950: '#431407',
48
- },
49
- blue: {
50
- 50: '#eff6ff',
51
- 300: '#93c5fd',
52
- 400: '#60a5fa',
53
- 700: '#1d4ed8',
54
- 800: '#1e40af',
55
- 950: '#172554',
56
- },
57
- amber: {
58
- 50: '#fffbeb',
59
- 300: '#fcd34d',
60
- 400: '#fbbf24',
61
- 700: '#b45309',
62
- 800: '#92400e',
63
- 950: '#451a03',
64
- },
65
- },
66
- extend: {
67
- fontFamily: {
68
- sans: [
69
- 'ui-sans-serif',
70
- 'system-ui',
71
- '-apple-system',
72
- 'BlinkMacSystemFont',
73
- '"Segoe UI"',
74
- 'Roboto',
75
- '"Helvetica Neue"',
76
- 'Arial',
77
- 'sans-serif',
78
- ],
79
- mono: [
80
- 'ui-monospace',
81
- 'SFMono-Regular',
82
- 'Menlo',
83
- 'Monaco',
84
- 'Consolas',
85
- '"Liberation Mono"',
86
- '"Courier New"',
87
- 'monospace',
88
- ],
89
- },
90
- fontSize: {
91
- '2xs': ['0.6875rem', { lineHeight: '1rem' }],
92
- },
93
- maxWidth: {
94
- container: '1140px',
95
- wide: '1400px',
96
- narrow: '720px',
97
- },
98
- borderRadius: {
99
- DEFAULT: '0.375rem',
100
- lg: '0.5rem',
101
- xl: '0.75rem',
102
- },
103
- keyframes: {
104
- 'fade-in-up': {
105
- '0%': { opacity: '0', transform: 'translateY(8px)' },
106
- '100%': { opacity: '1', transform: 'translateY(0)' },
107
- },
108
- 'fade-in': {
109
- '0%': { opacity: '0' },
110
- '100%': { opacity: '1' },
111
- },
112
- 'gradient-shift': {
113
- '0%, 100%': { 'background-position': '0% 50%' },
114
- '50%': { 'background-position': '100% 50%' },
115
- },
116
- 'subtle-bob': {
117
- '0%, 100%': { transform: 'translateY(0)' },
118
- '50%': { transform: 'translateY(-2px)' },
119
- },
120
- },
121
- animation: {
122
- 'fade-in-up': 'fade-in-up 0.6s ease-out both',
123
- 'fade-in': 'fade-in 0.8s ease-out both',
124
- 'gradient-shift': 'gradient-shift 8s ease-in-out infinite',
125
- 'subtle-bob': 'subtle-bob 3s ease-in-out infinite',
126
- },
127
- },
128
- },
129
- plugins: [],
130
- };