PageCTA

A call to action section to display in your pages.

Usage

The PageCTA component provides a flexible way to display a call to action in your pages with an illustration in the default slot.

Trusted and supported by our amazing community

Preview the latest Tailwind CSS v4 beta and get started with Nuxt UI v3.
Illustration

Use it inside a PageSection component or directly in your page:

<template>
  <UPageHero />

  <UPageCTA class="rounded-none" />

  <UPageSection />

  <UPageSection :ui="{ container: 'px-0' }">
    <UPageCTA class="rounded-none sm:rounded-[calc(var(--ui-radius)*3)]" />
  </UPageSection>

  <UPageSection />
</template>
Use px-0 and rounded-none classes to make the CTA fill the edge of the page on mobile.

Title

Use the title prop to set the title of the CTA.

Trusted and supported by our amazing community

<template>
  <UPageCTA title="Trusted and supported by our amazing community" />
</template>

Description

Use the description prop to set the description of the CTA.

Trusted and supported by our amazing community

We've built a strong, lasting partnership. Their trust is our driving force, propelling us towards shared success.
<template>
  <UPageCTA
    title="Trusted and supported by our amazing community"
    description="We've built a strong, lasting partnership. Their trust is our driving force, propelling us towards shared success."
  />
</template>

Use the links prop to display a list of Button under the description.

Trusted and supported by our amazing community

We've built a strong, lasting partnership. Their trust is our driving force, propelling us towards shared success.
<script setup lang="ts">
const links = ref([
  {
    label: 'Get started',
    color: 'neutral'
  },
  {
    label: 'Learn more',
    color: 'neutral',
    variant: 'subtle',
    trailingIcon: 'i-lucide-arrow-right'
  }
])
</script>

<template>
  <UPageCTA
    title="Trusted and supported by our amazing community"
    description="We've built a strong, lasting partnership. Their trust is our driving force, propelling us towards shared success."
    :links="links"
  />
</template>

Variant

Use the variant prop to change the style of the CTA.

Trusted and supported by our amazing community

We've built a strong, lasting partnership. Their trust is our driving force, propelling us towards shared success.
<script setup lang="ts">
const links = ref([
  {
    label: 'Get started',
    color: 'neutral'
  },
  {
    label: 'Learn more',
    color: 'neutral',
    variant: 'subtle',
    trailingIcon: 'i-lucide-arrow-right'
  }
])
</script>

<template>
  <UPageCTA
    title="Trusted and supported by our amazing community"
    description="We've built a strong, lasting partnership. Their trust is our driving force, propelling us towards shared success."
    variant="soft"
    :links="links"
  />
</template>
You can apply the light or dark class to the links slot when using the solid variant to reverse the colors.

Orientation

Use the orientation prop to change the orientation with the default slot. Defaults to vertical.

Trusted and supported by our amazing community

We've built a strong, lasting partnership. Their trust is our driving force, propelling us towards shared success.
Illustration
<script setup lang="ts">
const links = ref([
  {
    label: 'Get started',
    color: 'neutral'
  },
  {
    label: 'Learn more',
    color: 'neutral',
    variant: 'subtle',
    trailingIcon: 'i-lucide-arrow-right'
  }
])
</script>

<template>
  <UPageCTA
    title="Trusted and supported by our amazing community"
    description="We've built a strong, lasting partnership. Their trust is our driving force, propelling us towards shared success."
    orientation="horizontal"
    :links="links"
  >
    <img
      src="https://picsum.photos/640/728"
      width="320"
      height="364"
      alt="Illustration"
      class="w-full rounded-[calc(var(--ui-radius)*2)]"
    />
  </UPageCTA>
</template>

Reverse

Use the reverse prop to reverse the orientation of the default slot.

Trusted and supported by our amazing community

We've built a strong, lasting partnership. Their trust is our driving force, propelling us towards shared success.
Illustration
<script setup lang="ts">
const links = ref([
  {
    label: 'Get started',
    color: 'neutral'
  },
  {
    label: 'Learn more',
    color: 'neutral',
    variant: 'subtle',
    trailingIcon: 'i-lucide-arrow-right'
  }
])
</script>

<template>
  <UPageCTA
    title="Trusted and supported by our amazing community"
    description="We've built a strong, lasting partnership. Their trust is our driving force, propelling us towards shared success."
    orientation="horizontal"
    reverse
    :links="links"
  >
    <img
      src="https://picsum.photos/640/728"
      width="320"
      height="364"
      alt="Illustration"
      class="w-full rounded-[calc(var(--ui-radius)*2)]"
    />
  </UPageCTA>
</template>

API

Props

Prop Default Type
as

'div'

any

The element or component this component should render as.

title

string

description

string

orientation

'vertical'

"horizontal" | "vertical"

The orientation of the page cta.

reverse

false

boolean

Reverse the order of the default slot.

variant

'outline'

"solid" | "outline" | "soft" | "subtle" | "naked"

links

ButtonProps[]

Display a list of Button under the description. { size: 'lg' }

ui

Partial<{ root: string; container: string; wrapper: string; title: string; description: string; links: string; }>

Slots

Slot Type
default

{}

title

{}

description

{}

links

{}

Theme

app.config.ts
export default defineAppConfig({
  uiPro: {
    pageCTA: {
      slots: {
        root: 'relative isolate rounded-[calc(var(--ui-radius)*3)] overflow-hidden',
        container: 'flex flex-col lg:grid px-6 py-12 sm:px-12 sm:py-24 lg:px-16 lg:py-24 gap-8 sm:gap-16',
        wrapper: '',
        title: 'text-3xl sm:text-4xl text-pretty tracking-tight font-bold text-[var(--ui-text-highlighted)]',
        description: 'text-base sm:text-lg text-[var(--ui-text-muted)]',
        links: 'mt-8 flex flex-wrap gap-x-6 gap-y-3'
      },
      variants: {
        orientation: {
          horizontal: {
            container: 'lg:grid-cols-2 lg:items-center',
            description: 'text-pretty'
          },
          vertical: {
            container: '',
            title: 'text-center',
            description: 'text-center text-balance',
            links: 'justify-center'
          }
        },
        reverse: {
          true: {
            wrapper: 'lg:order-last'
          }
        },
        variant: {
          solid: {
            root: 'bg-[var(--ui-bg-inverted)] text-[var(--ui-bg)]',
            title: 'text-[var(--ui-bg)]',
            description: 'text-[var(--ui-text-dimmed)]'
          },
          outline: {
            root: 'bg-[var(--ui-bg)] ring ring-[var(--ui-border)]',
            description: 'text-[var(--ui-text-muted)]'
          },
          soft: {
            root: 'bg-[var(--ui-bg-elevated)]/50',
            description: 'text-[var(--ui-text-toned)]'
          },
          subtle: {
            root: 'bg-[var(--ui-bg-elevated)]/50 ring ring-[var(--ui-border)]',
            description: 'text-[var(--ui-text-toned)]'
          },
          naked: {
            description: 'text-[var(--ui-text-muted)]'
          }
        },
        title: {
          true: {
            description: 'mt-6'
          }
        }
      },
      defaultVariants: {
        variant: 'outline'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      uiPro: {
        pageCTA: {
          slots: {
            root: 'relative isolate rounded-[calc(var(--ui-radius)*3)] overflow-hidden',
            container: 'flex flex-col lg:grid px-6 py-12 sm:px-12 sm:py-24 lg:px-16 lg:py-24 gap-8 sm:gap-16',
            wrapper: '',
            title: 'text-3xl sm:text-4xl text-pretty tracking-tight font-bold text-[var(--ui-text-highlighted)]',
            description: 'text-base sm:text-lg text-[var(--ui-text-muted)]',
            links: 'mt-8 flex flex-wrap gap-x-6 gap-y-3'
          },
          variants: {
            orientation: {
              horizontal: {
                container: 'lg:grid-cols-2 lg:items-center',
                description: 'text-pretty'
              },
              vertical: {
                container: '',
                title: 'text-center',
                description: 'text-center text-balance',
                links: 'justify-center'
              }
            },
            reverse: {
              true: {
                wrapper: 'lg:order-last'
              }
            },
            variant: {
              solid: {
                root: 'bg-[var(--ui-bg-inverted)] text-[var(--ui-bg)]',
                title: 'text-[var(--ui-bg)]',
                description: 'text-[var(--ui-text-dimmed)]'
              },
              outline: {
                root: 'bg-[var(--ui-bg)] ring ring-[var(--ui-border)]',
                description: 'text-[var(--ui-text-muted)]'
              },
              soft: {
                root: 'bg-[var(--ui-bg-elevated)]/50',
                description: 'text-[var(--ui-text-toned)]'
              },
              subtle: {
                root: 'bg-[var(--ui-bg-elevated)]/50 ring ring-[var(--ui-border)]',
                description: 'text-[var(--ui-text-toned)]'
              },
              naked: {
                description: 'text-[var(--ui-text-muted)]'
              }
            },
            title: {
              true: {
                description: 'mt-6'
              }
            }
          },
          defaultVariants: {
            variant: 'outline'
          }
        }
      }
    })
  ]
})