title: Spinning Text
description: The Spinning Text component animates text in a circular motion with customizable speed, direction, color, and transitions for dynamic and engaging effects.
---

```vue
<template>
  <ClientOnly>
    <div class="flex min-h-[350px] w-full items-center justify-center">
      <SpinningText text="learn more · earn more · grow more ·" />
    </div>
  </ClientOnly>
</template>

<script lang="ts" setup></script>
<style scoped></style>

```

::alert{type="warning"}
This component uses the `nuxt-only` syntax with the `<ClientOnly>`. If you are not using Nuxt, you can simply remove it.
::

## Examples

reverse

```vue
<template>
  <ClientOnly>
    <div class="flex min-h-[350px] w-full items-center justify-center">
      <SpinningText
        text="learn more · earn more · grow more ·"
        :duration="20"
        reverse
      />
    </div>
  </ClientOnly>
</template>

<script lang="ts" setup></script>
<style scoped></style>

```

## API

| Prop Name    | Type                                                    | Default | Description                                             |
| ------------ | ------------------------------------------------------- | ------- | ------------------------------------------------------- |
| `duration`   | `number`                                                | `10`    | The duration of the full circular rotation animation.   |
| `reverse`    | `boolean`                                               | `false` | Determines if the animation should rotate in reverse.   |
| `radius`     | `number`                                                | `5`     | The radius of the circular path for the text animation. |
| `transition` | `motion-v Transition`                                   | ``      | Custom transition effects for the animation.            |
| `variants`   | `{container: motion-v Variant, item: motion-v Variant}` | ``      | Variants for container and item animations.             |
| `class`      | `string`                                                | `""`    | A custom class name for the text container.             |

## Install using CLI

```vue
<InstallationCli component-id="spinning-text" />
```

## Component Code

You can copy and paste the following code to create this component:

```vue
<template>
  <Motion
    as="div"
    :class="cn('relative', props.class)"
    initial="hidden"
    animate="visible"
    :variants="containerVariants"
    :transition="finalTransition"
  >
    <span
      v-for="(letter, index) in letters"
      :key="`${letter}-${index}`"
      class="absolute left-1/2 top-1/2"
      :variants="itemVariants"
      :style="{
        '--index': index,
        '--total': letters.length,
        '--radius': radius,
        transform: `
                  translate(-50%, -50%)
                  rotate(calc(360deg / var(--total) * var(--index)))
                  translateY(calc(var(--radius, 5) * -1ch))
                `,
        transformOrigin: 'center',
      }"
    >
      {{ letter }}
    </span>
  </Motion>
</template>

<script lang="ts" setup>
import { cn } from "~/lib/utils";
import { Motion } from "motion-v";
import type { Variant, Transition } from "motion-v";

const BASE_TRANSITION = {
  repeat: Infinity,
  ease: "linear",
};

const BASE_ITEM_VARIANTS = {
  hidden: { opacity: 1 },
  visible: { opacity: 1 },
};

interface CircularTextProps {
  text: string;
  duration?: number;
  class?: string;
  reverse?: boolean;
  radius?: number;
  transition?: Transition;
  variants?: {
    container?: Variant;
    item?: Variant;
  };
}

const props = withDefaults(defineProps<CircularTextProps>(), {
  duration: 10,
  radius: 5,
});

const letters = computed(() => {
  let letters = props.text.split("");
  letters.push(" ");
  return letters;
});
const finalTransition = computed(() => ({
  ...BASE_TRANSITION,
  ...props.transition,
  duration: props.transition?.duration ?? props.duration,
}));

const containerVariants = computed(() => ({
  visible: { rotate: props.reverse ? -360 : 360 },
  // ...props.variants?.container,
}));

const itemVariants = computed(() => ({
  ...BASE_ITEM_VARIANTS,
  ...props?.variants?.item,
}));
</script>
<style scoped></style>

```

## Credits

- Credits to [Whbbit1999](https://github.com/Whbbit1999) for this component.
- Ported from [Magic UI Spinning Text](https://magicui.design/docs/components/spinning-text).