diff --git a/animata/section/feature-grid-hover-reveal.stories.tsx b/animata/section/feature-grid-hover-reveal.stories.tsx new file mode 100644 index 00000000..24a1b22a --- /dev/null +++ b/animata/section/feature-grid-hover-reveal.stories.tsx @@ -0,0 +1,112 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Brain, Database, Lock, Rocket } from "lucide-react"; +import FeatureGridHoverReveal, { + type FeatureGridProps, +} from "@/animata/section/feature-grid-hover-reveal"; + +const meta = { + title: "Section/Feature Grid Hover Reveal", + component: FeatureGridHoverReveal, + parameters: { + layout: "fullscreen", + }, + tags: ["autodocs"], + argTypes: { + columns: { + control: "select", + options: [2, 3], + description: "Number of columns in the grid", + }, + title: { + control: "text", + description: "Section heading", + }, + subtitle: { + control: "text", + description: "Section subheading", + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: {}, + render: (args: FeatureGridProps) => ( +
+ +
+ ), +}; + +export const TwoColumn: Story = { + args: { + columns: 2, + title: "Built for scale", + subtitle: "Four core capabilities that grow with your team.", + features: [ + { + icon: , + title: "Instant Deploy", + description: + "Push to production in seconds with zero-downtime deployments and automatic rollbacks.", + }, + { + icon: , + title: "Zero-Trust Security", + description: "Every request is authenticated and authorised. No implicit trust, ever.", + }, + { + icon: , + title: "Managed Database", + description: + "Fully managed Postgres with automatic backups, point-in-time recovery, and read replicas.", + }, + { + icon: , + title: "AI-Powered Insights", + description: + "Surface anomalies and opportunities automatically using built-in machine learning.", + }, + ], + }, + render: (args: FeatureGridProps) => ( +
+ +
+ ), +}; + +export const CustomContent: Story = { + args: { + columns: 3, + title: "Why teams choose us", + subtitle: "Purpose-built features that eliminate complexity and ship value faster.", + features: [ + { + icon: , + title: "One-Click Setup", + description: + "Go from sign-up to production in under five minutes with our guided onboarding.", + }, + { + icon: , + title: "Smart Automation", + description: + "Let AI handle the repetitive work so your team can focus on what actually matters.", + }, + { + icon: , + title: "Reliable Storage", + description: + "99.999% uptime SLA with geo-redundant storage across three availability zones.", + }, + ], + }, + render: (args: FeatureGridProps) => ( +
+ +
+ ), +}; diff --git a/animata/section/feature-grid-hover-reveal.tsx b/animata/section/feature-grid-hover-reveal.tsx new file mode 100644 index 00000000..486d7a48 --- /dev/null +++ b/animata/section/feature-grid-hover-reveal.tsx @@ -0,0 +1,162 @@ +"use client"; + +import { BarChart, Code, Globe, Layers, Shield, Zap } from "lucide-react"; +import { useEffect, useState } from "react"; +import { cn } from "@/lib/utils"; + +export interface FeatureItem { + icon: React.ReactNode; + title: string; + description: string; +} + +export interface FeatureGridProps { + features?: FeatureItem[]; + columns?: 2 | 3; + title?: string; + subtitle?: string; +} + +const defaultFeatures: FeatureItem[] = [ + { + icon: , + title: "Lightning Fast", + description: + "Optimised for speed at every layer. Sub-second load times keep your users engaged and your conversion rate high.", + }, + { + icon: , + title: "Enterprise Security", + description: + "SOC 2 Type II certified with end-to-end encryption, SSO, and role-based access controls built in from day one.", + }, + { + icon: , + title: "Advanced Analytics", + description: + "Real-time dashboards and custom reports give your team the clarity to make confident, data-driven decisions.", + }, + { + icon: , + title: "Global CDN", + description: + "Content delivered from 200+ edge locations worldwide so every user gets a fast, reliable experience.", + }, + { + icon: , + title: "Developer First", + description: + "Powerful REST and GraphQL APIs, webhooks, and an SDK for every major language. Automate anything.", + }, + { + icon: , + title: "Seamless Integrations", + description: + "Connect to 200+ tools including Slack, Salesforce, and Stripe in minutes — no custom code required.", + }, +]; + +const columnClass: Record<2 | 3, string> = { + 2: "md:grid-cols-2", + 3: "md:grid-cols-2 lg:grid-cols-3", +}; + +export default function FeatureGridHoverReveal({ + features = defaultFeatures, + columns = 3, + title = "Everything you need to ship faster", + subtitle = "A complete platform built for modern teams — from zero to production without the growing pains.", +}: FeatureGridProps) { + const [prefersReducedMotion, setPrefersReducedMotion] = useState(false); + + useEffect(() => { + const mq = window.matchMedia("(prefers-reduced-motion: reduce)"); + setPrefersReducedMotion(mq.matches); + const handler = (e: MediaQueryListEvent) => setPrefersReducedMotion(e.matches); + mq.addEventListener("change", handler); + return () => mq.removeEventListener("change", handler); + }, []); + + const safeFeatures = Array.isArray(features) ? features : defaultFeatures; + + return ( +
+
+ {(title || subtitle) && ( +
+ {title && ( +

+ {title} +

+ )} + {subtitle && ( +

{subtitle}

+ )} +
+ )} + +
+ {safeFeatures.map((feature, index) => ( + + ))} +
+
+
+ ); +} + +interface FeatureCardProps { + feature: FeatureItem; + prefersReducedMotion: boolean; +} + +function FeatureCard({ feature, prefersReducedMotion }: FeatureCardProps) { + const [hovered, setHovered] = useState(false); + + return ( +
setHovered(true)} + onMouseLeave={() => setHovered(false)} + onFocus={() => setHovered(true)} + onBlur={() => setHovered(false)} + className={cn( + "group relative flex flex-col gap-4 rounded-2xl border p-6", + "bg-card text-card-foreground", + "shadow-sm transition-shadow duration-300", + !prefersReducedMotion && "transition-transform duration-300", + !prefersReducedMotion && hovered && "-translate-y-1.5 shadow-md", + hovered ? "border-primary/40" : "border-border", + )} + > +
+ {feature.icon} +
+ +
+

{feature.title}

+

{feature.description}

+
+ + {!prefersReducedMotion && ( +
+ ); +} diff --git a/content/docs/section/feature-grid-hover-reveal.mdx b/content/docs/section/feature-grid-hover-reveal.mdx new file mode 100644 index 00000000..2856a4de --- /dev/null +++ b/content/docs/section/feature-grid-hover-reveal.mdx @@ -0,0 +1,71 @@ +--- +title: Feature Grid Hover Reveal +description: A responsive SaaS feature section with icon cards, hover lift, border highlight, and icon scale micro-interactions. +author: KeenIsHere +published: true +--- + + + +## Overview + +Feature Grid Hover Reveal is a polished section component for SaaS landing pages. It displays a grid of feature cards with icon, title, and description. On hover, cards lift, the border highlights, and the icon scales up using only transform and opacity. Animations are skipped when prefers-reduced-motion is enabled. + +## Features + +- Responsive grid: 1 column mobile, 2 tablet, 3 desktop +- Hover lift: -translate-y-1.5 with 300ms transition +- Icon scale: scale-115 with 200ms transition +- Border highlight: border-primary/40 on hover +- Ring overlay: inset ring fades in via opacity +- prefers-reduced-motion: all animations off when set +- Dark mode: full Tailwind token support +- Configurable: 2 or 3 column layout via prop +- Zero-props render: 6 default SaaS feature items built in + +## Usage + +```tsx +import FeatureGridHoverReveal from "@/animata/section/feature-grid-hover-reveal"; + +export default function Page() { + return ; +} +``` + +## Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| features | FeatureItem[] | 6 built-in items | Array of feature cards | +| columns | 2 or 3 | 3 | Grid column count | +| title | string | Built-in heading | Section title | +| subtitle | string | Built-in subtitle | Section subtitle | + +## Types + +```typescript +interface FeatureItem { + icon: React.ReactNode; + title: string; + description: string; +} + +interface FeatureGridProps { + features?: FeatureItem[]; + columns?: 2 | 3; + title?: string; + subtitle?: string; +} +``` + +## Accessibility + +- Semantic section and article elements +- Hover state triggered on focus and blur for keyboard access +- Decorative ring span has aria-hidden set to true +- Icon container meets 44x44px minimum touch target +- All motion respects prefers-reduced-motion +## Credits + +Built by [Keen Sha](https://github.com/KeenIsHere).