astro-component-kit 0.3.1 → 0.4.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/README.md +33 -14
- package/package.json +2 -2
- package/src/components/index.ts +16 -202
- package/src/components/lib/buttons/NeonBorderButton.astro +162 -0
- package/src/components/lib/buttons/RippleButton.astro +199 -0
- package/src/components/lib/buttons/SlideRevealButton.astro +159 -0
- package/src/components/lib/buttons/index.ts +4 -0
- package/src/components/lib/cards/GithubRepoCard.astro +176 -0
- package/src/components/lib/cards/PricingCompareMiniCard.astro +196 -0
- package/src/components/lib/cards/StatsTrendCard.astro +149 -0
- package/src/components/lib/cards/index.ts +3 -0
- package/src/components/lib/charts/ActivityRings.astro +105 -0
- package/src/components/lib/charts/BoxPlotChart.astro +109 -0
- package/src/components/lib/charts/BubbleChart.astro +101 -0
- package/src/components/lib/charts/BulletChart.astro +160 -0
- package/src/components/lib/charts/BumpChart.astro +92 -0
- package/src/components/lib/charts/CandlestickChart.astro +105 -0
- package/src/components/lib/charts/ChartFrame.astro +373 -0
- package/src/components/lib/charts/DivergingBarChart.astro +98 -0
- package/src/components/lib/charts/DumbbellChart.astro +92 -0
- package/src/components/lib/charts/ForecastLineChart.astro +125 -0
- package/src/components/lib/charts/FunnelChart.astro +122 -0
- package/src/components/lib/charts/GaugeChart.astro +111 -0
- package/src/components/lib/charts/GoalProgressChart.astro +97 -0
- package/src/components/lib/charts/GroupedBarChart.astro +125 -0
- package/src/components/lib/charts/HeatmapChart.astro +131 -0
- package/src/components/lib/charts/HistogramChart.astro +111 -0
- package/src/components/lib/charts/HorizontalBarChart.astro +155 -0
- package/src/components/lib/charts/KpiStatTile.astro +116 -0
- package/src/components/lib/charts/KpiTrendGrid.astro +60 -0
- package/src/components/lib/charts/LineChart.astro +160 -0
- package/src/components/lib/charts/LinearProgressGauge.astro +136 -0
- package/src/components/lib/charts/LollipopChart.astro +100 -0
- package/src/components/lib/charts/MeterGauge.astro +122 -0
- package/src/components/lib/charts/MetricDeltaTable.astro +125 -0
- package/src/components/lib/charts/PieChart.astro +135 -0
- package/src/components/lib/charts/PolarAreaChart.astro +85 -0
- package/src/components/lib/charts/PopulationPyramid.astro +122 -0
- package/src/components/lib/charts/PunchCardChart.astro +89 -0
- package/src/components/lib/charts/RadarChart.astro +94 -0
- package/src/components/lib/charts/RadarMetricChart.astro +168 -0
- package/src/components/lib/charts/RadialBarChart.astro +124 -0
- package/src/components/lib/charts/RangeAreaChart.astro +113 -0
- package/src/components/lib/charts/RetentionCohortTable.astro +126 -0
- package/src/components/lib/charts/SankeyChart.astro +128 -0
- package/src/components/lib/charts/ScatterPlot.astro +139 -0
- package/src/components/lib/charts/SegmentedBarChart.astro +119 -0
- package/src/components/lib/charts/SlopeChart.astro +105 -0
- package/src/components/lib/charts/SparklineChart.astro +87 -0
- package/src/components/lib/charts/StackedAreaChart.astro +130 -0
- package/src/components/lib/charts/StackedBarChart.astro +136 -0
- package/src/components/lib/charts/SunburstChart.astro +103 -0
- package/src/components/lib/charts/TreemapChart.astro +94 -0
- package/src/components/lib/charts/WaffleChart.astro +121 -0
- package/src/components/lib/charts/WaterfallChart.astro +118 -0
- package/src/components/lib/charts/chart-tooltip.ts +75 -0
- package/src/components/lib/charts/chart-utils.ts +271 -0
- package/src/components/lib/charts/index.ts +46 -0
- package/src/components/lib/data/ActivityHeatmapGrid.astro +157 -0
- package/src/components/lib/data/MetricComparisonRow.astro +109 -0
- package/src/components/lib/data/StatusTimelineFeed.astro +168 -0
- package/src/components/lib/data/index.ts +3 -0
- package/src/components/lib/feedback/ProgressRingCounter.astro +118 -0
- package/src/components/lib/feedback/ToastNotificationGroup.astro +173 -0
- package/src/components/lib/feedback/index.ts +2 -0
- package/src/components/lib/forms/GlassInlineToggleGroup.astro +161 -0
- package/src/components/lib/forms/PasswordStrengthInput.astro +242 -0
- package/src/components/lib/forms/PhoneCountryInput.astro +145 -0
- package/src/components/lib/forms/TagsAutocompleteInput.astro +249 -0
- package/src/components/lib/forms/index.ts +5 -0
- package/src/components/lib/layout/DiagonalSectionDivider.astro +69 -0
- package/src/components/lib/layout/HolyGrailGrid.astro +125 -0
- package/src/components/lib/layout/index.ts +3 -1
- package/src/components/lib/navigation/QuickJumpDock.astro +125 -0
- package/src/components/lib/navigation/StepBreadcrumbBar.astro +151 -0
- package/src/components/lib/navigation/SubNavbarPills.astro +102 -0
- package/src/components/lib/navigation/index.ts +3 -0
- package/src/components/lib/overlays/CookiePreferencesDrawer.astro +226 -0
- package/src/components/lib/overlays/FloatingFeedbackWidget.astro +203 -0
- package/src/components/lib/overlays/ImageCompareSlider.astro +172 -0
- package/src/components/lib/overlays/index.ts +3 -0
- package/src/components/lib/sections/BlogGridSection.astro +131 -0
- package/src/components/lib/sections/CareersOpenings.astro +139 -0
- package/src/components/lib/sections/ChangelogSection.astro +144 -0
- package/src/components/lib/sections/ContactSplitMap.astro +139 -0
- package/src/components/lib/sections/CtaNewsletterSection.astro +163 -0
- package/src/components/lib/sections/CtaSplitImage.astro +147 -0
- package/src/components/lib/sections/FaqTwoColumn.astro +119 -0
- package/src/components/lib/sections/FeatureAlternatingRows.astro +190 -0
- package/src/components/lib/sections/FeatureIconGrid.astro +155 -0
- package/src/components/lib/sections/FeatureTabsShowcase.astro +180 -0
- package/src/components/lib/sections/FooterMegaSection.astro +155 -0
- package/src/components/lib/sections/HeroDashboardPreview.astro +180 -0
- package/src/components/lib/sections/HeroMinimalCentered.astro +175 -0
- package/src/components/lib/sections/HeroShowcaseSplit.astro +304 -0
- package/src/components/lib/sections/HeroTerminal.astro +251 -0
- package/src/components/lib/sections/HeroWaitlist.astro +229 -0
- package/src/components/lib/sections/HowItWorksSteps.astro +178 -0
- package/src/components/lib/sections/IntegrationsGrid.astro +167 -0
- package/src/components/lib/sections/LogoCloudSection.astro +96 -0
- package/src/components/lib/sections/LogoWallGrid.astro +91 -0
- package/src/components/lib/sections/PricingSinglePlan.astro +157 -0
- package/src/components/lib/sections/PricingToggleCards.astro +171 -0
- package/src/components/lib/sections/StatsCounterBand.astro +122 -0
- package/src/components/lib/sections/StatsDashboardSection.astro +83 -0
- package/src/components/lib/sections/TestimonialCarousel.astro +165 -0
- package/src/components/lib/sections/TestimonialFeatured.astro +120 -0
- package/src/components/lib/sections/TestimonialGridSection.astro +188 -0
- package/src/components/lib/sections/index.ts +29 -0
- package/src/components/lib/typography/AnimatedCounterText.astro +102 -0
- package/src/components/lib/typography/CurvedPathHeading.astro +86 -0
- package/src/components/lib/typography/GradientTextMarquee.astro +105 -0
- package/src/components/lib/typography/HackerDecodeText.astro +85 -0
- package/src/components/lib/typography/index.ts +4 -0
- package/src/styles/global.css +18 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* FooterMegaSection — Full site footer: brand blurb, newsletter field, four link
|
|
4
|
+
* columns, social icons, system-status pill and legal row.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} brand - Brand name.
|
|
7
|
+
* @param {string} tagline - Short brand description.
|
|
8
|
+
* @param {Array<{title: string, links: Array<{label: string, href: string}>}>} columns - Link columns.
|
|
9
|
+
* @param {Array<{label: string, href: string, icon: 'github'|'x'|'discord'|'youtube'}>} socials - Social links.
|
|
10
|
+
* @param {string} status - System status text (empty to hide).
|
|
11
|
+
* @param {string} copyright - Copyright line.
|
|
12
|
+
* @param {string} variant - Footer style (default|bordered|minimal).
|
|
13
|
+
* @param {string} size - Vertical rhythm (sm|md|lg).
|
|
14
|
+
* @param {string} className - Extra CSS class.
|
|
15
|
+
*/
|
|
16
|
+
interface Column { title: string; links: Array<{ label: string; href: string }> }
|
|
17
|
+
interface Social { label: string; href: string; icon: 'github' | 'x' | 'discord' | 'youtube' }
|
|
18
|
+
interface Props {
|
|
19
|
+
brand?: string;
|
|
20
|
+
tagline?: string;
|
|
21
|
+
columns?: Column[];
|
|
22
|
+
socials?: Social[];
|
|
23
|
+
status?: string;
|
|
24
|
+
copyright?: string;
|
|
25
|
+
variant?: 'default' | 'bordered' | 'minimal';
|
|
26
|
+
size?: 'sm' | 'md' | 'lg';
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const {
|
|
31
|
+
brand = 'Astro Kit',
|
|
32
|
+
tagline = 'Accessible, zero-dependency components for building beautiful Astro sites.',
|
|
33
|
+
columns = [
|
|
34
|
+
{ title: 'Product', links: [{ label: 'Components', href: '#' }, { label: 'Sections', href: '#' }, { label: 'Charts', href: '#' }, { label: 'Changelog', href: '#' }] },
|
|
35
|
+
{ title: 'Resources', links: [{ label: 'Documentation', href: '#' }, { label: 'Installation', href: '#' }, { label: 'Notes', href: '#' }, { label: 'Showcase', href: '#' }] },
|
|
36
|
+
{ title: 'Company', links: [{ label: 'About', href: '#' }, { label: 'Careers', href: '#' }, { label: 'Contact', href: '#' }] },
|
|
37
|
+
{ title: 'Legal', links: [{ label: 'Privacy', href: '#' }, { label: 'Terms', href: '#' }, { label: 'License (MIT)', href: '#' }] },
|
|
38
|
+
],
|
|
39
|
+
socials = [
|
|
40
|
+
{ label: 'GitHub', href: '#', icon: 'github' },
|
|
41
|
+
{ label: 'X (Twitter)', href: '#', icon: 'x' },
|
|
42
|
+
{ label: 'Discord', href: '#', icon: 'discord' },
|
|
43
|
+
{ label: 'YouTube', href: '#', icon: 'youtube' },
|
|
44
|
+
],
|
|
45
|
+
status = 'All systems operational',
|
|
46
|
+
copyright = `© ${new Date().getFullYear()} Astro Kit. All rights reserved.`,
|
|
47
|
+
variant = 'default',
|
|
48
|
+
size = 'md',
|
|
49
|
+
className = '',
|
|
50
|
+
} = Astro.props;
|
|
51
|
+
|
|
52
|
+
const icons = {
|
|
53
|
+
github: '<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-.9-2.6c3.1-.4 6.4-1.5 6.4-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 19.9 1S18.7.6 16 2.5a13.4 13.4 0 0 0-7 0C6.3.6 5.1 1 5.1 1A5 5 0 0 0 5 4.8a5.4 5.4 0 0 0-1.5 3.7c0 5.4 3.3 6.6 6.4 7a3.4 3.4 0 0 0-.9 2.6V22"/>',
|
|
54
|
+
x: '<path d="M4 4l16 16M20 4 4 20"/>',
|
|
55
|
+
discord: '<path d="M8 12h.01M16 12h.01"/><path d="M7.5 7.5c3-1 6-1 9 0M7 16.5c3 1 7 1 10 0"/><path d="M15.5 17l1 3c3-1 5-3 5.5-4.5.5-4-1-8-3-11-1.5-.8-3-1.2-4.5-1.5L14 4.5M8.5 17l-1 3c-3-1-5-3-5.5-4.5-.5-4 1-8 3-11 1.5-.8 3-1.2 4.5-1.5L10 4.5"/>',
|
|
56
|
+
youtube: '<path d="M2.5 17a24 24 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.6 49.6 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24 24 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.6 49.6 0 0 1-16.2 0A2 2 0 0 1 2.5 17"/><path d="m10 15 5-3-5-3z"/>',
|
|
57
|
+
};
|
|
58
|
+
const id = `fms-${Math.random().toString(36).slice(2, 8)}`;
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
<footer class={`fms fms--${variant} fms--${size} ${className}`} aria-labelledby={id}>
|
|
62
|
+
<h2 id={id} class="fms__sr">Site footer</h2>
|
|
63
|
+
<div class="fms__inner">
|
|
64
|
+
<div class="fms__top">
|
|
65
|
+
<div class="fms__brand">
|
|
66
|
+
<a class="fms__logo" href="/">
|
|
67
|
+
<svg width="28" height="28" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2 3 20h4l5-10 5 10h4z" fill="var(--c-primary-light, #d4a017)" /></svg>
|
|
68
|
+
{brand}
|
|
69
|
+
</a>
|
|
70
|
+
<p class="fms__tagline">{tagline}</p>
|
|
71
|
+
<form class="fms__news" action="#" method="post">
|
|
72
|
+
<label for={`${id}-email`} class="fms__news-label">Get product updates</label>
|
|
73
|
+
<div class="fms__news-field">
|
|
74
|
+
<input id={`${id}-email`} type="email" name="email" placeholder="you@company.com" autocomplete="email" required />
|
|
75
|
+
<button type="submit" aria-label="Subscribe to product updates">
|
|
76
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6" /></svg>
|
|
77
|
+
</button>
|
|
78
|
+
</div>
|
|
79
|
+
</form>
|
|
80
|
+
</div>
|
|
81
|
+
<nav class="fms__cols" aria-label="Footer">
|
|
82
|
+
{columns.map((c) => (
|
|
83
|
+
<div class="fms__col">
|
|
84
|
+
<h3 class="fms__col-title">{c.title}</h3>
|
|
85
|
+
<ul>
|
|
86
|
+
{c.links.map((l) => <li><a href={l.href}>{l.label}</a></li>)}
|
|
87
|
+
</ul>
|
|
88
|
+
</div>
|
|
89
|
+
))}
|
|
90
|
+
</nav>
|
|
91
|
+
</div>
|
|
92
|
+
<div class="fms__bottom">
|
|
93
|
+
<p class="fms__copy">{copyright}</p>
|
|
94
|
+
{status && (
|
|
95
|
+
<a class="fms__status" href="#">
|
|
96
|
+
<span class="fms__dot" aria-hidden="true"></span>{status}
|
|
97
|
+
</a>
|
|
98
|
+
)}
|
|
99
|
+
<ul class="fms__socials">
|
|
100
|
+
{socials.map((s) => (
|
|
101
|
+
<li>
|
|
102
|
+
<a href={s.href} aria-label={s.label}>
|
|
103
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" set:html={icons[s.icon]}></svg>
|
|
104
|
+
</a>
|
|
105
|
+
</li>
|
|
106
|
+
))}
|
|
107
|
+
</ul>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</footer>
|
|
111
|
+
|
|
112
|
+
<style>
|
|
113
|
+
.fms {
|
|
114
|
+
--fms-py: 4.5rem;
|
|
115
|
+
padding: var(--fms-py) var(--sp-6, 1.5rem) 2rem;
|
|
116
|
+
background: var(--c-bg-1, #0a0a0a);
|
|
117
|
+
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
|
118
|
+
}
|
|
119
|
+
.fms--sm { --fms-py: 3rem; }
|
|
120
|
+
.fms--lg { --fms-py: 6rem; }
|
|
121
|
+
.fms--bordered .fms__inner { padding: clamp(1.5rem, 4vw, 3rem); border-radius: var(--r-xl, 28px); border: 1px solid var(--c-border, rgba(255, 255, 255, 0.08)); background: rgba(255, 255, 255, 0.015); }
|
|
122
|
+
.fms--minimal { background: transparent; border-top: 0; }
|
|
123
|
+
.fms--minimal .fms__news { display: none; }
|
|
124
|
+
.fms__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
125
|
+
.fms__inner { max-width: 1180px; margin: 0 auto; }
|
|
126
|
+
.fms__top { display: grid; grid-template-columns: 1.2fr 2fr; gap: clamp(2rem, 6vw, 5rem); padding-bottom: 3rem; border-bottom: 1px solid rgba(255, 255, 255, 0.07); }
|
|
127
|
+
.fms__logo { display: inline-flex; align-items: center; gap: 0.6rem; min-height: 44px; font-size: 1.25rem; font-weight: 800; letter-spacing: -0.02em; color: var(--c-text-1, #fff); text-decoration: none; }
|
|
128
|
+
.fms__tagline { margin: 0.75rem 0 1.75rem; max-width: 320px; font-size: 0.9375rem; line-height: 1.6; color: var(--c-text-2, #a3a3a3); }
|
|
129
|
+
.fms__news-label { display: block; margin-bottom: 0.5rem; font-size: 0.8125rem; font-weight: 600; color: var(--c-text-1, #fff); }
|
|
130
|
+
.fms__news-field { display: flex; max-width: 340px; border-radius: var(--r-md, 12px); border: 1px solid rgba(255, 255, 255, 0.12); background: rgba(0, 0, 0, 0.3); overflow: hidden; transition: border-color 0.2s ease; }
|
|
131
|
+
.fms__news-field:focus-within { border-color: var(--c-primary-light, #d4a017); }
|
|
132
|
+
.fms__news-field input { flex: 1; min-width: 0; min-height: 46px; padding: 0 0.9rem; border: 0; background: transparent; color: var(--c-text-1, #fff); font: inherit; font-size: 0.9375rem; }
|
|
133
|
+
.fms__news-field input:focus { outline: none; }
|
|
134
|
+
.fms__news-field input::placeholder { color: var(--c-text-3, #737373); }
|
|
135
|
+
.fms__news-field button { width: 46px; border: 0; background: rgba(255, 255, 255, 0.06); color: var(--c-text-1, #fff); cursor: pointer; transition: background 0.2s ease; }
|
|
136
|
+
.fms__news-field button:hover { background: var(--c-primary-light, #d4a017); color: #0a0a0a; }
|
|
137
|
+
.fms__news-field button:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: -2px; }
|
|
138
|
+
.fms__cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 2rem; }
|
|
139
|
+
.fms__col-title { margin: 0 0 1rem; font-size: 0.8125rem; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--c-text-1, #fff); }
|
|
140
|
+
.fms__col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.25rem; }
|
|
141
|
+
.fms__col a, .fms__copy, .fms__status { font-size: 0.9rem; color: var(--c-text-2, #a3a3a3); text-decoration: none; }
|
|
142
|
+
.fms__col a { display: inline-flex; align-items: center; min-height: 36px; transition: color 0.2s ease; }
|
|
143
|
+
.fms__col a:hover { color: var(--c-text-1, #fff); }
|
|
144
|
+
.fms a:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 2px; border-radius: 4px; }
|
|
145
|
+
.fms__bottom { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; padding-top: 1.75rem; }
|
|
146
|
+
.fms__copy { margin: 0; font-size: 0.8125rem; }
|
|
147
|
+
.fms__status { display: inline-flex; align-items: center; gap: 0.5rem; min-height: 36px; padding: 0 0.85rem; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.08); font-size: 0.8125rem; }
|
|
148
|
+
.fms__status:hover { color: var(--c-text-1, #fff); }
|
|
149
|
+
.fms__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--chart-pos, #34c38f); box-shadow: 0 0 8px var(--chart-pos, #34c38f); }
|
|
150
|
+
.fms__socials { list-style: none; margin: 0; padding: 0; display: flex; gap: 0.25rem; }
|
|
151
|
+
.fms__socials a { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 10px; color: var(--c-text-2, #a3a3a3); transition: color 0.2s ease, background 0.2s ease; }
|
|
152
|
+
.fms__socials a:hover { color: var(--c-text-1, #fff); background: rgba(255, 255, 255, 0.06); }
|
|
153
|
+
@media (max-width: 860px) { .fms__top { grid-template-columns: 1fr; } }
|
|
154
|
+
@media (max-width: 560px) { .fms__bottom { flex-direction: column; align-items: flex-start; } }
|
|
155
|
+
</style>
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* HeroDashboardPreview — SaaS hero with headline, CTAs and a live-rendered
|
|
4
|
+
* product dashboard mockup built from the kit's own SVG charts.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} badge - Eyebrow badge.
|
|
7
|
+
* @param {string} title - Headline.
|
|
8
|
+
* @param {string} subtitle - Supporting paragraph.
|
|
9
|
+
* @param {{label: string, href: string}} primary - Primary CTA.
|
|
10
|
+
* @param {{label: string, href: string}} secondary - Secondary CTA.
|
|
11
|
+
* @param {string} variant - Mockup frame (browser|floating|flat).
|
|
12
|
+
* @param {string} size - Vertical rhythm (sm|md|lg).
|
|
13
|
+
* @param {string} className - Extra CSS class.
|
|
14
|
+
*/
|
|
15
|
+
import LineChart from '../charts/LineChart.astro';
|
|
16
|
+
import KpiStatTile from '../charts/KpiStatTile.astro';
|
|
17
|
+
|
|
18
|
+
interface Props {
|
|
19
|
+
badge?: string;
|
|
20
|
+
title?: string;
|
|
21
|
+
subtitle?: string;
|
|
22
|
+
primary?: { label: string; href: string };
|
|
23
|
+
secondary?: { label: string; href: string };
|
|
24
|
+
variant?: 'browser' | 'floating' | 'flat';
|
|
25
|
+
size?: 'sm' | 'md' | 'lg';
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const {
|
|
30
|
+
badge = 'Analytics, reimagined',
|
|
31
|
+
title = 'See every metric that matters, in real time',
|
|
32
|
+
subtitle = 'Unified revenue, product and infrastructure dashboards. Set up in minutes, no SQL required.',
|
|
33
|
+
primary = { label: 'Start free trial', href: '#' },
|
|
34
|
+
secondary = { label: 'Book a demo', href: '#' },
|
|
35
|
+
variant = 'browser',
|
|
36
|
+
size = 'md',
|
|
37
|
+
className = '',
|
|
38
|
+
} = Astro.props;
|
|
39
|
+
|
|
40
|
+
const id = `hdp-${Math.random().toString(36).slice(2, 8)}`;
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
<section class={`hdp hdp--${variant} hdp--${size} ${className}`} aria-labelledby={id}>
|
|
44
|
+
<div class="hdp__glow" aria-hidden="true"></div>
|
|
45
|
+
<div class="hdp__copy">
|
|
46
|
+
<span class="hdp__badge">{badge}</span>
|
|
47
|
+
<h1 id={id} class="hdp__title">{title}</h1>
|
|
48
|
+
<p class="hdp__subtitle">{subtitle}</p>
|
|
49
|
+
<div class="hdp__actions">
|
|
50
|
+
<a class="hdp__btn hdp__btn--primary" href={primary.href}>{primary.label}</a>
|
|
51
|
+
<a class="hdp__btn hdp__btn--ghost" href={secondary.href}>
|
|
52
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="10" /><path d="m10 8 6 4-6 4V8z" fill="currentColor" /></svg>
|
|
53
|
+
{secondary.label}
|
|
54
|
+
</a>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div class="hdp__mock" role="group" aria-label="Product dashboard preview">
|
|
59
|
+
{variant === 'browser' && (
|
|
60
|
+
<div class="hdp__chrome" aria-hidden="true">
|
|
61
|
+
<span></span><span></span><span></span>
|
|
62
|
+
<p>app.example.com/overview</p>
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
65
|
+
<div class="hdp__screen">
|
|
66
|
+
<div class="hdp__kpis">
|
|
67
|
+
<KpiStatTile label="Revenue" value="$128.4k" change={9.2} period="vs last month" size="sm" variant="solid" trend={[80, 84, 90, 88, 96, 102, 110, 118, 128]} />
|
|
68
|
+
<KpiStatTile label="Active users" value="24,812" change={4.1} period="vs last month" size="sm" variant="solid" trend={[20, 21, 21.5, 22, 22.8, 23.1, 23.9, 24.2, 24.8]} />
|
|
69
|
+
<KpiStatTile label="Churn" value="2.3%" change={-0.6} invert period="vs last month" size="sm" variant="solid" trend={[3.1, 3, 2.9, 2.8, 2.7, 2.6, 2.5, 2.4, 2.3]} />
|
|
70
|
+
</div>
|
|
71
|
+
<LineChart title="Revenue by channel" subtitle="Last 12 weeks" variant="solid" size="sm" height={220} />
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</section>
|
|
75
|
+
|
|
76
|
+
<style>
|
|
77
|
+
.hdp {
|
|
78
|
+
--hdp-py: 5.5rem;
|
|
79
|
+
position: relative;
|
|
80
|
+
overflow: hidden;
|
|
81
|
+
padding: var(--hdp-py) var(--sp-6, 1.5rem) 0;
|
|
82
|
+
background: var(--c-bg, #050505);
|
|
83
|
+
}
|
|
84
|
+
.hdp--sm { --hdp-py: 3.5rem; }
|
|
85
|
+
.hdp--lg { --hdp-py: 7.5rem; }
|
|
86
|
+
.hdp__glow {
|
|
87
|
+
position: absolute;
|
|
88
|
+
top: 30%;
|
|
89
|
+
left: 50%;
|
|
90
|
+
width: 900px;
|
|
91
|
+
height: 600px;
|
|
92
|
+
transform: translateX(-50%);
|
|
93
|
+
background: radial-gradient(ellipse, rgba(57, 135, 229, 0.16), transparent 65%);
|
|
94
|
+
filter: blur(40px);
|
|
95
|
+
pointer-events: none;
|
|
96
|
+
}
|
|
97
|
+
.hdp__copy { position: relative; max-width: 760px; margin: 0 auto 3.5rem; text-align: center; }
|
|
98
|
+
.hdp__badge {
|
|
99
|
+
display: inline-block;
|
|
100
|
+
padding: 0.35rem 0.85rem;
|
|
101
|
+
border-radius: var(--r-full, 999px);
|
|
102
|
+
background: rgba(57, 135, 229, 0.12);
|
|
103
|
+
border: 1px solid rgba(57, 135, 229, 0.3);
|
|
104
|
+
color: #a9cdf7;
|
|
105
|
+
font-size: 0.8125rem;
|
|
106
|
+
font-weight: 600;
|
|
107
|
+
}
|
|
108
|
+
.hdp__title {
|
|
109
|
+
margin: 1.4rem 0 1rem;
|
|
110
|
+
font-size: clamp(2.25rem, 5.5vw, 3.75rem);
|
|
111
|
+
font-weight: 800;
|
|
112
|
+
letter-spacing: -0.035em;
|
|
113
|
+
line-height: 1.06;
|
|
114
|
+
color: var(--c-text-1, #fff);
|
|
115
|
+
text-wrap: balance;
|
|
116
|
+
}
|
|
117
|
+
.hdp__subtitle { margin: 0 auto 2rem; max-width: 560px; font-size: 1.0625rem; line-height: 1.6; color: var(--c-text-2, #a3a3a3); }
|
|
118
|
+
.hdp__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; justify-content: center; }
|
|
119
|
+
.hdp__btn {
|
|
120
|
+
display: inline-flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
gap: 0.5rem;
|
|
123
|
+
min-height: 48px;
|
|
124
|
+
padding: 0 1.5rem;
|
|
125
|
+
border-radius: var(--r-md, 12px);
|
|
126
|
+
font-weight: 650;
|
|
127
|
+
text-decoration: none;
|
|
128
|
+
transition: transform 0.2s ease, background 0.2s ease;
|
|
129
|
+
}
|
|
130
|
+
.hdp__btn:hover { transform: translateY(-1px); }
|
|
131
|
+
.hdp__btn:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 3px; }
|
|
132
|
+
.hdp__btn--primary { background: var(--chart-1, #3987e5); color: #fff; }
|
|
133
|
+
.hdp__btn--primary:hover { background: #5598e7; color: #fff; }
|
|
134
|
+
.hdp__btn--ghost { color: var(--c-text-1, #fff); border: 1px solid rgba(255, 255, 255, 0.14); }
|
|
135
|
+
.hdp__btn--ghost:hover { border-color: rgba(255, 255, 255, 0.3); color: var(--c-text-1, #fff); }
|
|
136
|
+
|
|
137
|
+
.hdp__mock {
|
|
138
|
+
position: relative;
|
|
139
|
+
max-width: 1080px;
|
|
140
|
+
margin: 0 auto;
|
|
141
|
+
border-radius: var(--r-xl, 24px) var(--r-xl, 24px) 0 0;
|
|
142
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
143
|
+
border-bottom: 0;
|
|
144
|
+
background: #0a0a0c;
|
|
145
|
+
overflow: hidden;
|
|
146
|
+
mask-image: linear-gradient(to bottom, #000 70%, transparent);
|
|
147
|
+
}
|
|
148
|
+
.hdp--floating .hdp__mock {
|
|
149
|
+
border-radius: var(--r-xl, 24px);
|
|
150
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
151
|
+
margin-bottom: var(--hdp-py);
|
|
152
|
+
mask-image: none;
|
|
153
|
+
transform: perspective(1600px) rotateX(8deg);
|
|
154
|
+
box-shadow: 0 60px 120px -40px rgba(57, 135, 229, 0.35);
|
|
155
|
+
}
|
|
156
|
+
.hdp--flat .hdp__mock { background: transparent; border-color: transparent; }
|
|
157
|
+
.hdp__chrome {
|
|
158
|
+
display: flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
gap: 0.45rem;
|
|
161
|
+
padding: 0.8rem 1rem;
|
|
162
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
|
163
|
+
}
|
|
164
|
+
.hdp__chrome span { width: 10px; height: 10px; border-radius: 50%; background: rgba(255, 255, 255, 0.12); }
|
|
165
|
+
.hdp__chrome p {
|
|
166
|
+
margin: 0 auto;
|
|
167
|
+
padding: 0.25rem 1rem;
|
|
168
|
+
border-radius: 6px;
|
|
169
|
+
background: rgba(255, 255, 255, 0.04);
|
|
170
|
+
font-size: 0.75rem;
|
|
171
|
+
color: var(--c-text-3, #737373);
|
|
172
|
+
}
|
|
173
|
+
.hdp__screen { display: grid; gap: 1rem; padding: 1.25rem; }
|
|
174
|
+
.hdp__kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
|
|
175
|
+
@media (max-width: 760px) {
|
|
176
|
+
.hdp__kpis { grid-template-columns: 1fr; }
|
|
177
|
+
.hdp__kpis > :global(*:nth-child(n + 2)) { display: none; }
|
|
178
|
+
.hdp--floating .hdp__mock { transform: none; }
|
|
179
|
+
}
|
|
180
|
+
</style>
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* HeroMinimalCentered — Typography-first centered hero with an announcement pill,
|
|
4
|
+
* two CTAs and a row of trust signals. No imagery, loads instantly.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} announcement - Text in the top pill (empty to hide).
|
|
7
|
+
* @param {string} announcementHref - Link for the pill.
|
|
8
|
+
* @param {string} title - Main headline. Wrap a word in *asterisks* to highlight it.
|
|
9
|
+
* @param {string} subtitle - Supporting paragraph.
|
|
10
|
+
* @param {{label: string, href: string}} primary - Primary CTA.
|
|
11
|
+
* @param {{label: string, href: string}} secondary - Secondary CTA.
|
|
12
|
+
* @param {string[]} trust - Short trust signals under the CTAs.
|
|
13
|
+
* @param {string} variant - Background treatment (default|glow|grid).
|
|
14
|
+
* @param {string} size - Vertical rhythm (sm|md|lg).
|
|
15
|
+
* @param {string} className - Extra CSS class.
|
|
16
|
+
*/
|
|
17
|
+
interface Props {
|
|
18
|
+
announcement?: string;
|
|
19
|
+
announcementHref?: string;
|
|
20
|
+
title?: string;
|
|
21
|
+
subtitle?: string;
|
|
22
|
+
primary?: { label: string; href: string };
|
|
23
|
+
secondary?: { label: string; href: string };
|
|
24
|
+
trust?: string[];
|
|
25
|
+
variant?: 'default' | 'glow' | 'grid';
|
|
26
|
+
size?: 'sm' | 'md' | 'lg';
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const {
|
|
31
|
+
announcement = 'New: 50 sections & 45 SVG charts',
|
|
32
|
+
announcementHref = '#',
|
|
33
|
+
title = 'Build landing pages that *feel* expensive',
|
|
34
|
+
subtitle = 'Accessible, zero-dependency Astro components with a dark, refined aesthetic. Copy, paste, ship.',
|
|
35
|
+
primary = { label: 'Browse components', href: '#' },
|
|
36
|
+
secondary = { label: 'Read the docs', href: '#' },
|
|
37
|
+
trust = ['MIT licensed', 'WCAG AA', 'No runtime JS required'],
|
|
38
|
+
variant = 'glow',
|
|
39
|
+
size = 'lg',
|
|
40
|
+
className = '',
|
|
41
|
+
} = Astro.props;
|
|
42
|
+
|
|
43
|
+
const id = `hmc-${Math.random().toString(36).slice(2, 8)}`;
|
|
44
|
+
const parts = title.split(/\*(.+?)\*/);
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
<section class={`hmc hmc--${variant} hmc--${size} ${className}`} aria-labelledby={id}>
|
|
48
|
+
<div class="hmc__bg" aria-hidden="true"></div>
|
|
49
|
+
<div class="hmc__inner">
|
|
50
|
+
{announcement && (
|
|
51
|
+
<a class="hmc__pill" href={announcementHref}>
|
|
52
|
+
<span class="hmc__dot" aria-hidden="true"></span>
|
|
53
|
+
{announcement}
|
|
54
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6" /></svg>
|
|
55
|
+
</a>
|
|
56
|
+
)}
|
|
57
|
+
<h1 id={id} class="hmc__title">
|
|
58
|
+
{parts.map((p, i) => (i % 2 ? <em>{p}</em> : p))}
|
|
59
|
+
</h1>
|
|
60
|
+
<p class="hmc__subtitle">{subtitle}</p>
|
|
61
|
+
<div class="hmc__actions">
|
|
62
|
+
<a class="hmc__btn hmc__btn--primary" href={primary.href}>{primary.label}</a>
|
|
63
|
+
<a class="hmc__btn hmc__btn--ghost" href={secondary.href}>{secondary.label}</a>
|
|
64
|
+
</div>
|
|
65
|
+
{trust.length > 0 && (
|
|
66
|
+
<ul class="hmc__trust">
|
|
67
|
+
{trust.map((t) => (
|
|
68
|
+
<li>
|
|
69
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>
|
|
70
|
+
{t}
|
|
71
|
+
</li>
|
|
72
|
+
))}
|
|
73
|
+
</ul>
|
|
74
|
+
)}
|
|
75
|
+
</div>
|
|
76
|
+
</section>
|
|
77
|
+
|
|
78
|
+
<style>
|
|
79
|
+
.hmc {
|
|
80
|
+
--hmc-py: 6rem;
|
|
81
|
+
position: relative;
|
|
82
|
+
overflow: hidden;
|
|
83
|
+
padding: var(--hmc-py) var(--sp-6, 1.5rem);
|
|
84
|
+
background: var(--c-bg, #050505);
|
|
85
|
+
text-align: center;
|
|
86
|
+
}
|
|
87
|
+
.hmc--sm { --hmc-py: 4rem; }
|
|
88
|
+
.hmc--lg { --hmc-py: 8rem; }
|
|
89
|
+
.hmc__bg { position: absolute; inset: 0; pointer-events: none; }
|
|
90
|
+
.hmc--glow .hmc__bg {
|
|
91
|
+
background:
|
|
92
|
+
radial-gradient(ellipse 60% 50% at 50% 0%, var(--c-primary-glow, rgba(184, 134, 11, 0.14)), transparent 70%),
|
|
93
|
+
radial-gradient(ellipse 40% 30% at 50% 100%, rgba(57, 135, 229, 0.08), transparent 70%);
|
|
94
|
+
}
|
|
95
|
+
.hmc--grid .hmc__bg {
|
|
96
|
+
background-image:
|
|
97
|
+
linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
|
|
98
|
+
linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
|
|
99
|
+
background-size: 48px 48px;
|
|
100
|
+
mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, #000, transparent);
|
|
101
|
+
}
|
|
102
|
+
.hmc__inner { position: relative; max-width: 820px; margin: 0 auto; }
|
|
103
|
+
.hmc__pill {
|
|
104
|
+
display: inline-flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
gap: 0.5rem;
|
|
107
|
+
min-height: 36px;
|
|
108
|
+
padding: 0.35rem 0.9rem;
|
|
109
|
+
border-radius: var(--r-full, 999px);
|
|
110
|
+
border: 1px solid var(--c-border, rgba(255, 255, 255, 0.08));
|
|
111
|
+
background: rgba(255, 255, 255, 0.03);
|
|
112
|
+
color: var(--c-text-2, #a3a3a3);
|
|
113
|
+
font-size: 0.8125rem;
|
|
114
|
+
text-decoration: none;
|
|
115
|
+
transition: border-color 0.2s ease, color 0.2s ease;
|
|
116
|
+
}
|
|
117
|
+
.hmc__pill:hover { border-color: rgba(255, 255, 255, 0.2); color: var(--c-text-1, #fff); }
|
|
118
|
+
.hmc__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--c-primary-light, #d4a017); box-shadow: 0 0 10px var(--c-primary-light, #d4a017); }
|
|
119
|
+
.hmc__title {
|
|
120
|
+
margin: 1.75rem 0 1.25rem;
|
|
121
|
+
font-size: clamp(2.5rem, 6vw, 4.5rem);
|
|
122
|
+
font-weight: 800;
|
|
123
|
+
line-height: 1.04;
|
|
124
|
+
letter-spacing: -0.035em;
|
|
125
|
+
color: var(--c-text-1, #fff);
|
|
126
|
+
text-wrap: balance;
|
|
127
|
+
}
|
|
128
|
+
.hmc__title em {
|
|
129
|
+
font-style: normal;
|
|
130
|
+
background: linear-gradient(120deg, var(--c-accent, #fef3c7), var(--c-primary-light, #d4a017));
|
|
131
|
+
-webkit-background-clip: text;
|
|
132
|
+
background-clip: text;
|
|
133
|
+
color: transparent;
|
|
134
|
+
}
|
|
135
|
+
.hmc__subtitle {
|
|
136
|
+
max-width: 600px;
|
|
137
|
+
margin: 0 auto 2.25rem;
|
|
138
|
+
font-size: clamp(1rem, 2vw, 1.1875rem);
|
|
139
|
+
line-height: 1.6;
|
|
140
|
+
color: var(--c-text-2, #a3a3a3);
|
|
141
|
+
}
|
|
142
|
+
.hmc__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; justify-content: center; }
|
|
143
|
+
.hmc__btn {
|
|
144
|
+
display: inline-flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
justify-content: center;
|
|
147
|
+
min-height: 48px;
|
|
148
|
+
padding: 0 1.5rem;
|
|
149
|
+
border-radius: var(--r-md, 12px);
|
|
150
|
+
font-weight: 650;
|
|
151
|
+
font-size: 0.9375rem;
|
|
152
|
+
text-decoration: none;
|
|
153
|
+
transition: transform 0.2s ease, background 0.2s ease, border-color 0.2s ease;
|
|
154
|
+
}
|
|
155
|
+
.hmc__btn:hover { transform: translateY(-1px); }
|
|
156
|
+
.hmc__btn:focus-visible, .hmc__pill:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 3px; }
|
|
157
|
+
.hmc__btn--primary { background: var(--c-primary-light, #d4a017); color: #0a0a0a; }
|
|
158
|
+
.hmc__btn--primary:hover { background: var(--c-accent, #fef3c7); color: #0a0a0a; }
|
|
159
|
+
.hmc__btn--ghost { border: 1px solid rgba(255, 255, 255, 0.14); color: var(--c-text-1, #fff); }
|
|
160
|
+
.hmc__btn--ghost:hover { border-color: rgba(255, 255, 255, 0.32); color: var(--c-text-1, #fff); }
|
|
161
|
+
.hmc__trust {
|
|
162
|
+
display: flex;
|
|
163
|
+
flex-wrap: wrap;
|
|
164
|
+
justify-content: center;
|
|
165
|
+
gap: 0.75rem 1.75rem;
|
|
166
|
+
margin: 2.5rem 0 0;
|
|
167
|
+
padding: 0;
|
|
168
|
+
list-style: none;
|
|
169
|
+
font-size: 0.875rem;
|
|
170
|
+
color: var(--c-text-2, #a3a3a3);
|
|
171
|
+
}
|
|
172
|
+
.hmc__trust li { display: inline-flex; align-items: center; gap: 0.45rem; }
|
|
173
|
+
.hmc__trust svg { color: var(--chart-pos, #34c38f); }
|
|
174
|
+
@media (prefers-reduced-motion: reduce) { .hmc__btn { transition: none; } }
|
|
175
|
+
</style>
|