# About Us
*URL: https://www.grettech.com/components/about-us*

An About section with mission and vision cards, a soft spotlight background and a grid of colour-coded value cards.

- Mission and vision cards with animated border beams
- Value cards with a colour-coded hover glow
- Spotlight background
- Scroll-triggered entrance animations

## Install with the shadcn CLI
```bash
npx shadcn@latest add https://www.grettech.com/api/registry/about-us
```
With its demo: `npx shadcn@latest add https://www.grettech.com/api/registry/about-us-demo`

**Dependencies:** npm: clsx, tailwind-merge, motion, lucide-react, class-variance-authority

## Manual installation
**Step 1: Install dependencies**
Install the packages this component uses and the shadcn/ui components it builds on. It also needs the `cn` helper in `lib/utils.ts`, which `npx shadcn@latest init` adds.

```bash
npm install clsx tailwind-merge motion lucide-react class-variance-authority
```

**Step 2: Copy the source code**
Add these files to your project components directory.

File: `components/ui/about-us.tsx`
```tsx
"use client"
import * as React from "react"

import { BorderBeam } from "@/components/ui/border-beam"
import { PulseCard } from "@/components/ui/pulse-card"
import { Spotlight } from "@/components/ui/spotlight"
import { cn } from "@/lib/utils"
import { Rocket, Target } from "lucide-react"
import { motion } from "motion/react"

export interface AboutValueItem {
  title: string
  description: string
  icon: React.ReactNode
  color?: "emerald" | "blue" | "indigo" | "amber" | "slate"
}

export interface AboutUsProps extends React.HTMLAttributes<HTMLDivElement> {
  title?: string
  subtitle?: string
  mission?: string
  vision?: string
  valuesTitle?: string
  valuesSubtitle?: string
  values: AboutValueItem[]
}

// --- SUB-COMPONENTS ---

const AboutUsHeader = ({
  title,
  subtitle,
}: {
  title: string
  subtitle: string
}) => (
  <motion.div
    initial={{ opacity: 0, y: 20 }}
    whileInView={{ opacity: 1, y: 0 }}
    viewport={{ once: true }}
    transition={{ duration: 0.8, ease: "easeOut" }}
    className="mx-auto mb-16 max-w-2xl text-center"
  >
    <h2 className="mb-4 bg-linear-to-b from-foreground to-foreground/70 bg-clip-text text-4xl font-bold tracking-tight text-balance text-transparent md:text-5xl lg:text-6xl">
      {title}
    </h2>
    <p className="mx-auto max-w-2xl text-base text-pretty text-muted-foreground md:text-lg">
      {subtitle}
    </p>
  </motion.div>
)

const AboutUsStatementCard = ({
  icon,
  label,
  text,
  reverse,
}: {
  icon: React.ReactNode
  label: string
  text: string
  reverse?: boolean
}) => (
  <motion.div
    whileHover={{ y: -4 }}
    transition={{ type: "spring", stiffness: 300, damping: 20 }}
    className="group relative flex h-full flex-col overflow-hidden rounded-2xl border border-border/60 bg-card/70 p-8 shadow-sm backdrop-blur-xl transition-shadow duration-500 hover:shadow-[0_20px_40px_-12px_rgba(0,0,0,0.12)] md:p-10"
  >
    <BorderBeam
      duration={8}
      size={300}
      reverse={reverse}
      className="from-transparent via-primary/40 to-transparent"
    />
    <div className="mb-6 inline-flex size-14 items-center justify-center rounded-2xl border border-primary/15 bg-primary/10 text-primary [&_svg]:size-7">
      {icon}
    </div>
    <h3 className="mb-3 text-2xl font-semibold tracking-tight text-foreground md:text-3xl">
      {label}
    </h3>
    <p className="text-base leading-relaxed text-pretty text-muted-foreground md:text-lg">
      {text}
    </p>
  </motion.div>
)

const AboutUsValuesGrid = ({
  title,
  subtitle,
  values,
}: {
  title: string
  subtitle: string
  values: AboutValueItem[]
}) => {
  const containerVariants = {
    hidden: { opacity: 0 },
    visible: {
      opacity: 1,
      transition: { staggerChildren: 0.15, delayChildren: 0.2 },
    },
  }

  const itemVariants = {
    hidden: { opacity: 0, y: 30, scale: 0.95 },
    visible: {
      opacity: 1,
      y: 0,
      scale: 1,
      transition: { type: "spring" as const, stiffness: 100, damping: 20 },
    },
  }

  return (
    <div className="mb-24">
      <motion.div
        initial={{ opacity: 0, y: 20 }}
        whileInView={{ opacity: 1, y: 0 }}
        viewport={{ once: true, amount: 0.1 }}
        transition={{ duration: 0.6, ease: "easeOut" }}
        className="mb-12 text-center"
      >
        <h2 className="mb-4 bg-linear-to-b from-foreground to-foreground/70 bg-clip-text text-4xl font-bold tracking-tight text-balance text-transparent md:text-5xl lg:text-6xl">
          {title}
        </h2>
        <p className="mx-auto mt-4 max-w-2xl text-base text-pretty text-muted-foreground md:text-lg">
          {subtitle}
        </p>
      </motion.div>

      <motion.div
        variants={containerVariants}
        initial="hidden"
        whileInView="visible"
        viewport={{ once: true, amount: 0.1 }}
        className="grid gap-6 md:grid-cols-2 xl:grid-cols-4"
      >
        {values.map((value, i) => (
          <motion.div
            key={`${value.title}-${i}`}
            variants={itemVariants}
            className="h-full"
          >
            <PulseCard
              icon={value.icon}
              title={value.title}
              description={value.description}
              variant={value.color || "blue"}
              glowEffect={true}
              size="lg"
              className="h-full"
            />
          </motion.div>
        ))}
      </motion.div>
    </div>
  )
}

// --- MAIN COMPONENT ---

export const AboutUs = React.forwardRef<HTMLElement, AboutUsProps>(
  (
    {
      title = "About Us",
      subtitle = "We craft modern websites and mobile apps that help businesses thrive in the digital age.",
      mission = "We aim to empower businesses through innovative technology, fostering growth and efficiency in a rapidly evolving digital landscape.",
      vision = "To be the leading catalyst for digital transformation, setting new standards in web and app development globally.",
      valuesTitle = "Our Core Values",
      valuesSubtitle = "What drives us forward",
      values,
      className,
      ...props
    },
    ref
  ) => {
    return (
      <section
        ref={ref}
        className={cn(
          "relative w-full overflow-hidden bg-secondary/20 py-24 md:py-32 dark:bg-secondary/10",
          className
        )}
        {...props}
      >
        <Spotlight
          gradientFirst="radial-gradient(68.54% 68.72% at 55.02% 31.46%, hsla(225, 100%, 50%, 0.08) 0, hsla(230, 100%, 55%, 0.04) 50%, hsla(225, 100%, 45%, 0) 80%)"
          gradientSecond="radial-gradient(50% 50% at 50% 50%, hsla(220, 100%, 85%, 0.08) 0, hsla(225, 100%, 55%, 0.04) 80%, transparent 100%)"
          gradientThird="radial-gradient(50% 50% at 50% 50%, hsla(220, 100%, 85%, 0.06) 0, hsla(215, 100%, 85%, 0.06) 80%, transparent 100%)"
        />

        <div className="relative z-10 container mx-auto px-4 md:px-6">
          <AboutUsHeader title={title} subtitle={subtitle} />

          <div className="relative mx-auto mb-24 max-w-7xl">
            <motion.div
              initial={{ opacity: 0, y: 40 }}
              whileInView={{ opacity: 1, y: 0 }}
              viewport={{ once: true, amount: 0.1 }}
              transition={{ duration: 0.8, delay: 0.2, ease: "easeOut" }}
              className="relative z-10 grid gap-6 md:grid-cols-2"
            >
              <AboutUsStatementCard
                icon={<Rocket />}
                label="Our Mission"
                text={mission}
              />
              <AboutUsStatementCard
                icon={<Target />}
                label="Our Vision"
                text={vision}
                reverse
              />
            </motion.div>
          </div>

          <AboutUsValuesGrid
            title={valuesTitle}
            subtitle={valuesSubtitle}
            values={values}
          />
        </div>
      </section>
    )
  }
)
AboutUs.displayName = "AboutUs"

```

File: `components/ui/border-beam.tsx`
```tsx
import { cn } from "@/lib/utils"
import * as React from "react"

export interface BorderBeamProps extends React.HTMLAttributes<HTMLDivElement> {
  /**
   * Length of the beam; larger values give a longer arc of light.
   */
  size?: number
  /**
   * Seconds per lap.
   */
  duration?: number
  /**
   * Seconds to start ahead by (a negative delay), to offset several beams.
   */
  delay?: number
  /**
   * Colour at the head of the beam. Ignored when className sets from-* /
   * via-* / to-* gradient colours.
   */
  colorFrom?: string
  /**
   * Colour along the body of the beam.
   */
  colorTo?: string
  /**
   * Classes for the beam, e.g. "from-transparent via-primary/40 to-transparent".
   */
  className?: string
  style?: React.CSSProperties
  /**
   * Lap counter-clockwise.
   */
  reverse?: boolean
  /**
   * Starting position along the lap, 0–100.
   */
  initialOffset?: number
}

/**
 * A beam of light running around the border of its parent (give the parent
 * position: relative and a border radius).
 *
 * A conic gradient behind a border-shaped mask, turned with a CSS transform:
 * the GPU runs it, so it costs no JavaScript and no repaints per frame.
 */
export const BorderBeam = React.forwardRef<HTMLDivElement, BorderBeamProps>(
  (
    {
      className,
      size = 50,
      delay = 0,
      duration = 6,
      colorFrom = "#4f7df5",
      colorTo = "#22b8cf",
      style,
      reverse = false,
      initialOffset = 0,
      ...props
    },
    ref
  ) => {
    // Gradient classes in className win; otherwise use the colour props
    const classColors = /(^|\s)(from|via|to)-/.test(className ?? "")
    // Longer beams sweep a wider arc
    const arc = Math.min(140, Math.max(20, size * 0.35))

    return (
      <div
        ref={ref}
        aria-hidden="true"
        className="@container-size pointer-events-none absolute inset-0 rounded-[inherit] border border-transparent mask-[linear-gradient(transparent,transparent),linear-gradient(#000,#000)] mask-intersect [mask-clip:padding-box,border-box]"
        {...props}
      >
        <div
          className={cn(
            "absolute top-1/2 left-1/2 aspect-square -translate-x-1/2 -translate-y-1/2 animate-spin motion-reduce:animate-none",
            className
          )}
          style={
            {
              // Large enough to cover the corners of any rectangle
              width: "calc(100cqw + 100cqh)",
              rotate: `${initialOffset * 3.6}deg`,
              animationDuration: `${duration}s`,
              animationDelay: `${-delay}s`,
              animationDirection: reverse ? "reverse" : "normal",
              background: `conic-gradient(from 0deg, transparent 0deg, var(--tw-gradient-to) calc(360deg - ${arc}deg), var(--tw-gradient-via) calc(360deg - ${arc / 2}deg), var(--tw-gradient-from) 360deg)`,
              ...(!classColors && {
                "--tw-gradient-from": colorFrom,
                "--tw-gradient-via": colorTo,
                "--tw-gradient-to": "transparent",
              }),
              ...style,
            } as React.CSSProperties
          }
        />
      </div>
    )
  }
)
BorderBeam.displayName = "BorderBeam"

```

File: `components/ui/pulse-card.tsx`
```tsx
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"

const pulseCardVariants = cva(
  [
    "group/pulse relative w-full overflow-hidden rounded-2xl border border-border/50",
    "transition-transform duration-300 ease-in-out hover:scale-[1.02]",
    "bg-white/80 dark:bg-white/[0.03]",
    "before:absolute before:inset-0 before:rounded-[inherit] before:content-['']",
    "before:bg-linear-to-b before:from-white/5 before:to-white/20 before:backdrop-blur-3xl",
    "dark:before:from-black/5 dark:before:to-black/20",
    "after:absolute after:inset-0 after:rounded-[inherit] after:content-['']",
    "after:bg-linear-to-b after:from-transparent after:via-transparent after:to-white/20",
    "dark:after:to-black/20",
    "shadow-[0px_3px_8px_rgba(0,0,0,0.04),0px_12px_20px_rgba(0,0,0,0.08)]",
    "hover:shadow-[0px_5px_15px_rgba(0,0,0,0.03),0px_25px_35px_rgba(0,0,0,0.2)]",
    "dark:shadow-[0px_3px_8px_rgba(0,0,0,0.08),0px_12px_20px_rgba(0,0,0,0.15)]",
    "dark:hover:shadow-[0px_5px_15px_rgba(0,0,0,0.06),0px_25px_35px_rgba(0,0,0,0.4)]",
  ],
  {
    variants: {
      variant: {
        emerald: "[--card-color:var(--color-emerald-500)]",
        blue: "[--card-color:var(--color-blue-500)]",
        indigo: "[--card-color:var(--color-indigo-500)]",
        amber: "[--card-color:var(--color-amber-500)]",
        slate: "[--card-color:var(--color-slate-500)]",
      },
      size: {
        sm: "p-6 pt-12",
        md: "p-8 pt-16",
        lg: "p-6 pt-16",
      },
      glowEffect: {
        true: "hover:before:bg-[color-mix(in_srgb,var(--card-color)_10%,transparent)]",
        false: "",
      },
    },
    defaultVariants: {
      variant: "emerald",
      size: "md",
      glowEffect: false,
    },
  }
)

const pulseCardIconVariants = cva(
  "relative z-1 block text-black/60 transition-colors duration-300 group-hover/pulse:text-[var(--card-color)] dark:text-zinc-400",
  {
    variants: {
      size: {
        sm: "h-5 w-5",
        md: "h-6 w-6",
        lg: "h-7 w-7",
      },
    },
    defaultVariants: { size: "md" },
  }
)

const pulseCardTitleVariants = cva(
  "font-medium text-black/80 transition-colors duration-300 group-hover/pulse:text-[var(--card-color)] dark:text-white/80",
  {
    variants: {
      size: {
        sm: "text-sm",
        md: "text-base",
        lg: "text-lg",
      },
    },
    defaultVariants: { size: "md" },
  }
)

const pulseCardDescVariants = cva(
  "mt-1 text-black/60 transition-colors duration-300 dark:text-white/60",
  {
    variants: {
      size: {
        sm: "text-xs",
        md: "text-[15px]",
        lg: "text-base",
      },
    },
    defaultVariants: { size: "md" },
  }
)

export interface PulseCardProps
  extends
    React.HTMLAttributes<HTMLDivElement>,
    VariantProps<typeof pulseCardVariants> {
  icon: React.ReactNode
  title: string
  description: string
}

const PulseCard = React.forwardRef<HTMLDivElement, PulseCardProps>(
  (
    {
      className,
      icon,
      title,
      description,
      variant,
      size,
      glowEffect,
      ...props
    },
    ref
  ) => {
    return (
      <div
        ref={ref}
        className={cn(
          pulseCardVariants({ variant, size, glowEffect, className })
        )}
        {...props}
      >
        {/* Moving Border */}
        <div
          aria-hidden="true"
          className="pointer-events-none absolute inset-0 overflow-hidden rounded-[inherit]"
          style={
            {
              WebkitMask:
                "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
              WebkitMaskComposite: "xor",
              mask: "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
              maskComposite: "exclude",
              padding: "2px",
            } as React.CSSProperties
          }
        >
          <div
            className="absolute inset-[-200%] animate-spin opacity-0 transition-opacity duration-300 group-hover/pulse:opacity-100"
            style={{
              background: `conic-gradient(from 0deg at 50% 50%, transparent 0deg, transparent 340deg, var(--card-color) 360deg)`,
              animationDuration: "4s",
            }}
          />
        </div>

        {/* Icon Wrapper */}
        <div className="relative z-40 table rounded-xl pb-2 transition-transform duration-300 ease-in-out group-hover/pulse:scale-110">
          <span
            className={cn(
              "absolute inset-[4.5px] rounded-[inherit]",
              "bg-linear-to-b from-black/5 to-black/10 backdrop-blur-3xl",
              "dark:from-white/10 dark:to-white/5",
              "transition-all duration-300"
            )}
          />
          <span className={cn(pulseCardIconVariants({ size }))}>{icon}</span>
        </div>

        {/* Content */}
        <div className="relative z-30 mt-2">
          <h3 className={cn(pulseCardTitleVariants({ size }))}>{title}</h3>
          <p className={cn(pulseCardDescVariants({ size }), "text-pretty")}>
            {description}
          </p>
        </div>

        {/* Shine Effect */}
        <div
          aria-hidden="true"
          className="pointer-events-none absolute inset-0 z-20 overflow-hidden rounded-[inherit] opacity-100 transition-all duration-500"
        >
          <div
            className="absolute bottom-[55%] left-1/2 aspect-square w-[200%] -translate-x-1/2 rounded-[50%]"
            style={{
              background: `conic-gradient(from 205deg, transparent 0deg, var(--card-color) 20deg, color-mix(in srgb, var(--card-color) 30%, transparent) 280deg, transparent 360deg)`,
              filter: "blur(40px)",
            }}
          />
        </div>
      </div>
    )
  }
)
PulseCard.displayName = "PulseCard"

export { PulseCard, pulseCardVariants }

```

File: `components/ui/spotlight.tsx`
```tsx
"use client"
import * as React from "react"
import { HTMLMotionProps, motion } from "motion/react"

import { cn } from "@/lib/utils"

export interface SpotlightProps extends Omit<HTMLMotionProps<"div">, "ref"> {
  gradientFirst?: string
  gradientSecond?: string
  gradientThird?: string
  translateY?: number
  width?: number
  height?: number
  smallWidth?: number
  duration?: number
  xOffset?: number
}

export const Spotlight = React.forwardRef<HTMLDivElement, SpotlightProps>(
  (
    {
      gradientFirst = "radial-gradient(68.54% 68.72% at 55.02% 31.46%, hsla(225, 100%, 50%, 0.1) 0, hsla(230, 100%, 55%, 0.02) 50%, hsla(225, 100%, 45%, 0) 80%)",
      gradientSecond = "radial-gradient(50% 50% at 50% 50%, hsla(220, 100%, 85%, 0.06) 0, hsla(225, 100%, 55%, 0.02) 80%, transparent 100%)",
      gradientThird = "radial-gradient(50% 50% at 50% 50%, hsla(220, 100%, 85%, 0.04) 0, hsla(215, 100%, 85%, 0.04) 80%, transparent 100%)",
      translateY = -350,
      width = 560,
      height = 1380,
      smallWidth = 240,
      duration = 7,
      xOffset = 100,
      className,
      ...props
    },
    ref
  ) => {
    return (
      <motion.div
        ref={ref}
        initial={{
          opacity: 0,
        }}
        animate={{
          opacity: 1,
        }}
        transition={{
          duration: 1.5,
        }}
        className={cn(
          "pointer-events-none absolute inset-0 z-10 h-full w-full",
          className
        )}
        {...props}
      >
        <motion.div
          animate={{
            x: [0, xOffset, 0],
          }}
          transition={{
            duration,
            repeat: Infinity,
            repeatType: "reverse",
            ease: "easeInOut",
          }}
          className="pointer-events-none absolute top-0 left-0 z-0 h-screen w-screen"
        >
          <div
            style={{
              transform: `translateY(${translateY}px) rotate(-45deg)`,
              background: gradientFirst,
              width: `${width}px`,
              height: `${height}px`,
            }}
            className={`absolute top-0 left-0`}
          />

          <div
            style={{
              transform: "rotate(-45deg) translate(5%, -50%)",
              background: gradientSecond,
              width: `${smallWidth}px`,
              height: `${height}px`,
            }}
            className={`absolute top-0 left-0 origin-top-left`}
          />

          <div
            style={{
              transform: "rotate(-45deg) translate(-180%, -70%)",
              background: gradientThird,
              width: `${smallWidth}px`,
              height: `${height}px`,
            }}
            className={`absolute top-0 left-0 origin-top-left`}
          />
        </motion.div>

        <motion.div
          animate={{
            x: [0, -xOffset, 0],
          }}
          transition={{
            duration,
            repeat: Infinity,
            repeatType: "reverse",
            ease: "easeInOut",
          }}
          className="pointer-events-none absolute top-0 right-0 z-40 h-screen w-screen"
        >
          <div
            style={{
              transform: `translateY(${translateY}px) rotate(45deg)`,
              background: gradientFirst,
              width: `${width}px`,
              height: `${height}px`,
            }}
            className={`absolute top-0 right-0`}
          />

          <div
            style={{
              transform: "rotate(45deg) translate(-5%, -50%)",
              background: gradientSecond,
              width: `${smallWidth}px`,
              height: `${height}px`,
            }}
            className={`absolute top-0 right-0 origin-top-right`}
          />

          <div
            style={{
              transform: "rotate(45deg) translate(180%, -70%)",
              background: gradientThird,
              width: `${smallWidth}px`,
              height: `${height}px`,
            }}
            className={`absolute top-0 right-0 origin-top-right`}
          />
        </motion.div>
      </motion.div>
    )
  }
)
Spotlight.displayName = "Spotlight"

```

**Step 3: Framework Adjustments (Optional)**
If you are manually copying this code into a Vite or Remix project (without using the CLI), make sure to remove the `"use client";` directive from the very top of the file.

## Props
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
| `title` | `string` | `"About Us"` | No | Main heading. |
| `subtitle` | `string` | `"We craft modern websites and mobile apps that help businesses thrive in the digital age."` | No | Text under the main heading. |
| `mission` | `string` | `"We aim to empower businesses through innovative technology, fostering growth and efficiency in a rapidly evolving digital landscape."` | No | Body text of the "Our Mission" card. |
| `vision` | `string` | `"To be the leading catalyst for digital transformation, setting new standards in web and app development globally."` | No | Body text of the "Our Vision" card. |
| `valuesTitle` | `string` | `"Our Core Values"` | No | Heading above the value cards. |
| `valuesSubtitle` | `string` | `"What drives us forward"` | No | Text under the values heading. |
| `values` | `AboutValueItem[]` | - | Yes | The value cards: one column on mobile, two on tablets, four on extra-large screens. |
| `values.title` | `string` | - | Yes | Card title. |
| `values.description` | `string` | - | Yes | Card text. |
| `values.icon` | `React.ReactNode` | - | Yes | Icon at the top of the card, e.g. a lucide-react icon. |
| `values.color` | `"emerald" \| "blue" \| "indigo" \| "amber" \| "slate"` | `"blue"` | No | Hover glow colour of the card. |
| `className` | `string` | - | No | Extra classes for the root <section>. |
| `...props` | `React.HTMLAttributes<HTMLElement>` | - | No | Any other section attributes (id, style, etc.). |

## Usage
```tsx
"use client"

import { Globe, Rocket, Target, Zap } from "lucide-react"
import { AboutUs, type AboutValueItem } from "@/components/ui/about-us"

export default function AboutUsDemo() {
  const values: AboutValueItem[] = [
    {
      title: "Global Reach",
      description:
        "We design products capable of scaling across the world with zero downtime.",
      icon: <Globe className="h-6 w-6" />,
      color: "blue",
    },
    {
      title: "Rapid Deployment",
      description:
        "Ship features faster using our state-of-the-art continuous integration pipelines.",
      icon: <Rocket className="h-6 w-6" />,
      color: "indigo",
    },
    {
      title: "Precision Targeting",
      description:
        "Hit the exact demographic you need with highly specialized analytics.",
      icon: <Target className="h-6 w-6" />,
      color: "emerald",
    },
    {
      title: "Blazing Speed",
      description:
        "Unmatched performance across every device thanks to edge computing.",
      icon: <Zap className="h-6 w-6" />,
      color: "amber",
    },
  ]

  return (
    <div className="relative h-[800px] w-full overflow-hidden overflow-y-auto rounded-xl border border-dashed bg-background">
      <AboutUs
        title="About Us"
        subtitle="We craft modern websites and mobile apps that help businesses thrive in the digital age."
        mission="We aim to empower businesses through innovative technology, fostering growth and efficiency in a rapidly evolving digital landscape."
        vision="To be the leading catalyst for digital transformation, setting new standards in web and app development globally."
        valuesTitle="Our Core Values"
        valuesSubtitle="What drives us forward"
        values={values}
      />
    </div>
  )
}

```
