# Apple Hello Effect

SVG writing animation inspired by Apple’s “Hello” screen.

```tsx
"use client"

import { useState } from "react"
import { AnimatePresence } from "motion/react"

import { AppleHelloEffectEnglish } from "@/components/apple-hello-effect/apple-hello-effect-english"
import { AppleHelloEffectHindi } from "@/components/apple-hello-effect/apple-hello-effect-hindi"
import { AppleHelloEffectSpanish } from "@/components/apple-hello-effect/apple-hello-effect-spanish"
import { AppleHelloEffectVietnamese } from "@/components/apple-hello-effect/apple-hello-effect-vietnamese"

export default function AppleHelloEffectLanguagesDemo() {
  const [index, setIndex] = useState(0)

  const handleAnimationEnd = () => {
    setIndex((prevIndex) => (prevIndex + 1) % 4)
  }

  const demos = [
    <AppleHelloEffectEnglish
      key="english"
      onAnimationComplete={handleAnimationEnd}
    />,
    <AppleHelloEffectHindi
      key="hindi"
      onAnimationComplete={handleAnimationEnd}
    />,
    <AppleHelloEffectSpanish
      key="spanish"
      durationScale={0.8}
      onAnimationComplete={handleAnimationEnd}
    />,
    <AppleHelloEffectVietnamese key="vietnamese" durationScale={0.8} />,
  ]

  return <AnimatePresence mode="wait">{demos[index]}</AnimatePresence>
}

```

## Installation

<CodeTabs>
  <TabsListInstallType />

  <TabsContent value="cli">
    For English:

    ```bash
    npx shadcn@latest add @ncdai/apple-hello-effect
    ```

    For Hindi:

    ```bash
    npx shadcn@latest add @ncdai/apple-hello-effect-hindi
    ```

    For Spanish:

    ```bash
    npx shadcn@latest add @ncdai/apple-hello-effect-spanish
    ```

    For Vietnamese:

    ```bash
    npx shadcn@latest add @ncdai/apple-hello-effect-vietnamese
    ```
  </TabsContent>

  <TabsContent value="manual">
    <Steps>
      <Step>Install the following dependencies</Step>

      ```bash
      npm install motion clsx tailwind-merge
      ```

      <Step>Add a cn helper</Step>

      ```ts title="lib/utils.ts" 
      import type { ClassValue } from "clsx"
      import { clsx } from "clsx"
      import { twMerge } from "tailwind-merge"

      export const cn = (...inputs: ClassValue[]) => {
        return twMerge(clsx(inputs))
      }

      export function absoluteUrl(path: string) {
        return `${process.env.NEXT_PUBLIC_APP_URL}${path}`
      }

      ```

      <Step>Copy and paste the following code into your project</Step>

      For English:

      ```tsx title="components/apple-hello-effect-english.tsx" 
      "use client"

      import type { ComponentProps } from "react"
      import type { TargetAndTransition } from "motion/react"
      import { motion } from "motion/react"

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

      const initialProps: TargetAndTransition = {
        pathLength: 0,
        opacity: 0,
      }

      const animateProps: TargetAndTransition = {
        pathLength: 1,
        opacity: 1,
      }

      export type AppleHelloEffectEnglishProps = Omit<
        ComponentProps<typeof motion.svg>,
        "durationScale" | "onAnimationComplete"
      > & {
        /**
         * Scales the duration and delay of the handwriting animation.
         * Values below 1 speed up, values above 1 slow down.
         * @defaultValue 1
         */
        durationScale?: number
        /** Called when the full handwriting animation completes. */
        onAnimationComplete?: () => void
      }

      export function AppleHelloEffectEnglish({
        className,
        durationScale = 1,
        onAnimationComplete,
        ...props
      }: AppleHelloEffectEnglishProps) {
        const calc = (x: number) => x * durationScale

        return (
          <motion.svg
            className={cn("h-20", className)}
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 638 200"
            fill="none"
            stroke="currentColor"
            strokeWidth="14.8883"
            strokeLinecap="round"
            initial={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.5 }}
            {...props}
          >
            <title>hello</title>

            {/* h1 */}
            <motion.path
              d="M8.69214 166.553C36.2393 151.239 61.3409 131.548 89.8191 98.0295C109.203 75.1488 119.625 49.0228 120.122 31.0026C120.37 17.6036 113.836 7.43883 101.759 7.43883C88.3598 7.43883 79.9231 17.6036 74.7122 40.9363C69.005 66.5793 64.7866 96.0036 54.1166 190.356"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.8),
                ease: "easeInOut",
                opacity: { duration: 0.4 },
              }}
            />

            {/* h2, ello */}
            <motion.path
              d="M55.1624 181.135C60.6251 133.114 81.4118 98.0479 107.963 98.0479C123.844 98.0479 133.937 110.703 131.071 128.817C129.457 139.487 127.587 150.405 125.408 163.06C122.869 178.941 130.128 191.348 152.122 191.348C184.197 191.348 219.189 173.523 237.097 145.915C243.198 136.509 245.68 128.073 245.928 119.884C246.176 104.996 237.739 93.8296 222.851 93.8296C203.992 93.8296 189.6 115.17 189.6 142.465C189.6 171.745 205.481 192.341 239.208 192.341C285.066 192.341 335.86 137.292 359.199 75.8585C365.788 58.513 368.26 42.4065 368.26 31.1512C368.26 17.8057 364.042 7.55823 352.131 7.55823C340.469 7.55823 332.777 16.6141 325.829 30.9129C317.688 47.4967 311.667 71.4162 309.203 98.4549C303 166.301 316.896 191.348 349.936 191.348C390 191.348 434.542 135.534 457.286 75.6686C463.803 58.513 466.275 42.4065 466.275 31.1512C466.275 17.8057 462.057 7.55823 450.146 7.55823C438.484 7.55823 430.792 16.6141 423.844 30.9129C415.703 47.4967 409.682 71.4162 407.218 98.4549C401.015 166.301 414.911 191.348 444.416 191.348C473.874 191.348 489.877 165.67 499.471 138.402C508.955 111.447 520.618 94.8221 544.935 94.8221C565.035 94.8221 580.916 109.71 580.916 137.75C580.916 168.768 560.792 192.093 535.362 192.341C512.984 192.589 498.285 174.475 499.774 147.179C501.511 116.907 519.873 94.8221 543.943 94.8221C557.839 94.8221 569.51 100.999 578.682 107.725C603.549 125.866 622.709 114.656 630.047 96.7186"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(2.8),
                ease: "easeInOut",
                delay: calc(0.7),
                opacity: { duration: 0.7, delay: calc(0.7) },
              }}
              onAnimationComplete={onAnimationComplete}
            />
          </motion.svg>
        )
      }

      ```

      For Hindi:

      ```tsx title="components/apple-hello-effect-hindi.tsx" 
      "use client"

      import type { ComponentProps } from "react"
      import type { TargetAndTransition } from "motion/react"
      import { motion } from "motion/react"

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

      const initialProps: TargetAndTransition = {
        pathLength: 0,
        opacity: 0,
      }

      const animateProps: TargetAndTransition = {
        pathLength: 1,
        opacity: 1,
      }

      export type AppleHelloEffectProps = Omit<
        ComponentProps<typeof motion.svg>,
        "durationScale" | "onAnimationComplete"
      > & {
        /**
         * Scales the duration and delay of the handwriting animation.
         * Values below 1 speed up, values above 1 slow down.
         * @defaultValue 0.8
         */
        durationScale?: number
        /** Called when the full handwriting animation completes. */
        onAnimationComplete?: () => void
      }

      export function AppleHelloEffectHindi({
        className,
        durationScale = 0.8,
        onAnimationComplete,
        ...props
      }: AppleHelloEffectProps) {
        const calc = (x: number) => x * durationScale

        return (
          <motion.svg
            className={cn("h-20", className)}
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 605 273"
            fill="none"
            stroke="currentColor"
            strokeWidth="14.888"
            strokeLinecap="round"
            initial={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.5 }}
            {...props}
          >
            <title>नमस्ते</title>
            <motion.path
              d="M42.3842 150.002C53.2928 153.473 60.4984 162.29 60.4984 175.561C60.4984 189.953 50.3247 201.119 36.677 201.119C24.022 201.119 14.8408 192.186 14.8408 179.035C14.8408 160.269 31.2182 148.265 56.5282 149.01C82.0863 149.754 103.723 163.663 120.367 185.069"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.6),
                ease: "easeOut",
                opacity: { duration: 0.2 },
              }}
            />
            <motion.path
              d="M133.502 93.5842C124.459 153.875 117.303 209.683 111.71 264.988"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.4),
                ease: "easeOut",
                delay: calc(0.6),
                opacity: { duration: 0.2, delay: calc(0.6) },
              }}
            />
            <motion.path
              d="M216.556 90.9181C217.117 117.977 216.81 137.689 214.869 160.067C212.007 193.058 200.119 213.115 180.936 213.115C169.295 213.115 160.844 205.334 160.844 193.399C160.844 177.222 175.901 164.28 203.653 165.376C229.863 166.411 256.651 174.863 275.138 192.025"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.6),
                ease: "easeOut",
                delay: calc(1),
                opacity: { duration: 0.2, delay: calc(1) },
              }}
            />
            <motion.path
              d="M289.489 90.0085C280.255 150.162 272.672 207.783 267.379 263.003"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.4),
                ease: "easeOut",
                delay: calc(1.6),
                opacity: { duration: 0.2, delay: calc(1.6) },
              }}
            />
            <motion.path
              d="M373.949 90.0198C394.816 102.051 408.098 128.602 408.098 154.079C408.098 185.141 387.465 205.586 358.47 205.586C330.249 205.586 311.145 186.038 317.527 170.35C322.864 157.231 341.378 156.812 356.237 168.861C374.674 183.811 382.044 216.764 385.021 261.169"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.6),
                ease: "easeOut",
                delay: calc(2),
                opacity: { duration: 0.2, delay: calc(2) },
              }}
            />
            <motion.path
              d="M403.474 177.549C418.085 183.32 439.163 184.314 458.424 179.805"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.4),
                ease: "easeOut",
                delay: calc(2.6),
                opacity: { duration: 0.2, delay: calc(2.6) },
              }}
            />
            <motion.path
              d="M556.981 88.1333C546.807 149.619 538.371 207.01 531.919 262.906"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.4),
                ease: "easeOut",
                delay: calc(3),
                opacity: { duration: 0.2, delay: calc(3) },
              }}
            />
            <motion.path
              d="M536.891 222.462C541.984 183.336 528.689 152.484 496.435 152.484C472.365 152.484 453.755 175.064 453.755 203.104C453.755 223.451 461.199 245.784 475.095 261.417"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.6),
                ease: "easeOut",
                delay: calc(3.4),
                opacity: { duration: 0.2, delay: calc(3.4) },
              }}
            />
            <motion.path
              d="M521.259 45.4307C485.619 43.0134 474.856 32.3917 474.856 21.5298C474.856 12.832 482.71 7.04349 493.506 7.46568C518.289 8.37031 542.96 35.3336 555.578 70.4412"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.6),
                ease: "easeOut",
                delay: calc(4),
                opacity: { duration: 0.2, delay: calc(4) },
              }}
            />
            <motion.path
              d="M7.44434 88.6792C30.9102 88.8706 59.0093 89.2085 95.3706 89.2085C132.178 89.2085 208.165 89.2571 253.623 89.2047C295.091 89.1568 396.683 89.0223 452.784 89.0234C506.182 89.0244 552.847 88.4444 596.931 87.2836"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.8),
                ease: "easeOut",
                delay: calc(4.6),
                opacity: { duration: 0.2, delay: calc(4.6) },
              }}
              onAnimationComplete={onAnimationComplete}
            />
          </motion.svg>
        )
      }

      ```

      For Spanish:

      ```tsx title="components/apple-hello-effect-spanish.tsx" 
      "use client"

      import type { ComponentProps } from "react"
      import type { TargetAndTransition } from "motion/react"
      import { motion } from "motion/react"

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

      const initialProps: TargetAndTransition = {
        pathLength: 0,
        opacity: 0,
      }

      const animateProps: TargetAndTransition = {
        pathLength: 1,
        opacity: 1,
      }

      export type AppleHelloEffectProps = Omit<
        ComponentProps<typeof motion.svg>,
        "durationScale" | "onAnimationComplete"
      > & {
        /**
         * Scales the duration and delay of the handwriting animation.
         * Values below 1 speed up, values above 1 slow down.
         * @defaultValue 1
         */
        durationScale?: number
        /** Called when the full handwriting animation completes. */
        onAnimationComplete?: () => void
      }

      export function AppleHelloEffectSpanish({
        className,
        durationScale = 1,
        onAnimationComplete,
        ...props
      }: AppleHelloEffectProps) {
        const calc = (x: number) => x * durationScale

        return (
          <motion.svg
            className={cn("h-20", className)}
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 562 200"
            fill="none"
            stroke="currentColor"
            strokeWidth="14.888"
            strokeLinecap="round"
            initial={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.5 }}
            {...props}
          >
            <title>hola</title>
            <motion.path
              d="M8.692 169.422c27.495-16.185 51.282-36.493 77.822-72.424 18.627-25.219 27.738-47.893 28.236-65.962.248-13.399-6.204-23.563-18.362-23.563-13.4 0-21.837 10.164-27.048 33.497-5.707 25.643-9.925 55.067-20.595 149.42"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.8),
                ease: "easeOut",
                opacity: { duration: 0.4 },
              }}
            />
            <motion.path
              d="M49.79 181.168c5.265-46.274 26.25-83.086 52.801-83.086 15.881 0 25.974 12.655 23.108 30.769-1.613 10.67-4.528 23.077-6.193 35.236-2.026 15.384 3.761 27.295 21.655 27.295 25.257 0 41.157-24.523 48.037-53.562"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.8),
                ease: "easeInOut",
                delay: calc(0.7),
                opacity: { duration: 0.2, delay: calc(0.8) },
              }}
            />
            <motion.path
              d="M234.601 94.36c-24.822 2.006-43.39 23.044-46.898 51.861-3.226 26.302 11.414 46.154 34.739 46.154 28.288 0 46.65-24.318 47.891-54.591.992-29.032-12.903-43.672-31.762-43.672-14.888 0-22.829 11.166-22.332 24.813.484 18.661 14.478 39.612 43.839 42.289 40.725 3.714 96.424-26.396 118.914-85.593 6.487-17.074 8.959-33.18 8.959-44.436 0-13.346-4.219-23.593-16.129-23.593-11.663 0-19.355 9.056-26.303 23.355-8.14 16.583-14.162 40.503-16.625 67.542-6.204 67.846 7.692 92.893 37.42 92.893 30.127 0 50.049-26.113 58.664-56.317"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(1.6),
                ease: "easeInOut",
                delay: calc(1.4),
                opacity: { duration: 0.2, delay: calc(1.5) },
              }}
            />
            <motion.path
              d="M503.236 112.864c-4.864-11.195-15.204-18.753-31.664-18.753-27.295 0-47.808 27.296-49.155 56.576-1.174 26.799 11.192 41.864 28.805 41.687 25.001-.25 43.378-24.805 51.581-76.763 1.012-6.41 2.061-13.104 3.073-19.514"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.7),
                ease: "easeInOut",
                delay: calc(2.9),
                opacity: { duration: 0.2, delay: calc(3) },
              }}
            />
            <motion.path
              d="m505.875 96.097-3.073 19.507c-4.482 28.44-6.549 39.66-6.327 46.994.518 17.121 6.675 28.784 22.06 28.784 19.355 0 30.21-13.152 35.421-27.544"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.8),
                ease: "easeInOut",
                delay: calc(3.5),
                opacity: { duration: 0.2, delay: calc(3.5) },
              }}
              onAnimationComplete={onAnimationComplete}
            />
          </motion.svg>
        )
      }

      ```

      For Vietnamese:

      ```tsx title="components/apple-hello-effect-vietnamese.tsx" 
      "use client"

      import type { ComponentProps } from "react"
      import type { TargetAndTransition } from "motion/react"
      import { motion } from "motion/react"

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

      const initialProps: TargetAndTransition = {
        pathLength: 0,
        opacity: 0,
      }

      const animateProps: TargetAndTransition = {
        pathLength: 1,
        opacity: 1,
      }

      export type AppleHelloEffectProps = Omit<
        ComponentProps<typeof motion.svg>,
        "durationScale" | "onAnimationComplete"
      > & {
        /**
         * Scales the duration and delay of the handwriting animation.
         * Values below 1 speed up, values above 1 slow down.
         * @defaultValue 1
         */
        durationScale?: number
        /** Called when the full handwriting animation completes. */
        onAnimationComplete?: () => void
      }

      export function AppleHelloEffectVietnamese({
        className,
        durationScale = 1,
        onAnimationComplete,
        ...props
      }: AppleHelloEffectProps) {
        const calc = (x: number) => x * durationScale

        return (
          <motion.svg
            className={cn("h-20", className)}
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 1009 200"
            fill="none"
            stroke="currentColor"
            strokeWidth="14.8883"
            strokeLinecap="round"
            initial={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.5 }}
            {...props}
          >
            <title>xin chào</title>

            {/* x1 */}
            <motion.path
              d="M102.233 96.2277C75.6823 127.245 45.1612 158.759 11.4143 190.521"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.3),
                ease: "easeInOut",
                opacity: { duration: 0.15 },
              }}
            />

            {/* x2 */}
            <motion.path
              d="M7.69214 116.575C9.67725 105.16 16.8733 95.7311 28.5358 95.7311C40.4465 95.7311 46.8981 105.408 53.3497 124.019C56.7409 133.283 60.1322 142.547 63.5234 151.81C73.689 179.58 81.1988 191.513 100.855 191.513C128.722 191.513 154.043 159.148 161.595 118.502C162.929 111.321 164.774 103.736 166.043 96.2273"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.7),
                ease: "easeInOut",
                delay: calc(0.4),
                opacity: { duration: 0.35, delay: calc(0.4) },
              }}
            />

            {/* i */}
            <motion.path
              d="M166.043 96.2273C163.191 113.101 160.565 126.997 158.92 139.404C157.989 147.592 157.544 154.54 157.596 161.488C157.729 179.354 164.764 191.513 182.695 191.513C209.39 191.513 236.181 159.123 243.73 118.5C245.064 111.321 247.012 103.759 248.139 96.2273"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.5),
                ease: "easeOut",
                delay: calc(1),
                opacity: { duration: 0.25, delay: calc(1) },
              }}
            />

            {/* n1 */}
            <motion.path
              d="M248.139 96.2278C243.424 127.741 239.454 158.759 234.491 190.272"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.3),
                ease: "easeOut",
                delay: calc(1.5),
                opacity: { duration: 0.15, delay: calc(1.5) },
              }}
            />

            {/* n2 */}
            <motion.path
              d="M237.873 167.951C244.704 121.32 265.508 94.2422 290.322 94.2422C307.692 94.2422 316.625 106.153 315.136 123.026C313.896 135.681 309.677 150.322 308.685 162.729C307.444 179.85 316.499 191.513 330.769 191.513C348.722 191.513 359.309 179.314 364.143 165.965"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.9),
                ease: "easeOut",
                delay: calc(1.8),
                opacity: { duration: 0.45, delay: calc(1.8) },
              }}
            />

            {/* c, h1 */}
            <motion.path
              d="M535.91 109.876C531.265 100.446 520.943 93.4984 505.459 93.4984C476.516 93.4984 462.044 117.816 462.044 143.374C462.044 171.503 482.265 192.506 511.307 192.506C559.762 192.506 592.902 136.708 621.581 97.8807C640.764 71.9101 649.874 49.2359 650.372 31.1674C650.62 17.7684 644.168 7.60362 632.01 7.60362C618.61 7.60362 610.173 17.7684 604.963 41.1011C599.255 66.7441 595.037 96.1684 584.367 190.521"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(1.1),
                ease: "easeInOut",
                delay: calc(2.6),
                opacity: { duration: 0.55, delay: calc(2.6) },
              }}
            />

            {/* h2 */}
            <motion.path
              d="M585.413 181.299C590.677 135.025 611.663 98.2125 638.213 98.2125C654.094 98.2125 664.187 110.868 661.321 128.982C659.708 139.652 656.794 152.059 655.128 164.217C653.102 179.602 658.89 191.513 676.813 191.513C702.178 191.513 717.375 164.077 725.613 135.196"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(1),
                ease: "easeInOut",
                delay: calc(3.6),
                opacity: { duration: 0.5, delay: calc(3.6) },
              }}
            />

            {/* a1 */}
            <motion.path
              d="M803.871 112.995C799.007 101.8 788.666 94.2423 772.207 94.2423C744.912 94.2423 724.398 121.538 723.052 150.818C721.878 177.617 734.244 192.681 751.857 192.505C776.858 192.255 795.234 167.699 803.437 115.742C804.449 109.332 805.498 102.638 806.51 96.2274"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.8),
                ease: "easeOut",
                delay: calc(4.6),
                opacity: { duration: 0.4, delay: calc(4.6) },
              }}
            />

            {/* a2, o */}
            <motion.path
              d="M806.51 96.2274C805.486 102.73 804.461 109.232 803.436 115.735C798.955 144.175 796.887 155.395 797.109 162.729C797.628 179.85 803.785 191.513 820.064 191.513C842.563 191.513 860.966 164.721 870.266 138.289C879.653 111.612 891.315 94.9867 915.633 94.9867C935.732 94.9867 951.613 109.875 951.613 137.915C951.613 168.932 931.489 192.257 906.059 192.505C883.681 192.753 868.983 174.639 870.471 147.344C872.208 117.071 890.571 94.9867 914.64 94.9867C928.536 94.9867 940.207 101.164 949.38 107.89C974.247 126.031 993.407 114.82 1000.74 96.8832"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(1.5),
                ease: "easeOut",
                delay: calc(5.4),
                opacity: { duration: 0.75, delay: calc(5.4) },
              }}
            />

            {/* sign */}
            <motion.path
              d="M763.027 19.3039C768.734 34.6886 780.397 48.3362 792.059 55.5322"
              initial={initialProps}
              animate={animateProps}
              transition={{
                duration: calc(0.8),
                ease: "easeInOut",
                delay: calc(7),
                opacity: { duration: 0.4, delay: calc(7) },
              }}
              onAnimationComplete={onAnimationComplete}
            />
          </motion.svg>
        )
      }

      ```

      <Step>Update the import paths to match your project setup</Step>
    </Steps>
  </TabsContent>
</CodeTabs>

## Usage

```tsx
import { AppleHelloEffectEnglish } from "@/components/apple-hello-effect-english"
import { AppleHelloEffectHindi } from "@/components/apple-hello-effect-hindi"
import { AppleHelloEffectSpanish } from "@/components/apple-hello-effect-spanish"
import { AppleHelloEffectVietnamese } from "@/components/apple-hello-effect-vietnamese"
```

```tsx
<AppleHelloEffectEnglish />
<AppleHelloEffectHindi />
<AppleHelloEffectSpanish />
<AppleHelloEffectVietnamese />
```

## API Reference

<TypeTable
  id="type-table-props.ts-AppleHelloEffectProps"
  type={{
  "id": "props.ts-AppleHelloEffectProps",
  "name": "AppleHelloEffectProps",
  "description": "",
  "entries": [
    {
      "name": "onAnimationComplete",
      "description": "Called when the full handwriting animation completes.",
      "tags": [],
      "type": "(() => void) | undefined",
      "simplifiedType": "function",
      "required": false,
      "deprecated": false
    },
    {
      "name": "durationScale",
      "description": "Scales the duration and delay of the handwriting animation.\nValues below 1 speed up, values above 1 slow down.",
      "tags": [
        {
          "name": "defaultValue",
          "text": "1"
        }
      ],
      "type": "number | undefined",
      "simplifiedType": "number",
      "required": false,
      "deprecated": false
    }
  ]
}}
/>

## Credits

* [JaceThings](https://github.com/JaceThings/SF-Hello)

## References

* [SVG pathLength](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/pathLength)
* [React Motion component](https://motion.dev/docs/react-motion-component)

<DocSponsors />


Last updated on April 5, 2026