astro-component-kit 0.0.1 → 0.1.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 +218 -119
- package/package.json +28 -55
- package/src/components/index.ts +207 -0
- package/src/components/lib/AnimatedGalaxy.astro +185 -0
- package/src/components/lib/Galaxy3D.astro +308 -0
- package/src/components/lib/GlassNavbar.astro +13 -11
- package/src/components/lib/LogoWithGalaxy.astro +63 -0
- package/src/components/lib/buttons/3dPushButton.astro +9 -0
- package/src/components/lib/buttons/AnimatedIconButton.astro +10 -0
- package/src/components/lib/buttons/BorderDrawButton.astro +9 -0
- package/src/components/lib/buttons/CyberpunkButton.astro +10 -0
- package/src/components/lib/buttons/DoubleBorderButton.astro +9 -0
- package/src/components/lib/buttons/GhostOutlineButton.astro +10 -0
- package/src/components/lib/buttons/GlassButton.astro +13 -32
- package/src/components/lib/buttons/GlowButton.astro +9 -0
- package/src/components/lib/buttons/LiquidButton.astro +9 -0
- package/src/components/lib/buttons/LoadingButton.astro +10 -0
- package/src/components/lib/buttons/MagneticButton.astro +10 -0
- package/src/components/lib/buttons/MinimalPillButton.astro +9 -0
- package/src/components/lib/buttons/NeumorphicButton.astro +10 -0
- package/src/components/lib/buttons/PulseButton.astro +10 -0
- package/src/components/lib/buttons/RetroArcadeButton.astro +9 -0
- package/src/components/lib/buttons/RetroShadowButton.astro +9 -0
- package/src/components/lib/buttons/ShimmerButton.astro +9 -0
- package/src/components/lib/buttons/ShinyButton.astro +9 -0
- package/src/components/lib/buttons/TiltGlowButton.astro +10 -0
- package/src/components/lib/cards/BlogHorizontalCard.astro +46 -13
- package/src/components/lib/cards/CyberFeatureCard.astro +50 -6
- package/src/components/lib/cards/EcommerceProductCard.astro +69 -16
- package/src/components/lib/cards/GlassCard.astro +8 -0
- package/src/components/lib/cards/GlassEventCard.astro +53 -12
- package/src/components/lib/cards/GlowPortfolioCard.astro +46 -9
- package/src/components/lib/cards/InteractiveTiltCard.astro +47 -7
- package/src/components/lib/cards/KanbanItemCard.astro +40 -9
- package/src/components/lib/cards/MinimalLinkCard.astro +37 -7
- package/src/components/lib/cards/MusicPlayerMini.astro +54 -14
- package/src/components/lib/cards/NeumorphicCard.astro +32 -2
- package/src/components/lib/cards/NotificationCard.astro +44 -9
- package/src/components/lib/cards/PricingCard.astro +47 -9
- package/src/components/lib/cards/ProfileCard.astro +50 -11
- package/src/components/lib/cards/RetroGameCard.astro +37 -9
- package/src/components/lib/cards/StatCard.astro +43 -8
- package/src/components/lib/cards/TaskKanbanCard.astro +50 -11
- package/src/components/lib/cards/TestimonialCardClean.astro +43 -12
- package/src/components/lib/cards/WeatherWidgetCard.astro +36 -10
- package/src/components/lib/feedback/AnimatedCheckmark.astro +58 -9
- package/src/components/lib/feedback/Badge.astro +47 -12
- package/src/components/lib/feedback/CircleProgress.astro +56 -13
- package/src/components/lib/feedback/ConfettiFeedback.astro +74 -11
- package/src/components/lib/feedback/CyberGlitchAlert.astro +69 -6
- package/src/components/lib/feedback/EmptyStateCard.astro +55 -7
- package/src/components/lib/feedback/GlassAlert.astro +59 -13
- package/src/components/lib/feedback/GlassModal.astro +99 -14
- package/src/components/lib/feedback/GlassProgress.astro +39 -5
- package/src/components/lib/feedback/IndicatorBadgeMinimal.astro +56 -3
- package/src/components/lib/feedback/NeonSpinner.astro +40 -3
- package/src/components/lib/feedback/PulseDot.astro +51 -7
- package/src/components/lib/feedback/RatingPill.astro +38 -8
- package/src/components/lib/feedback/ShakeErrorGroup.astro +44 -3
- package/src/components/lib/feedback/SimpleTooltip.astro +53 -4
- package/src/components/lib/feedback/SkeletonList.astro +59 -13
- package/src/components/lib/feedback/Spotlight.astro +49 -4
- package/src/components/lib/feedback/StepProgress.astro +96 -9
- package/src/components/lib/feedback/ToastNotif.astro +60 -6
- package/src/components/lib/feedback/TypingIndicator.astro +52 -7
- package/src/components/lib/forms/AnimatedInput.astro +47 -5
- package/src/components/lib/forms/ChipInput.astro +116 -8
- package/src/components/lib/forms/ColorPickerInput.astro +53 -6
- package/src/components/lib/forms/CurrencyInput.astro +59 -6
- package/src/components/lib/forms/CustomRadioGroup.astro +61 -9
- package/src/components/lib/forms/CyberpunkCheckbox.astro +64 -8
- package/src/components/lib/forms/DragDropUpload.astro +87 -7
- package/src/components/lib/forms/ErrorInput.astro +31 -4
- package/src/components/lib/forms/FloatingPassword.astro +48 -10
- package/src/components/lib/forms/FormGroupVertical.astro +63 -9
- package/src/components/lib/forms/GlassSlider.astro +84 -3
- package/src/components/lib/forms/GlassTextarea.astro +39 -6
- package/src/components/lib/forms/ModernSelect.astro +66 -10
- package/src/components/lib/forms/NeumorphicSwitch.astro +54 -26
- package/src/components/lib/forms/OTPInput.astro +84 -12
- package/src/components/lib/forms/RatingStars.astro +66 -10
- package/src/components/lib/forms/SearchReveal.astro +44 -6
- package/src/components/lib/forms/SegmentedControl.astro +61 -7
- package/src/components/lib/forms/SimpleFileInput.astro +57 -6
- package/src/components/lib/forms/StepperInput.astro +101 -9
- package/src/components/lib/layout/FeatureHero.astro +70 -6
- package/src/components/lib/layout/FooterCenteredMinimal.astro +5 -2
- package/src/components/lib/navigation/GlassNavbar.astro +10 -5
- package/src/components/lib/navigation/MinimalSidebar.astro +6 -3
- package/src/components/lib/navigation/SimpleFooterGlass.astro +6 -2
- package/src/components/lib/overlays/SplashIntroOverlay.astro +6 -3
- package/src/components/lib/sections/ButtonsShowcase.astro +182 -0
- package/src/components/lib/sections/CardsShowcase.astro +376 -0
- package/src/components/lib/sections/DataShowcase.astro +329 -0
- package/src/components/lib/sections/FeedbackShowcase.astro +320 -0
- package/src/components/lib/sections/FormsShowcase.astro +347 -0
- package/src/components/lib/sections/HeroGlass.astro +202 -0
- package/src/components/lib/sections/HeroGradient.astro +143 -0
- package/src/components/lib/sections/HeroSplit.astro +210 -0
- package/src/components/lib/sections/LayoutShowcase.astro +317 -0
- package/src/components/lib/sections/NavigationShowcase.astro +285 -0
- package/src/components/lib/sections/OverlaysShowcase.astro +373 -0
- package/src/components/lib/sections/TypographyShowcase.astro +239 -0
- package/src/components/lib/sections/index.ts +6 -0
- package/src/components/types.d.ts +6 -0
- package/{dist → src}/styles/global.css +5 -5
- package/dist/AnimatedInput.astro +0 -82
- package/dist/Badge.astro +0 -52
- package/dist/GlassButton.astro +0 -87
- package/dist/GlassCard.astro +0 -72
- package/dist/GlassNavbar.astro +0 -65
- package/dist/GlowButton.astro +0 -60
- package/dist/buttons/3dPushButton.astro +0 -136
- package/dist/buttons/AnimatedIconButton.astro +0 -146
- package/dist/buttons/BorderDrawButton.astro +0 -112
- package/dist/buttons/CyberpunkButton.astro +0 -148
- package/dist/buttons/DoubleBorderButton.astro +0 -131
- package/dist/buttons/GhostOutlineButton.astro +0 -109
- package/dist/buttons/GlassButton.astro +0 -165
- package/dist/buttons/GlowButton.astro +0 -119
- package/dist/buttons/LiquidButton.astro +0 -167
- package/dist/buttons/LoadingButton.astro +0 -148
- package/dist/buttons/MagneticButton.astro +0 -134
- package/dist/buttons/MinimalPillButton.astro +0 -102
- package/dist/buttons/NeumorphicButton.astro +0 -158
- package/dist/buttons/PulseButton.astro +0 -111
- package/dist/buttons/RetroArcadeButton.astro +0 -105
- package/dist/buttons/RetroShadowButton.astro +0 -82
- package/dist/buttons/ShimmerButton.astro +0 -113
- package/dist/buttons/ShinyButton.astro +0 -121
- package/dist/buttons/TiltGlowButton.astro +0 -145
- package/dist/buttons/index.mjs +0 -19
- package/dist/buttons/index.ts +0 -19
- package/dist/cards/BlogHorizontalCard.astro +0 -18
- package/dist/cards/CyberFeatureCard.astro +0 -12
- package/dist/cards/EcommerceProductCard.astro +0 -24
- package/dist/cards/GlassCard.astro +0 -17
- package/dist/cards/GlassEventCard.astro +0 -19
- package/dist/cards/GlowPortfolioCard.astro +0 -16
- package/dist/cards/InteractiveTiltCard.astro +0 -25
- package/dist/cards/KanbanItemCard.astro +0 -15
- package/dist/cards/MinimalLinkCard.astro +0 -12
- package/dist/cards/MusicPlayerMini.astro +0 -21
- package/dist/cards/NeumorphicCard.astro +0 -6
- package/dist/cards/NotificationCard.astro +0 -15
- package/dist/cards/PricingCard.astro +0 -17
- package/dist/cards/ProfileCard.astro +0 -17
- package/dist/cards/RetroGameCard.astro +0 -15
- package/dist/cards/StatCard.astro +0 -15
- package/dist/cards/TaskKanbanCard.astro +0 -18
- package/dist/cards/TestimonialCardClean.astro +0 -20
- package/dist/cards/WeatherWidgetCard.astro +0 -17
- package/dist/cards/index.mjs +0 -19
- package/dist/cards/index.ts +0 -19
- package/dist/data/AccordionGroupGlass.astro +0 -21
- package/dist/data/AvatarGroupStack.astro +0 -15
- package/dist/data/CalendarGridView.astro +0 -18
- package/dist/data/DataChipsGroup.astro +0 -16
- package/dist/data/DescriptionListHoriz.astro +0 -14
- package/dist/data/FileTreeView.astro +0 -22
- package/dist/data/GanttChartMinimal.astro +0 -12
- package/dist/data/GlassTable.astro +0 -23
- package/dist/data/KeyValuePillGroup.astro +0 -12
- package/dist/data/PriceCompareTable.astro +0 -22
- package/dist/data/ProgressListSmall.astro +0 -17
- package/dist/data/RatingBreakdownBar.astro +0 -13
- package/dist/data/SparklineStatCard.astro +0 -16
- package/dist/data/StatsGridDashboard.astro +0 -16
- package/dist/data/StepperDataVertical.astro +0 -15
- package/dist/data/TagCloudData.astro +0 -14
- package/dist/data/TimelineHorizSteps.astro +0 -18
- package/dist/data/TreeItemInteractive.astro +0 -18
- package/dist/data/UserDirectoryItem.astro +0 -15
- package/dist/data/VerticalTimeline.astro +0 -21
- package/dist/data/index.mjs +0 -20
- package/dist/data/index.ts +0 -20
- package/dist/feedback/AnimatedCheckmark.astro +0 -13
- package/dist/feedback/Badge.astro +0 -19
- package/dist/feedback/CircleProgress.astro +0 -22
- package/dist/feedback/ConfettiFeedback.astro +0 -18
- package/dist/feedback/CyberGlitchAlert.astro +0 -11
- package/dist/feedback/EmptyStateCard.astro +0 -13
- package/dist/feedback/GlassAlert.astro +0 -20
- package/dist/feedback/GlassModal.astro +0 -19
- package/dist/feedback/GlassProgress.astro +0 -10
- package/dist/feedback/IndicatorBadgeMinimal.astro +0 -10
- package/dist/feedback/NeonSpinner.astro +0 -7
- package/dist/feedback/PulseDot.astro +0 -12
- package/dist/feedback/RatingPill.astro +0 -13
- package/dist/feedback/ShakeErrorGroup.astro +0 -7
- package/dist/feedback/SimpleTooltip.astro +0 -10
- package/dist/feedback/SkeletonList.astro +0 -20
- package/dist/feedback/Spotlight.astro +0 -9
- package/dist/feedback/StepProgress.astro +0 -14
- package/dist/feedback/ToastNotif.astro +0 -11
- package/dist/feedback/TypingIndicator.astro +0 -12
- package/dist/feedback/index.mjs +0 -20
- package/dist/feedback/index.ts +0 -20
- package/dist/forms/AnimatedInput.astro +0 -16
- package/dist/forms/ChipInput.astro +0 -13
- package/dist/forms/ColorPickerInput.astro +0 -13
- package/dist/forms/CurrencyInput.astro +0 -11
- package/dist/forms/CustomRadioGroup.astro +0 -13
- package/dist/forms/CyberpunkCheckbox.astro +0 -15
- package/dist/forms/DragDropUpload.astro +0 -12
- package/dist/forms/ErrorInput.astro +0 -11
- package/dist/forms/FloatingPassword.astro +0 -20
- package/dist/forms/FormGroupVertical.astro +0 -14
- package/dist/forms/GlassSlider.astro +0 -7
- package/dist/forms/GlassTextarea.astro +0 -14
- package/dist/forms/ModernSelect.astro +0 -16
- package/dist/forms/NeumorphicSwitch.astro +0 -55
- package/dist/forms/OTPInput.astro +0 -22
- package/dist/forms/RatingStars.astro +0 -15
- package/dist/forms/SearchReveal.astro +0 -13
- package/dist/forms/SegmentedControl.astro +0 -13
- package/dist/forms/SimpleFileInput.astro +0 -11
- package/dist/forms/StepperInput.astro +0 -14
- package/dist/forms/index.mjs +0 -20
- package/dist/forms/index.ts +0 -20
- package/dist/index.js +0 -1
- package/dist/index.mjs +0 -1
- package/dist/layout/BentoGrid3.astro +0 -14
- package/dist/layout/CenterFixedBox.astro +0 -6
- package/dist/layout/CenteredContainer.astro +0 -8
- package/dist/layout/ClusterHorizontal.astro +0 -6
- package/dist/layout/FeatureHero.astro +0 -17
- package/dist/layout/FooterCenteredMinimal.astro +0 -11
- package/dist/layout/FullBleedSection.astro +0 -6
- package/dist/layout/GalleryGrid4.astro +0 -7
- package/dist/layout/GlassCardGrid.astro +0 -6
- package/dist/layout/GlassSectionHeader.astro +0 -15
- package/dist/layout/LandingSectionSplit.astro +0 -13
- package/dist/layout/MasonryGrid.astro +0 -7
- package/dist/layout/MinimalFooterGrid.astro +0 -20
- package/dist/layout/ScrollSnapSection.astro +0 -7
- package/dist/layout/SectionDividerText.astro +0 -7
- package/dist/layout/SidebarLayoutWrapper.astro +0 -11
- package/dist/layout/SplitScreenLayout.astro +0 -11
- package/dist/layout/StepLayoutVertical.astro +0 -21
- package/dist/layout/StickySidebarWrapper.astro +0 -10
- package/dist/layout/VerticalStack.astro +0 -8
- package/dist/layout/index.mjs +0 -20
- package/dist/layout/index.ts +0 -20
- package/dist/navigation/AnchorSideNav.astro +0 -13
- package/dist/navigation/BottomNavMobile.astro +0 -13
- package/dist/navigation/BreadcrumbsMinimal.astro +0 -16
- package/dist/navigation/BurgerMorphIcon.astro +0 -12
- package/dist/navigation/CommandPaletteUI.astro +0 -17
- package/dist/navigation/DotNavigationSlider.astro +0 -13
- package/dist/navigation/FloatingTabBar.astro +0 -12
- package/dist/navigation/GlassNavbar.astro +0 -19
- package/dist/navigation/LangSwitcherPill.astro +0 -17
- package/dist/navigation/MegaMenuGlass.astro +0 -25
- package/dist/navigation/MinimalSidebar.astro +0 -18
- package/dist/navigation/PaginationGlass.astro +0 -20
- package/dist/navigation/PaginationInfiniteUI.astro +0 -11
- package/dist/navigation/RadialIconMenu.astro +0 -15
- package/dist/navigation/RetroArcadeMenu.astro +0 -12
- package/dist/navigation/ScrollProgressTop.astro +0 -15
- package/dist/navigation/SimpleFooterGlass.astro +0 -21
- package/dist/navigation/TabUnderline.astro +0 -14
- package/dist/navigation/UserProfileNav.astro +0 -21
- package/dist/navigation/VerticalTabs.astro +0 -14
- package/dist/navigation/index.mjs +0 -20
- package/dist/navigation/index.ts +0 -20
- package/dist/overlays/AgeVerificationOverlay.astro +0 -20
- package/dist/overlays/BackdropBlurMask.astro +0 -6
- package/dist/overlays/BottomSheetMobile.astro +0 -16
- package/dist/overlays/CommandDialog.astro +0 -19
- package/dist/overlays/ContextMenuOverlay.astro +0 -17
- package/dist/overlays/CookieBannerGlass.astro +0 -14
- package/dist/overlays/ExitIntentOverlay.astro +0 -19
- package/dist/overlays/FloatingTrayActions.astro +0 -13
- package/dist/overlays/HelpBubbleOverlay.astro +0 -11
- package/dist/overlays/LightboxOverlay.astro +0 -13
- package/dist/overlays/LoadingOverlayFull.astro +0 -10
- package/dist/overlays/MobileNavOverlay.astro +0 -18
- package/dist/overlays/OverlayModal.astro +0 -24
- package/dist/overlays/PopoverMenuGlass.astro +0 -17
- package/dist/overlays/SearchOverlayFullscreen.astro +0 -15
- package/dist/overlays/SideDrawerRight.astro +0 -16
- package/dist/overlays/SplashIntroOverlay.astro +0 -11
- package/dist/overlays/SpotlightIndicator.astro +0 -6
- package/dist/overlays/ToastStackOverlay.astro +0 -12
- package/dist/overlays/TooltipActionTray.astro +0 -14
- package/dist/overlays/index.mjs +0 -20
- package/dist/overlays/index.ts +0 -20
- package/dist/typography/AnimatedUnderlineLink.astro +0 -10
- package/dist/typography/BackgroundClipMask.astro +0 -7
- package/dist/typography/CodeInlineGlass.astro +0 -6
- package/dist/typography/CyberpunkGlitchText.astro +0 -20
- package/dist/typography/DropCapParagraph.astro +0 -7
- package/dist/typography/FadedVerticalText.astro +0 -6
- package/dist/typography/FloatingTextLabel.astro +0 -10
- package/dist/typography/GlassBlockQuote.astro +0 -13
- package/dist/typography/GlassTextReveal.astro +0 -7
- package/dist/typography/GradientHeading.astro +0 -9
- package/dist/typography/GradientUnderlineLink.astro +0 -7
- package/dist/typography/KbdIndicator.astro +0 -6
- package/dist/typography/LetterSpacingWide.astro +0 -6
- package/dist/typography/MinimalListMarkers.astro +0 -10
- package/dist/typography/MonospaceStatLine.astro +0 -6
- package/dist/typography/NeonTextHighlight.astro +0 -6
- package/dist/typography/ShadowRevealText.astro +0 -7
- package/dist/typography/StrokeHeadingOutline.astro +0 -8
- package/dist/typography/Text3DLayer.astro +0 -7
- package/dist/typography/TypewriterText.astro +0 -15
- package/dist/typography/index.mjs +0 -20
- package/dist/typography/index.ts +0 -20
- package/dist/utilities/AspectRatioBox.astro +0 -11
- package/dist/utilities/BackgroundDotPattern.astro +0 -6
- package/dist/utilities/CircularMask.astro +0 -7
- package/dist/utilities/ClickRippleWrapper.astro +0 -7
- package/dist/utilities/FadeInWrapper.astro +0 -11
- package/dist/utilities/FixedRatioImage.astro +0 -7
- package/dist/utilities/GlassBlurLayer.astro +0 -6
- package/dist/utilities/GradientBorderMask.astro +0 -7
- package/dist/utilities/HoverLift.astro +0 -7
- package/dist/utilities/ResponsiveSpacer.astro +0 -15
- package/dist/utilities/ResponsiveVisToggle.astro +0 -11
- package/dist/utilities/ScrollLockParent.astro +0 -11
- package/dist/utilities/ScrollMarginTarget.astro +0 -10
- package/dist/utilities/SlideUpReveal.astro +0 -7
- package/dist/utilities/SmoothAnchorLink.astro +0 -22
- package/dist/utilities/StackLayering.astro +0 -12
- package/dist/utilities/StickyObserver.astro +0 -8
- package/dist/utilities/TextTruncate.astro +0 -10
- package/dist/utilities/TruncateSingleLine.astro +0 -6
- package/dist/utilities/VisuallyHidden.astro +0 -6
- package/dist/utilities/index.mjs +0 -20
- package/dist/utilities/index.ts +0 -20
- package/src/components/lib/utilities/AspectRatioBox.astro +0 -11
- package/src/components/lib/utilities/BackgroundDotPattern.astro +0 -6
- package/src/components/lib/utilities/CircularMask.astro +0 -7
- package/src/components/lib/utilities/ClickRippleWrapper.astro +0 -7
- package/src/components/lib/utilities/FadeInWrapper.astro +0 -11
- package/src/components/lib/utilities/FixedRatioImage.astro +0 -7
- package/src/components/lib/utilities/GlassBlurLayer.astro +0 -6
- package/src/components/lib/utilities/GradientBorderMask.astro +0 -7
- package/src/components/lib/utilities/HoverLift.astro +0 -7
- package/src/components/lib/utilities/ResponsiveSpacer.astro +0 -15
- package/src/components/lib/utilities/ResponsiveVisToggle.astro +0 -11
- package/src/components/lib/utilities/ScrollLockParent.astro +0 -11
- package/src/components/lib/utilities/ScrollMarginTarget.astro +0 -10
- package/src/components/lib/utilities/SlideUpReveal.astro +0 -7
- package/src/components/lib/utilities/SmoothAnchorLink.astro +0 -22
- package/src/components/lib/utilities/StackLayering.astro +0 -12
- package/src/components/lib/utilities/StickyObserver.astro +0 -8
- package/src/components/lib/utilities/TextTruncate.astro +0 -10
- package/src/components/lib/utilities/TruncateSingleLine.astro +0 -6
- package/src/components/lib/utilities/VisuallyHidden.astro +0 -6
- package/src/components/lib/utilities/index.ts +0 -20
|
@@ -1,14 +1,101 @@
|
|
|
1
1
|
---
|
|
2
|
+
/**
|
|
3
|
+
* StepProgress — A multi-stage stepper indicating flow through several discrete points.
|
|
4
|
+
*
|
|
5
|
+
* @param {Array<{label: string}>} steps - List of steps to represent.
|
|
6
|
+
* @param {number} activeIndex - The index (0-based) of the current step. Default is 0.
|
|
7
|
+
*/
|
|
8
|
+
interface Props {
|
|
9
|
+
steps?: Array<{ label: string }>;
|
|
10
|
+
activeIndex?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
steps = [
|
|
15
|
+
{ label: 'Details' },
|
|
16
|
+
{ label: 'Payment' },
|
|
17
|
+
{ label: 'Finish' }
|
|
18
|
+
],
|
|
19
|
+
activeIndex = 0
|
|
20
|
+
} = Astro.props;
|
|
2
21
|
---
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<div class="
|
|
6
|
-
<div class="
|
|
22
|
+
|
|
23
|
+
<div class="steps-container">
|
|
24
|
+
<div class="steps-line" aria-hidden="true" style={`--progress: ${(activeIndex / (steps.length - 1)) * 100}%`}></div>
|
|
25
|
+
<div class="steps-list">
|
|
26
|
+
{steps.map((step, i) => (
|
|
27
|
+
<div
|
|
28
|
+
class:list={['step-item', { 'step-item--active': i === activeIndex, 'step-item--complete': i < activeIndex }]}
|
|
29
|
+
aria-current={i === activeIndex ? "step" : undefined}
|
|
30
|
+
>
|
|
31
|
+
<div class="step-circle">{i + 1}</div>
|
|
32
|
+
<span class="step-label">{step.label}</span>
|
|
33
|
+
</div>
|
|
34
|
+
))}
|
|
35
|
+
</div>
|
|
7
36
|
</div>
|
|
37
|
+
|
|
8
38
|
<style>
|
|
9
|
-
.steps {
|
|
10
|
-
|
|
11
|
-
.
|
|
12
|
-
|
|
13
|
-
|
|
39
|
+
.steps-container { position: relative; margin-bottom: var(--sp-8, 2rem); width: 100%; padding: 0 var(--sp-4, 1rem); box-sizing: border-box; }
|
|
40
|
+
|
|
41
|
+
.steps-line {
|
|
42
|
+
position: absolute;
|
|
43
|
+
top: 16px; left: 0; right: 0;
|
|
44
|
+
height: 3px;
|
|
45
|
+
background: var(--c-bg-elev, rgba(255,255,255,0.05));
|
|
46
|
+
z-index: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.steps-line::after {
|
|
50
|
+
content: "";
|
|
51
|
+
position: absolute;
|
|
52
|
+
left: 0; top: 0;
|
|
53
|
+
height: 100%;
|
|
54
|
+
width: var(--progress);
|
|
55
|
+
background: var(--c-primary, #6366f1);
|
|
56
|
+
transition: width 0.4s ease-in-out;
|
|
57
|
+
box-shadow: 0 0 10px rgba(99,102,241,0.3);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.steps-list { display: flex; justify-content: space-between; position: relative; z-index: 1; }
|
|
61
|
+
|
|
62
|
+
.step-circle {
|
|
63
|
+
width: 32px; height: 32px;
|
|
64
|
+
border-radius: var(--r-full, 50%);
|
|
65
|
+
background: var(--c-bg, #1e293b);
|
|
66
|
+
color: var(--c-text-2, #64748b);
|
|
67
|
+
border: 2px solid var(--c-border, rgba(255,255,255,0.1));
|
|
68
|
+
display: grid; place-items: center;
|
|
69
|
+
font-size: 0.85rem; font-weight: 800;
|
|
70
|
+
transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.step-item--active .step-circle {
|
|
74
|
+
background: var(--c-primary, #6366f1);
|
|
75
|
+
border-color: var(--c-primary, #6366f1);
|
|
76
|
+
color: #fff;
|
|
77
|
+
box-shadow: 0 0 20px rgba(99,102,241,0.5);
|
|
78
|
+
transform: scale(1.1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.step-item--complete .step-circle {
|
|
82
|
+
background: var(--c-primary, #6366f1);
|
|
83
|
+
border-color: var(--c-primary, #6366f1);
|
|
84
|
+
color: #fff;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.step-label {
|
|
88
|
+
position: absolute;
|
|
89
|
+
top: 100%; left: 50%;
|
|
90
|
+
transform: translateX(-50%);
|
|
91
|
+
margin-top: 8px;
|
|
92
|
+
font-size: 0.7rem;
|
|
93
|
+
font-weight: 700;
|
|
94
|
+
white-space: nowrap;
|
|
95
|
+
color: var(--c-text-2, #64748b);
|
|
96
|
+
text-transform: uppercase;
|
|
97
|
+
letter-spacing: 0.05em;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.step-item--active .step-label, .step-item--complete .step-label { color: var(--c-text-1, #fff); }
|
|
14
101
|
</style>
|
|
@@ -1,11 +1,65 @@
|
|
|
1
1
|
---
|
|
2
|
+
/**
|
|
3
|
+
* ToastNotif — A transient snackbar notification that appears at the corner of the screen.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} message - The notification content.
|
|
6
|
+
* @param {string} icon - Emoji or SVG icon. Default is '✅'.
|
|
7
|
+
* @param {'success'|'info'|'error'} variant - Theme of the toast. Default is 'success'.
|
|
8
|
+
* @param {boolean} show - Initial visibility. Default is true.
|
|
9
|
+
*/
|
|
10
|
+
interface Props {
|
|
11
|
+
message: string;
|
|
12
|
+
icon?: string;
|
|
13
|
+
variant?: 'success' | 'info' | 'error';
|
|
14
|
+
show?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
message,
|
|
19
|
+
icon = "✅",
|
|
20
|
+
variant = 'success',
|
|
21
|
+
show = true
|
|
22
|
+
} = Astro.props;
|
|
2
23
|
---
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<
|
|
24
|
+
|
|
25
|
+
<div class:list={['toast', `toast--${variant}`, { 'toast--show': show }]} role="status">
|
|
26
|
+
<div class="toast__icon" aria-hidden="true">{icon}</div>
|
|
27
|
+
<span class="toast__msg">{message}</span>
|
|
6
28
|
</div>
|
|
29
|
+
|
|
7
30
|
<style>
|
|
8
|
-
.toast {
|
|
9
|
-
|
|
10
|
-
|
|
31
|
+
.toast {
|
|
32
|
+
position: fixed;
|
|
33
|
+
bottom: 2rem;
|
|
34
|
+
right: 2rem;
|
|
35
|
+
background: var(--c-bg-elev, #0f172a);
|
|
36
|
+
color: var(--c-text-1, #fff);
|
|
37
|
+
padding: var(--sp-4, 1rem) var(--sp-6, 1.5rem);
|
|
38
|
+
border-radius: var(--r-md, 14px);
|
|
39
|
+
border: 1px solid var(--c-border, rgba(255,255,255,0.1));
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
gap: var(--sp-3, 0.8rem);
|
|
43
|
+
box-shadow: 0 15px 45px rgba(0,0,0,0.4);
|
|
44
|
+
transform: translateY(150%) scale(0.9);
|
|
45
|
+
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
|
46
|
+
z-index: 10000;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.toast--show { transform: translateY(0) scale(1); }
|
|
50
|
+
|
|
51
|
+
.toast--success { border-left: 4px solid #10b981; }
|
|
52
|
+
.toast--info { border-left: 4px solid var(--c-primary, #6366f1); }
|
|
53
|
+
.toast--error { border-left: 4px solid #ef4444; }
|
|
54
|
+
|
|
55
|
+
.toast__icon {
|
|
56
|
+
background: rgba(255,255,255,0.05);
|
|
57
|
+
width: 28px; height: 28px;
|
|
58
|
+
display: grid; place-items: center;
|
|
59
|
+
border-radius: var(--r-sm, 6px);
|
|
60
|
+
font-size: 1rem;
|
|
61
|
+
flex-shrink: 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.toast__msg { font-size: 0.9rem; font-weight: 500; white-space: nowrap; }
|
|
11
65
|
</style>
|
|
@@ -1,12 +1,57 @@
|
|
|
1
1
|
---
|
|
2
|
+
/**
|
|
3
|
+
* TypingIndicator — A classic three-dot animation indicating a message is being composed.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} dotColor - CSS color for the dots. Default is 'var(--c-primary)'.
|
|
6
|
+
* @param {string} label - Accessible ARIA label. Default is "Typing...".
|
|
7
|
+
*/
|
|
8
|
+
interface Props {
|
|
9
|
+
dotColor?: string;
|
|
10
|
+
label?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
dotColor = 'var(--c-primary, #6366f1)',
|
|
15
|
+
label = "Someone is typing..."
|
|
16
|
+
} = Astro.props;
|
|
2
17
|
---
|
|
3
|
-
|
|
4
|
-
|
|
18
|
+
|
|
19
|
+
<div class="typing-wrap" role="status" aria-label={label}>
|
|
20
|
+
<div class="typing-dots" style={`--dot-color: ${dotColor};`}>
|
|
21
|
+
<span></span>
|
|
22
|
+
<span></span>
|
|
23
|
+
<span></span>
|
|
24
|
+
</div>
|
|
5
25
|
</div>
|
|
26
|
+
|
|
6
27
|
<style>
|
|
7
|
-
.typing {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
28
|
+
.typing-wrap {
|
|
29
|
+
display: flex;
|
|
30
|
+
padding: var(--sp-3, 0.75rem) var(--sp-5, 1.25rem);
|
|
31
|
+
background: var(--c-bg-elev, rgba(255,255,255,0.05));
|
|
32
|
+
border-radius: var(--r-xl, 20px);
|
|
33
|
+
width: fit-content;
|
|
34
|
+
border: 1px solid var(--c-border, rgba(255,255,255,0.1));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.typing-dots { display: flex; gap: var(--sp-1, 4px); }
|
|
38
|
+
|
|
39
|
+
.typing-dots span {
|
|
40
|
+
width: 6px;
|
|
41
|
+
height: 6px;
|
|
42
|
+
background: var(--c-text-muted, #64748b);
|
|
43
|
+
border-radius: var(--r-full, 50%);
|
|
44
|
+
animation: typing-bounce 0.8s infinite alternate cubic-bezier(0.455, 0.03, 0.515, 0.955);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.typing-dots span:nth-child(2) { animation-delay: 0.2s; }
|
|
48
|
+
.typing-dots span:nth-child(3) { animation-delay: 0.4s; }
|
|
49
|
+
|
|
50
|
+
@keyframes typing-bounce {
|
|
51
|
+
to {
|
|
52
|
+
transform: translateY(-4px);
|
|
53
|
+
background: var(--dot-color);
|
|
54
|
+
filter: drop-shadow(0 0 2px var(--dot-color));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
12
57
|
</style>
|
|
@@ -1,16 +1,58 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* AnimatedInput — A form input with a floating label animation and focus glow effect.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} label - The visible indicator for the input field.
|
|
6
|
+
* @param {string} id - The HTML id and for attribute linkage.
|
|
7
|
+
* @param {string} type - Input element type. Default is 'text'.
|
|
8
|
+
* @param {string} placeholder - Passed placeholder. Default is ' '. (Space is needed for CSS :placeholder-shown to work).
|
|
9
|
+
* @param {boolean} required - HTML required attribute parameter. Default is false.
|
|
10
|
+
* @param {string} name - HTML input name binding.
|
|
11
|
+
*/
|
|
12
|
+
interface Props {
|
|
13
|
+
label: string;
|
|
14
|
+
id: string;
|
|
15
|
+
type?: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url';
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
name?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
3
21
|
const { label, id, type = 'text', placeholder = ' ', required = false, name } = Astro.props;
|
|
4
22
|
---
|
|
23
|
+
|
|
5
24
|
<div class="anim-input-wrap">
|
|
6
25
|
<input {id} {name} {type} {placeholder} {required} class="anim-input" autocomplete="off" />
|
|
7
26
|
<label for={id} class="anim-input-label">{label}</label>
|
|
8
27
|
</div>
|
|
28
|
+
|
|
9
29
|
<style>
|
|
10
30
|
.anim-input-wrap { position: relative; width: 100%; }
|
|
11
|
-
.anim-input {
|
|
31
|
+
.anim-input {
|
|
32
|
+
width: 100%;
|
|
33
|
+
padding: 1.1rem 1rem 0.5rem;
|
|
34
|
+
font-family: inherit; font-size: 0.95rem;
|
|
35
|
+
color: var(--c-text-1, #e2e8f0);
|
|
36
|
+
background: var(--c-bg-elev, rgba(255, 255, 255, 0.04));
|
|
37
|
+
border: 1px solid var(--c-border, rgba(255, 255, 255, 0.1));
|
|
38
|
+
border-radius: var(--r-md, 12px); box-sizing: border-box;
|
|
39
|
+
outline: none; transition: border-color 0.25s ease, background 0.25s ease;
|
|
40
|
+
}
|
|
12
41
|
.anim-input::placeholder { color: transparent; }
|
|
13
|
-
.anim-input:focus {
|
|
14
|
-
|
|
15
|
-
|
|
42
|
+
.anim-input:focus {
|
|
43
|
+
background: rgba(99, 102, 241, 0.06);
|
|
44
|
+
border-color: rgba(99, 102, 241, 0.5);
|
|
45
|
+
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.12);
|
|
46
|
+
}
|
|
47
|
+
.anim-input-label {
|
|
48
|
+
position: absolute; top: 0.9rem; left: 1rem;
|
|
49
|
+
font-size: 0.9rem; color: var(--c-text-2, #64748b);
|
|
50
|
+
pointer-events: none; transition: top 0.2s ease, font-size 0.2s ease, color 0.2s ease;
|
|
51
|
+
}
|
|
52
|
+
.anim-input:focus ~ .anim-input-label,
|
|
53
|
+
.anim-input:not(:placeholder-shown) ~ .anim-input-label {
|
|
54
|
+
top: 0.28rem; font-size: 0.68rem;
|
|
55
|
+
color: var(--c-primary-light, #818cf8);
|
|
56
|
+
font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
|
|
57
|
+
}
|
|
16
58
|
</style>
|
|
@@ -1,13 +1,121 @@
|
|
|
1
1
|
---
|
|
2
|
+
/**
|
|
3
|
+
* ChipInput — An interactive input for managing a list of tags or chips.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} label - Input labeling title.
|
|
6
|
+
* @param {string[]} initialChips - Optional array of strings to pre-populate.
|
|
7
|
+
* @param {string} name - HTML name for form submission.
|
|
8
|
+
* @param {string} placeholder - Placeholder text for the input area.
|
|
9
|
+
*/
|
|
10
|
+
interface Props {
|
|
11
|
+
label?: string;
|
|
12
|
+
initialChips?: string[];
|
|
13
|
+
name?: string;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { label, initialChips = [], name, placeholder = "Add tag..." } = Astro.props;
|
|
2
18
|
---
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<
|
|
6
|
-
<
|
|
19
|
+
|
|
20
|
+
<div class="chip-input-container">
|
|
21
|
+
{label && <label class="chip-input-label">{label}</label>}
|
|
22
|
+
<div class="chip-input" data-chip-input>
|
|
23
|
+
<div class="chip-input__list" data-chip-list>
|
|
24
|
+
{initialChips.map(chip => (
|
|
25
|
+
<span class="chip">
|
|
26
|
+
{chip}
|
|
27
|
+
<button type="button" aria-label={`Remove ${chip}`} data-remove-chip>×</button>
|
|
28
|
+
<input type="hidden" name={`${name}[]`} value={chip} />
|
|
29
|
+
</span>
|
|
30
|
+
))}
|
|
31
|
+
</div>
|
|
32
|
+
<input
|
|
33
|
+
type="text"
|
|
34
|
+
class="chip-input__field"
|
|
35
|
+
placeholder={initialChips.length > 0 ? "" : placeholder}
|
|
36
|
+
data-chip-field
|
|
37
|
+
/>
|
|
38
|
+
</div>
|
|
7
39
|
</div>
|
|
40
|
+
|
|
8
41
|
<style>
|
|
9
|
-
.chip-input { display: flex; flex-
|
|
10
|
-
.chip {
|
|
11
|
-
|
|
12
|
-
.chip-input
|
|
42
|
+
.chip-input-container { display: flex; flex-direction: column; gap: var(--sp-2, 0.5rem); width: 100%; }
|
|
43
|
+
.chip-input-label { font-size: 0.85rem; font-weight: 600; color: var(--c-text-2, #94a3b8); margin-left: 0.5rem; }
|
|
44
|
+
|
|
45
|
+
.chip-input {
|
|
46
|
+
display: flex; flex-wrap: wrap; gap: 0.5rem; padding: 0.5rem;
|
|
47
|
+
background: var(--c-bg-elev, rgba(0,0,0,0.1));
|
|
48
|
+
border: 1px solid var(--c-border, rgba(255,255,255,0.1));
|
|
49
|
+
border-radius: var(--r-md, 10px);
|
|
50
|
+
transition: border-color 0.2s;
|
|
51
|
+
}
|
|
52
|
+
.chip-input:focus-within { border-color: var(--c-primary, #6366f1); }
|
|
53
|
+
|
|
54
|
+
.chip-input__list { display: flex; flex-wrap: wrap; gap: 0.5rem; }
|
|
55
|
+
|
|
56
|
+
.chip {
|
|
57
|
+
background: var(--c-primary, #6366f1);
|
|
58
|
+
color: #fff;
|
|
59
|
+
padding: 0.2rem 0.6rem;
|
|
60
|
+
border-radius: var(--r-sm, 6px);
|
|
61
|
+
font-size: 0.8rem;
|
|
62
|
+
display: flex; align-items: center; gap: 0.4rem;
|
|
63
|
+
}
|
|
64
|
+
.chip button {
|
|
65
|
+
background: none; border: none; color: #fff; cursor: pointer;
|
|
66
|
+
font-size: 1.1rem; line-height: 1; padding: 0;
|
|
67
|
+
opacity: 0.8; transition: opacity 0.2s;
|
|
68
|
+
}
|
|
69
|
+
.chip button:hover { opacity: 1; }
|
|
70
|
+
|
|
71
|
+
.chip-input__field {
|
|
72
|
+
background: none; border: none; outline: none;
|
|
73
|
+
color: var(--c-text-1, #fff); flex: 1; min-width: 100px;
|
|
74
|
+
padding: 0.2rem; font-family: inherit; font-size: 0.9rem;
|
|
75
|
+
}
|
|
13
76
|
</style>
|
|
77
|
+
|
|
78
|
+
<script>
|
|
79
|
+
// Simplified client-side logic for adding/removing chips
|
|
80
|
+
document.querySelectorAll('[data-chip-input]').forEach(container => {
|
|
81
|
+
const list = container.querySelector('[data-chip-list]');
|
|
82
|
+
const input = container.querySelector('[data-chip-field]') as HTMLInputElement;
|
|
83
|
+
const name = "tags"; // Should ideally be passed from props but hidden inputs solve this for now
|
|
84
|
+
|
|
85
|
+
const addChip = (value: string) => {
|
|
86
|
+
if (!value.trim() || !list) return;
|
|
87
|
+
const chip = document.createElement('span');
|
|
88
|
+
chip.className = 'chip';
|
|
89
|
+
chip.innerHTML = `${value}<button type="button" aria-label="Remove ${value}" data-remove-chip>×</button>`;
|
|
90
|
+
|
|
91
|
+
const hidden = document.createElement('input');
|
|
92
|
+
hidden.type = 'hidden';
|
|
93
|
+
hidden.name = 'chips[]';
|
|
94
|
+
hidden.value = value;
|
|
95
|
+
chip.appendChild(hidden);
|
|
96
|
+
|
|
97
|
+
list.appendChild(chip);
|
|
98
|
+
input.value = '';
|
|
99
|
+
input.placeholder = '';
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
input?.addEventListener('keydown', (e) => {
|
|
103
|
+
if (e.key === 'Enter') {
|
|
104
|
+
e.preventDefault();
|
|
105
|
+
addChip(input.value);
|
|
106
|
+
}
|
|
107
|
+
if (e.key === 'Backspace' && !input.value && list?.lastElementChild) {
|
|
108
|
+
list.removeChild(list.lastElementChild);
|
|
109
|
+
if (list.children.length === 0) input.placeholder = "Add tag...";
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
container.addEventListener('click', (e) => {
|
|
114
|
+
const target = e.target as HTMLElement;
|
|
115
|
+
if (target.hasAttribute('data-remove-chip')) {
|
|
116
|
+
target.closest('.chip')?.remove();
|
|
117
|
+
if (list?.children.length === 0) input.placeholder = "Add tag...";
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
</script>
|
|
@@ -1,13 +1,60 @@
|
|
|
1
1
|
---
|
|
2
|
+
/**
|
|
3
|
+
* ColorPickerInput — A specialized input for selecting hex colors with a circular preview.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} label - Input labeling title.
|
|
6
|
+
* @param {string} id - HTML ID for the picker.
|
|
7
|
+
* @param {string} value - Default starting color value (hex). Default is '#6366f1'.
|
|
8
|
+
* @param {string} name - HTML name binding.
|
|
9
|
+
*/
|
|
10
|
+
interface Props {
|
|
11
|
+
label: string;
|
|
12
|
+
id: string;
|
|
13
|
+
value?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { label, id, value = "#6366f1", name } = Astro.props;
|
|
2
18
|
---
|
|
19
|
+
|
|
3
20
|
<div class="color-picker-wrap">
|
|
4
|
-
<
|
|
5
|
-
|
|
21
|
+
<div class="color-input-container">
|
|
22
|
+
<input type="color" class="color-input" {id} {name} {value} />
|
|
23
|
+
<label for={id} class="color-label">{label}</label>
|
|
24
|
+
</div>
|
|
25
|
+
<span class="color-value" data-color-value>{value}</span>
|
|
6
26
|
</div>
|
|
27
|
+
|
|
7
28
|
<style>
|
|
8
|
-
.color-picker-wrap { display: flex; align-items: center; gap: 1rem; }
|
|
9
|
-
.color-input {
|
|
29
|
+
.color-picker-wrap { display: flex; align-items: center; justify-content: space-between; gap: 1rem; background: var(--c-bg-elev, rgba(255,255,255,0.03)); padding: var(--sp-3, 0.75rem) var(--sp-4, 1rem); border-radius: var(--r-md, 12px); border: 1px solid var(--c-border, rgba(255,255,255,0.1)); }
|
|
30
|
+
.color-input-container { display: flex; align-items: center; gap: 1rem; }
|
|
31
|
+
|
|
32
|
+
.color-input {
|
|
33
|
+
-webkit-appearance: none;
|
|
34
|
+
border: none;
|
|
35
|
+
width: 38px; height: 38px;
|
|
36
|
+
border-radius: var(--r-full, 50%);
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
background: transparent;
|
|
39
|
+
padding: 0;
|
|
40
|
+
}
|
|
10
41
|
.color-input::-webkit-color-swatch-wrapper { padding: 0; }
|
|
11
|
-
.color-input::-webkit-color-swatch {
|
|
12
|
-
|
|
42
|
+
.color-input::-webkit-color-swatch {
|
|
43
|
+
border: 2px solid rgba(255,255,255,0.2);
|
|
44
|
+
border-radius: 50%;
|
|
45
|
+
box-shadow: 0 4px 10px rgba(0,0,0,0.2);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.color-label { font-size: 0.9rem; color: var(--c-text-1, #e2e8f0); font-weight: 500; cursor: pointer; }
|
|
49
|
+
.color-value { font-size: 0.8rem; color: var(--c-text-2, #64748b); font-family: monospace; text-transform: uppercase; letter-spacing: 0.05em; }
|
|
13
50
|
</style>
|
|
51
|
+
|
|
52
|
+
<script>
|
|
53
|
+
document.querySelectorAll('.color-input').forEach(input => {
|
|
54
|
+
const parent = input.closest('.color-picker-wrap');
|
|
55
|
+
const display = parent?.querySelector('[data-color-value]');
|
|
56
|
+
input.addEventListener('input', (e) => {
|
|
57
|
+
if (display) display.textContent = (e.target as HTMLInputElement).value;
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
</script>
|
|
@@ -1,11 +1,64 @@
|
|
|
1
1
|
---
|
|
2
|
+
/**
|
|
3
|
+
* CurrencyInput — A numeric input prefixed with a currency symbol for financial data entry.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} label - Input labeling title.
|
|
6
|
+
* @param {string} id - HTML ID for attribution.
|
|
7
|
+
* @param {string} symbol - Currency symbol to display (e.g. "$", "€"). Default is "$".
|
|
8
|
+
* @param {number} value - Pre-filled numeric value.
|
|
9
|
+
* @param {string} name - HTML name binding.
|
|
10
|
+
* @param {number} step - Numeric increment. Default is 0.01.
|
|
11
|
+
*/
|
|
12
|
+
interface Props {
|
|
13
|
+
label: string;
|
|
14
|
+
id: string;
|
|
15
|
+
symbol?: string;
|
|
16
|
+
value?: number;
|
|
17
|
+
name?: string;
|
|
18
|
+
step?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { label, id, symbol = "$", value = 0.00, name, step = 0.01 } = Astro.props;
|
|
2
22
|
---
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<
|
|
23
|
+
|
|
24
|
+
<div class="curr-input-container">
|
|
25
|
+
<label for={id} class="curr-label">{label}</label>
|
|
26
|
+
<div class="curr-wrap">
|
|
27
|
+
<span class="curr-symbol">{symbol}</span>
|
|
28
|
+
<input type="number" {id} {name} {step} value={value.toFixed(2)} class="curr-field" />
|
|
29
|
+
</div>
|
|
6
30
|
</div>
|
|
31
|
+
|
|
7
32
|
<style>
|
|
8
|
-
.curr-
|
|
9
|
-
.
|
|
10
|
-
|
|
33
|
+
.curr-input-container { display: flex; flex-direction: column; gap: var(--sp-2, 0.5rem); width: 100%; }
|
|
34
|
+
.curr-label { font-size: 0.85rem; font-weight: 600; color: var(--c-text-2, #94a3b8); margin-left: 0.5rem; }
|
|
35
|
+
|
|
36
|
+
.curr-wrap {
|
|
37
|
+
display: flex; align-items: center;
|
|
38
|
+
background: var(--c-bg-elev, rgba(255,255,255,0.05));
|
|
39
|
+
border-radius: var(--r-md, 12px);
|
|
40
|
+
border: 1px solid var(--c-border, rgba(255,255,255,0.1));
|
|
41
|
+
overflow: hidden;
|
|
42
|
+
transition: border-color 0.2s;
|
|
43
|
+
}
|
|
44
|
+
.curr-wrap:focus-within { border-color: var(--c-primary, #6366f1); }
|
|
45
|
+
|
|
46
|
+
.curr-symbol {
|
|
47
|
+
padding: 0.8rem 1rem;
|
|
48
|
+
background: rgba(255,255,255,0.05);
|
|
49
|
+
color: var(--c-text-2, #94a3b8);
|
|
50
|
+
font-weight: 700; border-right: 1px solid var(--c-border, rgba(255,255,255,0.1));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.curr-field {
|
|
54
|
+
background: none; border: none;
|
|
55
|
+
padding: 0.8rem 1rem;
|
|
56
|
+
color: var(--c-text-1, #fff);
|
|
57
|
+
font-size: 1.1rem; width: 100%; outline: none;
|
|
58
|
+
font-family: inherit; font-weight: 600;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Remove number spins */
|
|
62
|
+
.curr-field::-webkit-inner-spin-button,
|
|
63
|
+
.curr-field::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
|
|
11
64
|
</style>
|
|
@@ -1,13 +1,65 @@
|
|
|
1
1
|
---
|
|
2
|
+
/**
|
|
3
|
+
* CustomRadioGroup — A group of styled radio buttons for vertical or horizontal options.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} label - Optional title for the fieldset.
|
|
6
|
+
* @param {string} name - Common HTML name for the radio group.
|
|
7
|
+
* @param {Array<{label: string, value: string, checked?: boolean}>} options - List of choices.
|
|
8
|
+
* @param {boolean} horizontal - Layout orientation. Default is false (vertical).
|
|
9
|
+
*/
|
|
10
|
+
interface Props {
|
|
11
|
+
label?: string;
|
|
12
|
+
name: string;
|
|
13
|
+
options: Array<{ label: string; value: string; checked?: boolean }>;
|
|
14
|
+
horizontal?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { label, name, options = [], horizontal = false } = Astro.props;
|
|
2
18
|
---
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
19
|
+
|
|
20
|
+
<fieldset class:list={["radio-group", { "radio-group--horizontal": horizontal }]}>
|
|
21
|
+
{label && <legend class="radio-group-legend">{label}</legend>}
|
|
22
|
+
<div class="radio-items">
|
|
23
|
+
{options.map((opt, i) => (
|
|
24
|
+
<label class="radio-item">
|
|
25
|
+
<input type="radio" name={name} value={opt.value} checked={opt.checked} />
|
|
26
|
+
<span class="radio-circle" aria-hidden="true"></span>
|
|
27
|
+
<span class="radio-label">{opt.label}</span>
|
|
28
|
+
</label>
|
|
29
|
+
))}
|
|
30
|
+
</div>
|
|
31
|
+
</fieldset>
|
|
32
|
+
|
|
7
33
|
<style>
|
|
8
|
-
.radio-group {
|
|
9
|
-
.radio-
|
|
10
|
-
|
|
11
|
-
.radio-
|
|
12
|
-
.radio-
|
|
34
|
+
.radio-group { border: none; padding: 0; margin: 0; width: 100%; }
|
|
35
|
+
.radio-group-legend { font-size: 0.85rem; font-weight: 600; color: var(--c-text-2, #94a3b8); margin-bottom: var(--sp-3, 0.75rem); margin-left: 0.5rem; }
|
|
36
|
+
|
|
37
|
+
.radio-items { display: flex; flex-direction: column; gap: var(--sp-3, 0.8rem); }
|
|
38
|
+
.radio-group--horizontal .radio-items { flex-direction: row; flex-wrap: wrap; gap: var(--sp-6, 1.5rem); }
|
|
39
|
+
|
|
40
|
+
.radio-item { display: flex; align-items: center; gap: 0.75rem; cursor: pointer; color: var(--c-text-2, #94a3b8); transition: 0.2s; user-select: none; }
|
|
41
|
+
|
|
42
|
+
.radio-item input { appearance: none; display: none; }
|
|
43
|
+
|
|
44
|
+
.radio-circle {
|
|
45
|
+
width: 20px; height: 20px;
|
|
46
|
+
border: 2px solid var(--c-border, #334155);
|
|
47
|
+
border-radius: var(--r-full, 50%);
|
|
48
|
+
position: relative; cursor: pointer; transition: 0.2s;
|
|
49
|
+
background: var(--c-bg-elev, rgba(255,255,255,0.02));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.radio-item:hover .radio-circle { border-color: var(--c-primary-light, #818cf8); }
|
|
53
|
+
|
|
54
|
+
.radio-circle::after {
|
|
55
|
+
content: ''; position: absolute; inset: 4px;
|
|
56
|
+
background: var(--c-primary, #6366f1);
|
|
57
|
+
border-radius: 50%; opacity: 0; transform: scale(0.5); transition: 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.radio-item input:checked + .radio-circle { border-color: var(--c-primary, #6366f1); box-shadow: 0 0 10px rgba(99, 102, 241, 0.2); }
|
|
61
|
+
.radio-item input:checked + .radio-circle::after { opacity: 1; transform: scale(1); }
|
|
62
|
+
|
|
63
|
+
.radio-label { font-size: 0.95rem; }
|
|
64
|
+
.radio-item input:checked ~ .radio-label { color: var(--c-text-1, #fff); font-weight: 600; }
|
|
13
65
|
</style>
|