astro-component-kit 0.3.1 → 0.4.1
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 +133 -36
- package/package.json +17 -4
- package/src/components/index.ts +18 -202
- package/src/components/lib/Galaxy3D.astro +249 -137
- package/src/components/lib/app/AppSidebar.astro +249 -0
- package/src/components/lib/app/AppTopbar.astro +284 -0
- package/src/components/lib/app/ArrivalsBoard.astro +176 -0
- package/src/components/lib/app/AuthCard.astro +213 -0
- package/src/components/lib/app/DataTable.astro +346 -0
- package/src/components/lib/app/GuestProfileCard.astro +133 -0
- package/src/components/lib/app/HousekeepingBoard.astro +189 -0
- package/src/components/lib/app/PageHeader.astro +157 -0
- package/src/components/lib/app/PlanUsageCard.astro +112 -0
- package/src/components/lib/app/RoomRack.astro +207 -0
- package/src/components/lib/app/SettingsSection.astro +96 -0
- package/src/components/lib/app/SwitchRow.astro +71 -0
- package/src/components/lib/app/TeamMembers.astro +190 -0
- package/src/components/lib/app/app-icons.ts +52 -0
- package/src/components/lib/app/index.ts +19 -0
- 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/AreaChart.astro +4 -4
- package/src/components/lib/charts/BarChart.astro +3 -3
- 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/DonutChart.astro +2 -2
- 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/ecommerce/CartDrawer.astro +483 -0
- package/src/components/lib/ecommerce/CartPageList.astro +290 -0
- package/src/components/lib/ecommerce/CartToast.astro +276 -0
- package/src/components/lib/ecommerce/CategoryTiles.astro +143 -0
- package/src/components/lib/ecommerce/CheckoutForm.astro +423 -0
- package/src/components/lib/ecommerce/CountdownBanner.astro +230 -0
- package/src/components/lib/ecommerce/FilterBar.astro +278 -0
- package/src/components/lib/ecommerce/FilterSidebar.astro +405 -0
- package/src/components/lib/ecommerce/LiveActivityToast.astro +213 -0
- package/src/components/lib/ecommerce/OrderSummary.astro +295 -0
- package/src/components/lib/ecommerce/ProductBuyBox.astro +247 -0
- package/src/components/lib/ecommerce/ProductCardMinimal.astro +229 -0
- package/src/components/lib/ecommerce/ProductGallery.astro +145 -0
- package/src/components/lib/ecommerce/ProductGrid.astro +118 -0
- package/src/components/lib/ecommerce/ProductMedia.astro +113 -0
- package/src/components/lib/ecommerce/ProductRating.astro +78 -0
- package/src/components/lib/ecommerce/ProductToolbar.astro +93 -0
- package/src/components/lib/ecommerce/PromoBar.astro +145 -0
- package/src/components/lib/ecommerce/StockIndicator.astro +127 -0
- package/src/components/lib/ecommerce/StoreHeader.astro +446 -0
- package/src/components/lib/ecommerce/StoreHero.astro +260 -0
- package/src/components/lib/ecommerce/StoreProductCard.astro +307 -0
- package/src/components/lib/ecommerce/TrustBadges.astro +101 -0
- package/src/components/lib/ecommerce/VariantPicker.astro +145 -0
- package/src/components/lib/ecommerce/cart-store.ts +151 -0
- package/src/components/lib/ecommerce/catalog-filter.ts +62 -0
- package/src/components/lib/ecommerce/index.ts +34 -0
- package/src/components/lib/ecommerce/product-icons.ts +28 -0
- package/src/components/lib/ecommerce/types.ts +70 -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/AnimatedInput.astro +4 -2
- package/src/components/lib/forms/CustomRadioGroup.astro +3 -1
- 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/index.ts +2 -0
- package/src/components/lib/layout/BentoGrid3.astro +6 -4
- package/src/components/lib/layout/CenterFixedBox.astro +2 -2
- package/src/components/lib/layout/CenteredContainer.astro +4 -2
- package/src/components/lib/layout/ClusterHorizontal.astro +2 -2
- package/src/components/lib/layout/DiagonalSectionDivider.astro +69 -0
- package/src/components/lib/layout/FeatureHero.astro +4 -2
- package/src/components/lib/layout/FooterCenteredMinimal.astro +4 -2
- package/src/components/lib/layout/FullBleedSection.astro +2 -2
- package/src/components/lib/layout/GalleryGrid4.astro +2 -2
- package/src/components/lib/layout/HolyGrailGrid.astro +127 -0
- package/src/components/lib/layout/LandingSectionSplit.astro +5 -3
- package/src/components/lib/layout/MasonryGrid.astro +2 -2
- package/src/components/lib/layout/MinimalFooterGrid.astro +1 -1
- package/src/components/lib/layout/ScrollSnapSection.astro +1 -1
- package/src/components/lib/layout/SidebarLayoutWrapper.astro +4 -2
- package/src/components/lib/layout/SplitScreenLayout.astro +3 -3
- package/src/components/lib/layout/StepLayoutVertical.astro +1 -1
- package/src/components/lib/layout/StickySidebarWrapper.astro +4 -2
- 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/AgencyContactBrief.astro +194 -0
- package/src/components/lib/sections/AgencyFooterCta.astro +94 -0
- package/src/components/lib/sections/AgencyHeader.astro +161 -0
- package/src/components/lib/sections/AgencyHeroKinetic.astro +172 -0
- package/src/components/lib/sections/AgencyServicesList.astro +113 -0
- package/src/components/lib/sections/AgencyTeamGrid.astro +111 -0
- package/src/components/lib/sections/AgencyWorkGrid.astro +147 -0
- package/src/components/lib/sections/BlogGridSection.astro +133 -0
- package/src/components/lib/sections/ButtonsShowcase.astro +20 -18
- package/src/components/lib/sections/CardsShowcase.astro +28 -26
- package/src/components/lib/sections/CareersOpenings.astro +141 -0
- package/src/components/lib/sections/ChangelogSection.astro +151 -0
- package/src/components/lib/sections/ContactGlassForm.astro +10 -8
- package/src/components/lib/sections/ContactSplitMap.astro +141 -0
- package/src/components/lib/sections/CtaAppDownload.astro +13 -11
- package/src/components/lib/sections/CtaGlowBanner.astro +12 -10
- package/src/components/lib/sections/CtaNewsletterSection.astro +165 -0
- package/src/components/lib/sections/CtaSplitImage.astro +149 -0
- package/src/components/lib/sections/DataShowcase.astro +23 -21
- package/src/components/lib/sections/FaqAccordionSection.astro +8 -8
- package/src/components/lib/sections/FaqTwoColumn.astro +121 -0
- package/src/components/lib/sections/FeatureAlternatingRows.astro +192 -0
- package/src/components/lib/sections/FeatureBentoGrid.astro +13 -11
- package/src/components/lib/sections/FeatureIconGrid.astro +155 -0
- package/src/components/lib/sections/FeatureTabsShowcase.astro +182 -0
- package/src/components/lib/sections/FeatureTimelineFlow.astro +8 -6
- package/src/components/lib/sections/FeedbackShowcase.astro +15 -13
- package/src/components/lib/sections/FooterMegaSection.astro +157 -0
- package/src/components/lib/sections/FormsShowcase.astro +22 -20
- package/src/components/lib/sections/HeroDashboardPreview.astro +182 -0
- package/src/components/lib/sections/HeroGlass.astro +22 -20
- package/src/components/lib/sections/HeroGradient.astro +15 -13
- package/src/components/lib/sections/HeroMinimalCentered.astro +175 -0
- package/src/components/lib/sections/HeroShowcaseSplit.astro +306 -0
- package/src/components/lib/sections/HeroSplit.astro +13 -11
- package/src/components/lib/sections/HeroTerminal.astro +253 -0
- package/src/components/lib/sections/HeroWaitlist.astro +231 -0
- package/src/components/lib/sections/HowItWorksSteps.astro +180 -0
- package/src/components/lib/sections/IntegrationsGrid.astro +167 -0
- package/src/components/lib/sections/LayoutShowcase.astro +21 -19
- package/src/components/lib/sections/LogoCloudSection.astro +96 -0
- package/src/components/lib/sections/LogoWallGrid.astro +93 -0
- package/src/components/lib/sections/NavigationShowcase.astro +15 -13
- package/src/components/lib/sections/OverlaysShowcase.astro +21 -19
- package/src/components/lib/sections/PricingComparisonMatrix.astro +15 -13
- package/src/components/lib/sections/PricingSinglePlan.astro +159 -0
- package/src/components/lib/sections/PricingTierCards.astro +11 -9
- package/src/components/lib/sections/PricingToggleCards.astro +171 -0
- package/src/components/lib/sections/ShopCategoryHero.astro +103 -0
- package/src/components/lib/sections/ShopCollectionMosaic.astro +131 -0
- package/src/components/lib/sections/ShopFooterWordmark.astro +100 -0
- package/src/components/lib/sections/ShopHeaderEditorial.astro +396 -0
- package/src/components/lib/sections/ShopHeroEditorial.astro +151 -0
- package/src/components/lib/sections/ShopLookbook.astro +250 -0
- package/src/components/lib/sections/ShopNewsletterEditorial.astro +128 -0
- package/src/components/lib/sections/ShopProductRail.astro +150 -0
- package/src/components/lib/sections/ShopReviewsEditorial.astro +133 -0
- package/src/components/lib/sections/ShopValuesMarquee.astro +91 -0
- package/src/components/lib/sections/StatsCounterBand.astro +124 -0
- package/src/components/lib/sections/StatsDashboardSection.astro +85 -0
- package/src/components/lib/sections/StatsMetricShowcase.astro +9 -7
- package/src/components/lib/sections/TeamGridSection.astro +12 -10
- package/src/components/lib/sections/TestimonialCarousel.astro +167 -0
- package/src/components/lib/sections/TestimonialFeatured.astro +122 -0
- package/src/components/lib/sections/TestimonialGridSection.astro +188 -0
- package/src/components/lib/sections/TestimonialWallGlass.astro +11 -9
- package/src/components/lib/sections/TypographyShowcase.astro +10 -8
- package/src/components/lib/sections/index.ts +39 -0
- package/src/components/lib/templates/ecommerce/StoreCategoryPage.astro +160 -0
- package/src/components/lib/templates/ecommerce/StoreCheckoutPage.astro +98 -0
- package/src/components/lib/templates/ecommerce/StoreHomePage.astro +191 -0
- package/src/components/lib/templates/ecommerce/StoreLayout.astro +169 -0
- package/src/components/lib/templates/ecommerce/StoreProductPage.astro +165 -0
- package/src/components/lib/templates/ecommerce/data.ts +187 -0
- package/src/components/lib/templates/ecommerce/index.ts +14 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialBagPage.astro +52 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialCheckoutPage.astro +123 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialHomePage.astro +102 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialLayout.astro +216 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialProductPage.astro +205 -0
- package/src/components/lib/templates/ecommerce-editorial/EditorialShopPage.astro +112 -0
- package/src/components/lib/templates/ecommerce-editorial/data.ts +125 -0
- package/src/components/lib/templates/ecommerce-editorial/index.ts +16 -0
- package/src/components/lib/templates/saas-hotel/AppLayout.astro +83 -0
- package/src/components/lib/templates/saas-hotel/DashboardPage.astro +66 -0
- package/src/components/lib/templates/saas-hotel/GuestsPage.astro +65 -0
- package/src/components/lib/templates/saas-hotel/LandingPage.astro +213 -0
- package/src/components/lib/templates/saas-hotel/ReportsPage.astro +63 -0
- package/src/components/lib/templates/saas-hotel/ReservationsPage.astro +49 -0
- package/src/components/lib/templates/saas-hotel/RoomsPage.astro +48 -0
- package/src/components/lib/templates/saas-hotel/SettingsPage.astro +115 -0
- package/src/components/lib/templates/saas-hotel/SignInPage.astro +50 -0
- package/src/components/lib/templates/saas-hotel/data.ts +229 -0
- package/src/components/lib/templates/saas-hotel/index.ts +19 -0
- package/src/components/lib/templates/saas-hotel/lobby-theme.css +90 -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 +113 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* FeatureIconGrid — Classic 3-column feature grid with SVG icons, titles,
|
|
4
|
+
* descriptions and optional "learn more" links. Cards light up on hover/focus.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} eyebrow - Small label above the heading.
|
|
7
|
+
* @param {string} title - Section heading.
|
|
8
|
+
* @param {string} subtitle - Section description.
|
|
9
|
+
* @param {Array<{icon: string, title: string, text: string, href?: string}>} features - Feature cards.
|
|
10
|
+
* `icon` is one of: bolt, shield, layers, chart, globe, code, sparkles, lock, users.
|
|
11
|
+
* @param {number} columns - Max columns on desktop (2|3|4).
|
|
12
|
+
* @param {string} variant - Card style (card|plain|bordered).
|
|
13
|
+
* @param {string} size - Vertical rhythm (sm|md|lg).
|
|
14
|
+
* @param {string} className - Extra CSS class.
|
|
15
|
+
*/
|
|
16
|
+
interface Feature { icon: string; title: string; text: string; href?: string }
|
|
17
|
+
interface Props {
|
|
18
|
+
eyebrow?: string;
|
|
19
|
+
title?: string;
|
|
20
|
+
subtitle?: string;
|
|
21
|
+
features?: Feature[];
|
|
22
|
+
columns?: 2 | 3 | 4;
|
|
23
|
+
variant?: 'card' | 'plain' | 'bordered';
|
|
24
|
+
size?: 'sm' | 'md' | 'lg';
|
|
25
|
+
className?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const icons: Record<string, string> = {
|
|
29
|
+
bolt: '<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>',
|
|
30
|
+
shield: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="m9 12 2 2 4-4"/>',
|
|
31
|
+
layers: '<path d="m12 2 10 5-10 5L2 7l10-5z"/><path d="m2 17 10 5 10-5"/><path d="m2 12 10 5 10-5"/>',
|
|
32
|
+
chart: '<path d="M3 3v18h18"/><path d="m19 9-5 5-4-4-3 3"/>',
|
|
33
|
+
globe: '<circle cx="12" cy="12" r="10"/><path d="M2 12h20M12 2a15 15 0 0 1 0 20 15 15 0 0 1 0-20z"/>',
|
|
34
|
+
code: '<path d="m16 18 6-6-6-6M8 6l-6 6 6 6"/>',
|
|
35
|
+
sparkles: '<path d="M12 3l1.9 5.8L20 10l-6.1 1.2L12 17l-1.9-5.8L4 10l6.1-1.2z"/><path d="M19 17v4M17 19h4"/>',
|
|
36
|
+
lock: '<rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
|
|
37
|
+
users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/>',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const {
|
|
41
|
+
eyebrow = 'Features',
|
|
42
|
+
title = 'Everything you need, nothing you don’t',
|
|
43
|
+
subtitle = 'A focused toolkit that keeps your pages fast, accessible and on-brand.',
|
|
44
|
+
features = [
|
|
45
|
+
{ icon: 'bolt', title: 'Zero runtime JS', text: 'Components render to static HTML and CSS. Interactivity is progressive and tiny.', href: '#' },
|
|
46
|
+
{ icon: 'shield', title: 'Accessible by default', text: 'Semantic markup, focus rings, ARIA where it matters and 4.5:1 contrast everywhere.', href: '#' },
|
|
47
|
+
{ icon: 'layers', title: 'Design tokens', text: 'Colors, spacing and radii come from CSS custom properties you can re-theme in one file.' },
|
|
48
|
+
{ icon: 'chart', title: 'SVG charts', text: '45 dependency-free charts with tooltips, legends and data-table fallbacks.' },
|
|
49
|
+
{ icon: 'globe', title: 'i18n ready', text: 'Every string is a prop. Ship English, Spanish and Russian docs out of the box.' },
|
|
50
|
+
{ icon: 'code', title: 'Copy & paste', text: 'No package lock-in. Grab the source from the docs and own every line.' },
|
|
51
|
+
],
|
|
52
|
+
columns = 3,
|
|
53
|
+
variant = 'card',
|
|
54
|
+
size = 'md',
|
|
55
|
+
className = '',
|
|
56
|
+
} = Astro.props;
|
|
57
|
+
|
|
58
|
+
const id = `fig-${Math.random().toString(36).slice(2, 8)}`;
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
<section class={`fig fig--${variant} fig--${size} ${className}`} aria-labelledby={id} style={`--fig-cols:${columns}`}>
|
|
62
|
+
<div class="fig__inner">
|
|
63
|
+
<header class="fig__head">
|
|
64
|
+
<p class="fig__eyebrow">{eyebrow}</p>
|
|
65
|
+
<h2 id={id} class="fig__title">{title}</h2>
|
|
66
|
+
<p class="fig__subtitle">{subtitle}</p>
|
|
67
|
+
</header>
|
|
68
|
+
<ul class="fig__grid">
|
|
69
|
+
{features.map((f) => (
|
|
70
|
+
<li class="fig__card">
|
|
71
|
+
<span class="fig__icon" aria-hidden="true">
|
|
72
|
+
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" set:html={icons[f.icon] ?? icons.sparkles}></svg>
|
|
73
|
+
</span>
|
|
74
|
+
<h3 class="fig__card-title">{f.title}</h3>
|
|
75
|
+
<p class="fig__text">{f.text}</p>
|
|
76
|
+
{f.href && (
|
|
77
|
+
<a class="fig__link" href={f.href}>
|
|
78
|
+
Learn more<span class="fig__sr"> about {f.title}</span>
|
|
79
|
+
<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>
|
|
80
|
+
</a>
|
|
81
|
+
)}
|
|
82
|
+
</li>
|
|
83
|
+
))}
|
|
84
|
+
</ul>
|
|
85
|
+
</div>
|
|
86
|
+
</section>
|
|
87
|
+
|
|
88
|
+
<style>
|
|
89
|
+
.fig {
|
|
90
|
+
--fig-py: 5.5rem;
|
|
91
|
+
padding: var(--fig-py) var(--sp-6, 1.5rem);
|
|
92
|
+
background: var(--c-bg, #050505);
|
|
93
|
+
}
|
|
94
|
+
.fig--sm { --fig-py: 3.5rem; }
|
|
95
|
+
.fig--lg { --fig-py: 7.5rem; }
|
|
96
|
+
.fig__inner { max-width: 1180px; margin: 0 auto; }
|
|
97
|
+
.fig__head { max-width: 640px; margin: 0 auto 3.5rem; text-align: center; }
|
|
98
|
+
.fig__eyebrow { margin: 0 0 0.75rem; font-size: 0.8125rem; font-weight: 650; letter-spacing: 0.08em; text-transform: uppercase; color: var(--c-primary-light, #d4a017); }
|
|
99
|
+
.fig__title { margin: 0 0 1rem; font-size: clamp(1.9rem, 4vw, 2.75rem); font-weight: 800; letter-spacing: -0.03em; line-height: 1.12; color: var(--c-text-1, #fff); text-wrap: balance; }
|
|
100
|
+
.fig__subtitle { margin: 0; font-size: 1.0625rem; line-height: 1.6; color: var(--c-text-2, #a3a3a3); }
|
|
101
|
+
.fig__grid {
|
|
102
|
+
list-style: none;
|
|
103
|
+
margin: 0;
|
|
104
|
+
padding: 0;
|
|
105
|
+
display: grid;
|
|
106
|
+
grid-template-columns: repeat(auto-fill, minmax(min(100%, calc((100% - (var(--fig-cols) - 1) * 1.25rem) / var(--fig-cols))), 1fr));
|
|
107
|
+
gap: 1.25rem;
|
|
108
|
+
}
|
|
109
|
+
.fig__card {
|
|
110
|
+
position: relative;
|
|
111
|
+
padding: 1.75rem;
|
|
112
|
+
border-radius: var(--r-lg, 20px);
|
|
113
|
+
transition: border-color 0.25s ease, background 0.25s ease, transform 0.25s ease;
|
|
114
|
+
}
|
|
115
|
+
.fig--card .fig__card {
|
|
116
|
+
background: linear-gradient(160deg, rgb(var(--ink-rgb, 255 255 255) / 0.04), rgb(var(--ink-rgb, 255 255 255) / 0.01));
|
|
117
|
+
border: 1px solid var(--c-border, rgb(var(--ink-rgb, 255 255 255) / 0.07));
|
|
118
|
+
}
|
|
119
|
+
.fig--bordered .fig__card { border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.1); }
|
|
120
|
+
.fig--plain .fig__card { padding: 0.5rem 0; }
|
|
121
|
+
.fig--card .fig__card:hover, .fig--card .fig__card:focus-within,
|
|
122
|
+
.fig--bordered .fig__card:hover, .fig--bordered .fig__card:focus-within {
|
|
123
|
+
border-color: color-mix(in srgb, var(--c-primary-light, #d4a017) 35%, transparent);
|
|
124
|
+
transform: translateY(-3px);
|
|
125
|
+
}
|
|
126
|
+
.fig__icon {
|
|
127
|
+
display: grid;
|
|
128
|
+
place-items: center;
|
|
129
|
+
width: 46px;
|
|
130
|
+
height: 46px;
|
|
131
|
+
margin-bottom: 1.25rem;
|
|
132
|
+
border-radius: var(--r-md, 12px);
|
|
133
|
+
background: var(--c-primary-glow, color-mix(in srgb, var(--c-primary, #b8860b) 12%, transparent));
|
|
134
|
+
border: 1px solid color-mix(in srgb, var(--c-primary-light, #d4a017) 25%, transparent);
|
|
135
|
+
color: var(--c-primary-light, #d4a017);
|
|
136
|
+
}
|
|
137
|
+
.fig__card-title { margin: 0 0 0.5rem; font-size: 1.125rem; font-weight: 650; color: var(--c-text-1, #fff); letter-spacing: -0.01em; }
|
|
138
|
+
.fig__text { margin: 0; font-size: 0.9375rem; line-height: 1.6; color: var(--c-text-2, #a3a3a3); }
|
|
139
|
+
.fig__link {
|
|
140
|
+
display: inline-flex;
|
|
141
|
+
align-items: center;
|
|
142
|
+
gap: 0.35rem;
|
|
143
|
+
min-height: 44px;
|
|
144
|
+
margin-top: 0.5rem;
|
|
145
|
+
font-size: 0.875rem;
|
|
146
|
+
font-weight: 600;
|
|
147
|
+
color: var(--c-primary-light, #d4a017);
|
|
148
|
+
text-decoration: none;
|
|
149
|
+
}
|
|
150
|
+
.fig__link svg { transition: transform 0.2s ease; }
|
|
151
|
+
.fig__link:hover svg { transform: translateX(3px); }
|
|
152
|
+
.fig__link:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 2px; border-radius: 4px; }
|
|
153
|
+
.fig__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
154
|
+
@media (prefers-reduced-motion: reduce) { .fig__card, .fig__link svg { transition: none; } }
|
|
155
|
+
</style>
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* FeatureTabsShowcase — Interactive feature section using the WAI-ARIA tabs
|
|
4
|
+
* pattern (arrow keys, Home/End) to switch between product capabilities.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} title - Section heading.
|
|
7
|
+
* @param {string} subtitle - Section description.
|
|
8
|
+
* @param {Array<{label: string, title: string, text: string, points: string[], stat: string, statLabel: string}>} tabs - Tab panels.
|
|
9
|
+
* @param {string} variant - Tab style (pills|underline|cards).
|
|
10
|
+
* @param {string} size - Vertical rhythm (sm|md|lg).
|
|
11
|
+
* @param {string} className - Extra CSS class.
|
|
12
|
+
*/
|
|
13
|
+
interface Tab { label: string; title: string; text: string; points: string[]; stat: string; statLabel: string }
|
|
14
|
+
interface Props {
|
|
15
|
+
title?: string;
|
|
16
|
+
subtitle?: string;
|
|
17
|
+
tabs?: Tab[];
|
|
18
|
+
variant?: 'pills' | 'underline' | 'cards';
|
|
19
|
+
size?: 'sm' | 'md' | 'lg';
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const {
|
|
24
|
+
title = 'One platform, every workflow',
|
|
25
|
+
subtitle = 'Switch between capabilities to see how teams use the kit.',
|
|
26
|
+
tabs = [
|
|
27
|
+
{ label: 'Marketing', title: 'Launch pages in an afternoon', text: 'Assemble hero, features, pricing and FAQ sections into conversion-ready landing pages.', points: ['24 new section blocks', 'SEO-friendly markup', 'Instant static builds'], stat: '3.4×', statLabel: 'faster page launches' },
|
|
28
|
+
{ label: 'Product', title: 'In-app analytics without a chart library', text: 'Render KPI tiles, funnels and cohort tables straight from your data at build time.', points: ['45 SVG charts', 'Tooltips & table view', 'Zero client JS'], stat: '0 kB', statLabel: 'chart runtime shipped' },
|
|
29
|
+
{ label: 'Engineering', title: 'Accessible components you can trust', text: 'Every component is keyboard navigable and screen-reader tested, with visible focus states.', points: ['WCAG 2.2 AA', 'Typed props', 'Reduced-motion aware'], stat: '100', statLabel: 'Lighthouse accessibility' },
|
|
30
|
+
],
|
|
31
|
+
variant = 'pills',
|
|
32
|
+
size = 'md',
|
|
33
|
+
className = '',
|
|
34
|
+
} = Astro.props;
|
|
35
|
+
|
|
36
|
+
const uid = Math.random().toString(36).slice(2, 8);
|
|
37
|
+
const id = `fts-${uid}`;
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
<div class="cq-feature-tabs-showcase-cq">
|
|
41
|
+
<section class={`fts fts--${variant} fts--${size} ${className}`} aria-labelledby={id}>
|
|
42
|
+
<div class="fts__inner">
|
|
43
|
+
<header class="fts__head">
|
|
44
|
+
<h2 id={id} class="fts__title">{title}</h2>
|
|
45
|
+
<p class="fts__subtitle">{subtitle}</p>
|
|
46
|
+
</header>
|
|
47
|
+
|
|
48
|
+
<div class="fts__tabs" data-fts>
|
|
49
|
+
<div class="fts__list" role="tablist" aria-label={title}>
|
|
50
|
+
{tabs.map((t, i) => (
|
|
51
|
+
<button
|
|
52
|
+
type="button"
|
|
53
|
+
role="tab"
|
|
54
|
+
class="fts__tab"
|
|
55
|
+
id={`${id}-tab-${i}`}
|
|
56
|
+
aria-controls={`${id}-panel-${i}`}
|
|
57
|
+
aria-selected={i === 0 ? 'true' : 'false'}
|
|
58
|
+
tabindex={i === 0 ? 0 : -1}
|
|
59
|
+
>{t.label}</button>
|
|
60
|
+
))}
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
{tabs.map((t, i) => (
|
|
64
|
+
<div class="fts__panel" role="tabpanel" id={`${id}-panel-${i}`} aria-labelledby={`${id}-tab-${i}`} tabindex="0" hidden={i !== 0}>
|
|
65
|
+
<div class="fts__copy">
|
|
66
|
+
<h3 class="fts__panel-title">{t.title}</h3>
|
|
67
|
+
<p class="fts__text">{t.text}</p>
|
|
68
|
+
<ul class="fts__points">
|
|
69
|
+
{t.points.map((p) => (
|
|
70
|
+
<li><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>{p}</li>
|
|
71
|
+
))}
|
|
72
|
+
</ul>
|
|
73
|
+
</div>
|
|
74
|
+
<div class="fts__stat">
|
|
75
|
+
<span class="fts__stat-value">{t.stat}</span>
|
|
76
|
+
<span class="fts__stat-label">{t.statLabel}</span>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
))}
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</section>
|
|
83
|
+
</div>
|
|
84
|
+
<script>
|
|
85
|
+
document.querySelectorAll<HTMLElement>('[data-fts]').forEach((root) => {
|
|
86
|
+
const tabs = Array.from(root.querySelectorAll<HTMLButtonElement>('[role="tab"]'));
|
|
87
|
+
const select = (next: HTMLButtonElement, focus = true) => {
|
|
88
|
+
tabs.forEach((t) => {
|
|
89
|
+
const on = t === next;
|
|
90
|
+
t.setAttribute('aria-selected', String(on));
|
|
91
|
+
t.tabIndex = on ? 0 : -1;
|
|
92
|
+
const panel = document.getElementById(t.getAttribute('aria-controls') || '');
|
|
93
|
+
if (panel) panel.hidden = !on;
|
|
94
|
+
});
|
|
95
|
+
if (focus) next.focus();
|
|
96
|
+
};
|
|
97
|
+
tabs.forEach((tab, i) => {
|
|
98
|
+
tab.addEventListener('click', () => select(tab, false));
|
|
99
|
+
tab.addEventListener('keydown', (e) => {
|
|
100
|
+
const map: Record<string, number> = { ArrowRight: i + 1, ArrowLeft: i - 1, Home: 0, End: tabs.length - 1 };
|
|
101
|
+
if (!(e.key in map)) return;
|
|
102
|
+
e.preventDefault();
|
|
103
|
+
select(tabs[(map[e.key] + tabs.length) % tabs.length]);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
<style>
|
|
110
|
+
.cq-feature-tabs-showcase-cq { container-type: inline-size; }
|
|
111
|
+
.fts {
|
|
112
|
+
--fts-py: 5.5rem;
|
|
113
|
+
padding: var(--fts-py) var(--sp-6, 1.5rem);
|
|
114
|
+
background: var(--c-bg, #050505);
|
|
115
|
+
}
|
|
116
|
+
.fts--sm { --fts-py: 3.5rem; }
|
|
117
|
+
.fts--lg { --fts-py: 7.5rem; }
|
|
118
|
+
.fts__inner { max-width: 1080px; margin: 0 auto; }
|
|
119
|
+
.fts__head { text-align: center; max-width: 640px; margin: 0 auto 2.5rem; }
|
|
120
|
+
.fts__title { margin: 0 0 0.75rem; font-size: clamp(1.9rem, 4vw, 2.75rem); font-weight: 800; letter-spacing: -0.03em; color: var(--c-text-1, #fff); }
|
|
121
|
+
.fts__subtitle { margin: 0; font-size: 1.0625rem; color: var(--c-text-2, #a3a3a3); }
|
|
122
|
+
.fts__list { display: flex; justify-content: center; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 2rem; }
|
|
123
|
+
.fts__tab {
|
|
124
|
+
min-height: 44px;
|
|
125
|
+
padding: 0 1.25rem;
|
|
126
|
+
border: 1px solid transparent;
|
|
127
|
+
border-radius: var(--r-full, 999px);
|
|
128
|
+
background: transparent;
|
|
129
|
+
color: var(--c-text-2, #a3a3a3);
|
|
130
|
+
font: inherit;
|
|
131
|
+
font-size: 0.9375rem;
|
|
132
|
+
font-weight: 600;
|
|
133
|
+
cursor: pointer;
|
|
134
|
+
transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
|
|
135
|
+
}
|
|
136
|
+
.fts__tab:hover { color: var(--c-text-1, #fff); }
|
|
137
|
+
.fts__tab:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 2px; }
|
|
138
|
+
.fts--pills .fts__list { width: fit-content; margin-inline: auto; padding: 0.35rem; border-radius: var(--r-full, 999px); background: rgb(var(--ink-rgb, 255 255 255) / 0.04); border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.07); }
|
|
139
|
+
.fts--pills .fts__tab[aria-selected='true'] { background: var(--c-text-1, #fff); color: var(--c-on-primary, #0a0a0a); }
|
|
140
|
+
.fts--underline .fts__list { border-bottom: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08); gap: 1.5rem; }
|
|
141
|
+
.fts--underline .fts__tab { border-radius: 0; padding: 0 0.25rem; border-bottom: 2px solid transparent; margin-bottom: -1px; }
|
|
142
|
+
.fts--underline .fts__tab[aria-selected='true'] { color: var(--c-text-1, #fff); border-bottom-color: var(--c-primary-light, #d4a017); }
|
|
143
|
+
.fts--cards .fts__tab { border-radius: var(--r-md, 12px); border-color: rgb(var(--ink-rgb, 255 255 255) / 0.08); }
|
|
144
|
+
.fts--cards .fts__tab[aria-selected='true'] { border-color: var(--c-primary-light, #d4a017); color: var(--c-text-1, #fff); background: var(--c-primary-glow, color-mix(in srgb, var(--c-primary, #b8860b) 12%, transparent)); }
|
|
145
|
+
|
|
146
|
+
.fts__panel {
|
|
147
|
+
display: grid;
|
|
148
|
+
grid-template-columns: 1.4fr 1fr;
|
|
149
|
+
gap: 2rem;
|
|
150
|
+
align-items: center;
|
|
151
|
+
padding: clamp(1.5rem, 4vw, 3rem);
|
|
152
|
+
border-radius: var(--r-xl, 24px);
|
|
153
|
+
background: linear-gradient(160deg, rgb(var(--ink-rgb, 255 255 255) / 0.045), rgb(var(--ink-rgb, 255 255 255) / 0.01));
|
|
154
|
+
border: 1px solid var(--c-border, rgb(var(--ink-rgb, 255 255 255) / 0.07));
|
|
155
|
+
animation: fts-in 0.35s ease;
|
|
156
|
+
}
|
|
157
|
+
.fts__panel[hidden] { display: none; }
|
|
158
|
+
.fts__panel:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 3px; }
|
|
159
|
+
@keyframes fts-in { from { opacity: 0; transform: translateY(6px); } }
|
|
160
|
+
.fts__panel-title { margin: 0 0 0.75rem; font-size: clamp(1.4rem, 3vw, 1.875rem); font-weight: 750; letter-spacing: -0.02em; color: var(--c-text-1, #fff); }
|
|
161
|
+
.fts__text { margin: 0 0 1.25rem; line-height: 1.65; color: var(--c-text-2, #a3a3a3); }
|
|
162
|
+
.fts__points { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
|
|
163
|
+
.fts__points li { display: flex; align-items: center; gap: 0.55rem; color: var(--c-text-1, #fff); font-size: 0.9375rem; }
|
|
164
|
+
.fts__points svg { color: var(--chart-pos, #34c38f); }
|
|
165
|
+
.fts__stat {
|
|
166
|
+
display: flex;
|
|
167
|
+
flex-direction: column;
|
|
168
|
+
align-items: center;
|
|
169
|
+
justify-content: center;
|
|
170
|
+
gap: 0.5rem;
|
|
171
|
+
min-height: 200px;
|
|
172
|
+
border-radius: var(--r-lg, 20px);
|
|
173
|
+
background: radial-gradient(circle at 50% 30%, var(--c-primary-glow, color-mix(in srgb, var(--c-primary, #b8860b) 16%, transparent)), transparent 70%), rgb(var(--ink-rgb, 255 255 255) / 0.02);
|
|
174
|
+
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.06);
|
|
175
|
+
text-align: center;
|
|
176
|
+
padding: 1.5rem;
|
|
177
|
+
}
|
|
178
|
+
.fts__stat-value { font-size: clamp(2.75rem, 6vw, 4rem); font-weight: 800; letter-spacing: -0.04em; color: var(--c-text-1, #fff); font-variant-numeric: tabular-nums; line-height: 1; }
|
|
179
|
+
.fts__stat-label { font-size: 0.875rem; color: var(--c-text-2, #a3a3a3); }
|
|
180
|
+
@container (max-width: 760px) { .fts__panel { grid-template-columns: 1fr; } }
|
|
181
|
+
@media (prefers-reduced-motion: reduce) { .fts__panel { animation: none; } }
|
|
182
|
+
</style>
|
|
@@ -48,6 +48,7 @@ const steps = [
|
|
|
48
48
|
];
|
|
49
49
|
---
|
|
50
50
|
|
|
51
|
+
<div class="cq-feature-timeline-flow-cq">
|
|
51
52
|
<section class={`timeline-section ${className}`} aria-labelledby="timeline-title">
|
|
52
53
|
<div class="timeline-bg" aria-hidden="true">
|
|
53
54
|
<div class="timeline-glow"></div>
|
|
@@ -83,8 +84,9 @@ const steps = [
|
|
|
83
84
|
</div>
|
|
84
85
|
</div>
|
|
85
86
|
</section>
|
|
86
|
-
|
|
87
|
+
</div>
|
|
87
88
|
<style>
|
|
89
|
+
.cq-feature-timeline-flow-cq { container-type: inline-size; }
|
|
88
90
|
.timeline-section {
|
|
89
91
|
position: relative;
|
|
90
92
|
padding: var(--sp-20, 5rem) var(--sp-6, 1.5rem);
|
|
@@ -131,7 +133,7 @@ const steps = [
|
|
|
131
133
|
font-weight: 700;
|
|
132
134
|
letter-spacing: 0.06em;
|
|
133
135
|
text-transform: uppercase;
|
|
134
|
-
background:
|
|
136
|
+
background: color-mix(in srgb, var(--c-primary, #b8860b) 12%, transparent);
|
|
135
137
|
color: #eab308;
|
|
136
138
|
border: 1px solid rgba(234, 179, 8, 0.25);
|
|
137
139
|
margin-bottom: var(--sp-4, 1rem);
|
|
@@ -199,7 +201,7 @@ const steps = [
|
|
|
199
201
|
flex: 1;
|
|
200
202
|
background: rgba(15, 23, 42, 0.6);
|
|
201
203
|
backdrop-filter: blur(20px);
|
|
202
|
-
border: 1px solid
|
|
204
|
+
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
|
|
203
205
|
border-radius: 20px;
|
|
204
206
|
padding: 2rem;
|
|
205
207
|
transition: transform 0.3s ease, border-color 0.3s ease;
|
|
@@ -207,7 +209,7 @@ const steps = [
|
|
|
207
209
|
|
|
208
210
|
.step-card__body:hover {
|
|
209
211
|
transform: translateX(4px);
|
|
210
|
-
border-color:
|
|
212
|
+
border-color: rgb(var(--ink-rgb, 255 255 255) / 0.18);
|
|
211
213
|
}
|
|
212
214
|
|
|
213
215
|
.step-tag {
|
|
@@ -234,7 +236,7 @@ const steps = [
|
|
|
234
236
|
.step-code {
|
|
235
237
|
padding: 0.75rem 1rem;
|
|
236
238
|
background: rgba(0, 0, 0, 0.5);
|
|
237
|
-
border: 1px solid
|
|
239
|
+
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
|
|
238
240
|
border-radius: 10px;
|
|
239
241
|
font-family: var(--font-mono, monospace);
|
|
240
242
|
font-size: 0.85rem;
|
|
@@ -242,7 +244,7 @@ const steps = [
|
|
|
242
244
|
overflow-x: auto;
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
@
|
|
247
|
+
@container (max-width: 640px) {
|
|
246
248
|
.flow-line {
|
|
247
249
|
display: none;
|
|
248
250
|
}
|
|
@@ -8,6 +8,7 @@ interface Props {
|
|
|
8
8
|
const { title = "Feedback", subtitle = "Badges, alerts, and notification components." } = Astro.props;
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
<div class="cq-feedback-showcase-cq">
|
|
11
12
|
<section class="feedback-showcase">
|
|
12
13
|
<div class="container">
|
|
13
14
|
<div class="showcase-header">
|
|
@@ -66,8 +67,9 @@ const { title = "Feedback", subtitle = "Badges, alerts, and notification compone
|
|
|
66
67
|
</div>
|
|
67
68
|
</div>
|
|
68
69
|
</section>
|
|
69
|
-
|
|
70
|
+
</div>
|
|
70
71
|
<style>
|
|
72
|
+
.cq-feedback-showcase-cq { container-type: inline-size; }
|
|
71
73
|
.feedback-showcase {
|
|
72
74
|
padding: var(--sp-16) 0;
|
|
73
75
|
position: relative;
|
|
@@ -84,8 +86,8 @@ const { title = "Feedback", subtitle = "Badges, alerts, and notification compone
|
|
|
84
86
|
text-transform: uppercase;
|
|
85
87
|
letter-spacing: 0.1em;
|
|
86
88
|
color: var(--c-primary-light);
|
|
87
|
-
background:
|
|
88
|
-
border: 1px solid
|
|
89
|
+
background: color-mix(in srgb, var(--c-primary, #b8860b) 10%, transparent);
|
|
90
|
+
border: 1px solid color-mix(in srgb, var(--c-primary, #b8860b) 25%, transparent);
|
|
89
91
|
border-radius: var(--r-full);
|
|
90
92
|
margin-bottom: var(--sp-4);
|
|
91
93
|
}
|
|
@@ -107,7 +109,7 @@ const { title = "Feedback", subtitle = "Badges, alerts, and notification compone
|
|
|
107
109
|
padding: var(--sp-12);
|
|
108
110
|
background: rgba(10, 10, 10, 0.6);
|
|
109
111
|
backdrop-filter: blur(20px);
|
|
110
|
-
border: 1px solid
|
|
112
|
+
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
|
|
111
113
|
border-radius: var(--r-xl);
|
|
112
114
|
margin-bottom: var(--sp-6);
|
|
113
115
|
box-shadow: 0 20px 60px rgba(0,0,0,0.4);
|
|
@@ -192,13 +194,13 @@ const { title = "Feedback", subtitle = "Badges, alerts, and notification compone
|
|
|
192
194
|
}
|
|
193
195
|
.badge--new {
|
|
194
196
|
background: linear-gradient(135deg, var(--c-primary-light), var(--c-primary));
|
|
195
|
-
color: #0a0a0a;
|
|
196
|
-
box-shadow: 0 2px 10px
|
|
197
|
+
color: var(--c-on-primary, #0a0a0a);
|
|
198
|
+
box-shadow: 0 2px 10px color-mix(in srgb, var(--c-primary, #b8860b) 25%, transparent);
|
|
197
199
|
}
|
|
198
200
|
.badge--beta {
|
|
199
|
-
background:
|
|
201
|
+
background: rgb(var(--ink-rgb, 255 255 255) / 0.08);
|
|
200
202
|
color: var(--c-text-1);
|
|
201
|
-
border: 1px solid
|
|
203
|
+
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.12);
|
|
202
204
|
}
|
|
203
205
|
.badge--count {
|
|
204
206
|
background: rgba(239,68,68,0.15);
|
|
@@ -215,9 +217,9 @@ const { title = "Feedback", subtitle = "Badges, alerts, and notification compone
|
|
|
215
217
|
gap: 0.75rem;
|
|
216
218
|
width: 100%;
|
|
217
219
|
padding: 1rem;
|
|
218
|
-
background:
|
|
220
|
+
background: rgb(var(--ink-rgb, 255 255 255) / 0.06);
|
|
219
221
|
backdrop-filter: blur(12px);
|
|
220
|
-
border: 1px solid
|
|
222
|
+
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.1);
|
|
221
223
|
border-radius: var(--r-lg);
|
|
222
224
|
box-shadow: 0 8px 30px rgba(0,0,0,0.3);
|
|
223
225
|
animation: fadeSlideIn 0.5s ease 0.45s both;
|
|
@@ -268,7 +270,7 @@ const { title = "Feedback", subtitle = "Badges, alerts, and notification compone
|
|
|
268
270
|
.spinner {
|
|
269
271
|
width: 1.5rem;
|
|
270
272
|
height: 1.5rem;
|
|
271
|
-
border: 2px solid
|
|
273
|
+
border: 2px solid color-mix(in srgb, var(--c-primary, #b8860b) 20%, transparent);
|
|
272
274
|
border-top-color: var(--c-primary-light);
|
|
273
275
|
border-radius: 50%;
|
|
274
276
|
animation: spin 0.8s linear infinite;
|
|
@@ -300,7 +302,7 @@ const { title = "Feedback", subtitle = "Badges, alerts, and notification compone
|
|
|
300
302
|
.usage-code {
|
|
301
303
|
text-align: center;
|
|
302
304
|
padding: var(--sp-4);
|
|
303
|
-
background:
|
|
305
|
+
background: rgb(var(--ink-rgb, 255 255 255) / 0.02);
|
|
304
306
|
border-radius: var(--r-md);
|
|
305
307
|
}
|
|
306
308
|
.usage-code code {
|
|
@@ -309,7 +311,7 @@ const { title = "Feedback", subtitle = "Badges, alerts, and notification compone
|
|
|
309
311
|
color: var(--c-primary-light);
|
|
310
312
|
}
|
|
311
313
|
|
|
312
|
-
@
|
|
314
|
+
@container (max-width: 640px) {
|
|
313
315
|
.feedback-stack { max-width: 100%; gap: var(--sp-4); }
|
|
314
316
|
.preview-stage { padding: var(--sp-8) var(--sp-4); }
|
|
315
317
|
.preview-stage__inner { min-height: auto; }
|
|
@@ -0,0 +1,157 @@
|
|
|
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
|
+
<div class="cq-footer-mega-section-cq">
|
|
62
|
+
<footer class={`fms fms--${variant} fms--${size} ${className}`} aria-labelledby={id}>
|
|
63
|
+
<h2 id={id} class="fms__sr">Site footer</h2>
|
|
64
|
+
<div class="fms__inner">
|
|
65
|
+
<div class="fms__top">
|
|
66
|
+
<div class="fms__brand">
|
|
67
|
+
<a class="fms__logo" href="/">
|
|
68
|
+
<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>
|
|
69
|
+
{brand}
|
|
70
|
+
</a>
|
|
71
|
+
<p class="fms__tagline">{tagline}</p>
|
|
72
|
+
<form class="fms__news" action="#" method="post">
|
|
73
|
+
<label for={`${id}-email`} class="fms__news-label">Get product updates</label>
|
|
74
|
+
<div class="fms__news-field">
|
|
75
|
+
<input id={`${id}-email`} type="email" name="email" placeholder="you@company.com" autocomplete="email" required />
|
|
76
|
+
<button type="submit" aria-label="Subscribe to product updates">
|
|
77
|
+
<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>
|
|
78
|
+
</button>
|
|
79
|
+
</div>
|
|
80
|
+
</form>
|
|
81
|
+
</div>
|
|
82
|
+
<nav class="fms__cols" aria-label="Footer">
|
|
83
|
+
{columns.map((c) => (
|
|
84
|
+
<div class="fms__col">
|
|
85
|
+
<h3 class="fms__col-title">{c.title}</h3>
|
|
86
|
+
<ul>
|
|
87
|
+
{c.links.map((l) => <li><a href={l.href}>{l.label}</a></li>)}
|
|
88
|
+
</ul>
|
|
89
|
+
</div>
|
|
90
|
+
))}
|
|
91
|
+
</nav>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="fms__bottom">
|
|
94
|
+
<p class="fms__copy">{copyright}</p>
|
|
95
|
+
{status && (
|
|
96
|
+
<a class="fms__status" href="#">
|
|
97
|
+
<span class="fms__dot" aria-hidden="true"></span>{status}
|
|
98
|
+
</a>
|
|
99
|
+
)}
|
|
100
|
+
<ul class="fms__socials">
|
|
101
|
+
{socials.map((s) => (
|
|
102
|
+
<li>
|
|
103
|
+
<a href={s.href} aria-label={s.label}>
|
|
104
|
+
<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>
|
|
105
|
+
</a>
|
|
106
|
+
</li>
|
|
107
|
+
))}
|
|
108
|
+
</ul>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</footer>
|
|
112
|
+
</div>
|
|
113
|
+
<style>
|
|
114
|
+
.cq-footer-mega-section-cq { container-type: inline-size; }
|
|
115
|
+
.fms {
|
|
116
|
+
--fms-py: 4.5rem;
|
|
117
|
+
padding: var(--fms-py) var(--sp-6, 1.5rem) 2rem;
|
|
118
|
+
background: var(--c-bg-1, #0a0a0a);
|
|
119
|
+
border-top: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.06);
|
|
120
|
+
}
|
|
121
|
+
.fms--sm { --fms-py: 3rem; }
|
|
122
|
+
.fms--lg { --fms-py: 6rem; }
|
|
123
|
+
.fms--bordered .fms__inner { padding: clamp(1.5rem, 4vw, 3rem); border-radius: var(--r-xl, 28px); border: 1px solid var(--c-border, rgb(var(--ink-rgb, 255 255 255) / 0.08)); background: rgb(var(--ink-rgb, 255 255 255) / 0.015); }
|
|
124
|
+
.fms--minimal { background: transparent; border-top: 0; }
|
|
125
|
+
.fms--minimal .fms__news { display: none; }
|
|
126
|
+
.fms__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
127
|
+
.fms__inner { max-width: 1180px; margin: 0 auto; }
|
|
128
|
+
.fms__top { display: grid; grid-template-columns: 1.2fr 2fr; gap: clamp(2rem, 6vw, 5rem); padding-bottom: 3rem; border-bottom: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.07); }
|
|
129
|
+
.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; }
|
|
130
|
+
.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); }
|
|
131
|
+
.fms__news-label { display: block; margin-bottom: 0.5rem; font-size: 0.8125rem; font-weight: 600; color: var(--c-text-1, #fff); }
|
|
132
|
+
.fms__news-field { display: flex; max-width: 340px; border-radius: var(--r-md, 12px); border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.12); background: rgba(0, 0, 0, 0.3); overflow: hidden; transition: border-color 0.2s ease; }
|
|
133
|
+
.fms__news-field:focus-within { border-color: var(--c-primary-light, #d4a017); }
|
|
134
|
+
.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; }
|
|
135
|
+
.fms__news-field input:focus { outline: none; }
|
|
136
|
+
.fms__news-field input::placeholder { color: var(--c-text-3, #737373); }
|
|
137
|
+
.fms__news-field button { width: 46px; border: 0; background: rgb(var(--ink-rgb, 255 255 255) / 0.06); color: var(--c-text-1, #fff); cursor: pointer; transition: background 0.2s ease; }
|
|
138
|
+
.fms__news-field button:hover { background: var(--c-primary-light, #d4a017); color: var(--c-on-primary, #0a0a0a); }
|
|
139
|
+
.fms__news-field button:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: -2px; }
|
|
140
|
+
.fms__cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 2rem; }
|
|
141
|
+
.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); }
|
|
142
|
+
.fms__col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.25rem; }
|
|
143
|
+
.fms__col a, .fms__copy, .fms__status { font-size: 0.9rem; color: var(--c-text-2, #a3a3a3); text-decoration: none; }
|
|
144
|
+
.fms__col a { display: inline-flex; align-items: center; min-height: 36px; transition: color 0.2s ease; }
|
|
145
|
+
.fms__col a:hover { color: var(--c-text-1, #fff); }
|
|
146
|
+
.fms a:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 2px; border-radius: 4px; }
|
|
147
|
+
.fms__bottom { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; padding-top: 1.75rem; }
|
|
148
|
+
.fms__copy { margin: 0; font-size: 0.8125rem; }
|
|
149
|
+
.fms__status { display: inline-flex; align-items: center; gap: 0.5rem; min-height: 36px; padding: 0 0.85rem; border-radius: 999px; border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08); font-size: 0.8125rem; }
|
|
150
|
+
.fms__status:hover { color: var(--c-text-1, #fff); }
|
|
151
|
+
.fms__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--chart-pos, #34c38f); box-shadow: 0 0 8px var(--chart-pos, #34c38f); }
|
|
152
|
+
.fms__socials { list-style: none; margin: 0; padding: 0; display: flex; gap: 0.25rem; }
|
|
153
|
+
.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; }
|
|
154
|
+
.fms__socials a:hover { color: var(--c-text-1, #fff); background: rgb(var(--ink-rgb, 255 255 255) / 0.06); }
|
|
155
|
+
@container (max-width: 860px) { .fms__top { grid-template-columns: 1fr; } }
|
|
156
|
+
@container (max-width: 560px) { .fms__bottom { flex-direction: column; align-items: flex-start; } }
|
|
157
|
+
</style>
|