A customizable, responsive Vue 3 hero component designed for web applications. Perfect for creating impactful landing sections with images, titles, descriptions, and call-to-action buttons. Fully compatible with Single Page Apps and Server-Side Rendered (SSR) environments like Nuxt 3.
- Features
- Installation
- Quick Start (SPA)
- Nuxt 4 / SSR Usage
- Component Registration Options
- Props
- Events
- Configuration Object (configHero)
- Customization (Styles / Theming)
- Layout Modes
- Examples
- Accessibility
- SSR Notes
- Styles Usage
- Development
- Contributing
- License
- Flexible layouts: Standard hero with image or full-width text-only hero
- Entry mode: Special layout optimized for blog posts and article pages
- Customizable styling: Override colors for background, text, and buttons
- Call-to-action support: Primary and optional secondary buttons powered by
@todovue/tv-button - Responsive design: Adapts beautifully across all screen sizes
- Dark/Light mode ready: Built-in theme support with custom color options
- SSR compatible: Works seamlessly in Nuxt 3 and other SSR frameworks
- TypeScript support: Full type definitions included
- Zero configuration: Works out of the box with sensible defaults
Using npm:
npm install @todovue/tv-heroUsing yarn:
yarn add @todovue/tv-heroUsing pnpm:
pnpm add @todovue/tv-heroGlobal registration (main.js / main.ts):
import { createApp } from 'vue'
import App from './App.vue'
import '@todovue/tv-hero/style.css'
import '@todovue/tv-button/style.css'
import TvHero from '@todovue/tv-hero'
createApp(App)
.use(TvHero) // enables <TvHero /> globally
.mount('#app')Local import inside a component:
<script setup>
import '@todovue/tv-hero/style.css'
import '@todovue/tv-button/style.css'
import { TvHero } from '@todovue/tv-hero'
const heroConfig = {
title: 'Welcome to TODOvue',
description: 'Build amazing web applications with Vue.js',
button: 'Get Started',
image: 'https://example.com/hero-image.png',
alt: 'Hero image'
}
function onButtonClick() {
console.log('CTA clicked!')
}
</script>
<template>
<TvHero :configHero="heroConfig" @click-button="onButtonClick" />
</template>Create a plugin file: plugins/tv-hero.client.ts (or without suffix for SSR-safe usage):
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
'@todovue/tv-card/nuxt'
]
})Use anywhere in your Nuxt app:
<template>
<TvHero :configHero="heroData" @click-button="handleAction" />
</template>
<script setup>
const heroData = {
title: 'My Nuxt App',
description: 'Server-side rendered with love',
button: 'Learn More',
image: '/images/hero.jpg'
}
const handleAction = () => {
navigateTo('/about')
}
</script>Optional direct import (no plugin):
<script setup>
import '@todovue/tv-hero/style.css'
import '@todovue/tv-button/style.css'
import { TvHero } from '@todovue/tv-hero'
</script>| Approach | When to use |
|---|---|
Global via app.use(TvHero) |
Multiple hero sections across your app |
Local named import { TvHero } |
Isolated usage or code-splitting scenarios |
Direct default import import TvHero from '@todovue/tv-hero' |
Single usage or manual registration |
| Prop | Type | Default | Description |
|---|---|---|---|
| configHero | Object | {} | Main configuration object with title, description, buttons, and image. |
| customHero | Object | {} | Custom styling object for colors and themes. |
| isEntry | Boolean | false | Enables entry/article layout mode (full-width, no buttons). |
| imagePosition | String | 'left' | Controls image position: 'left' or 'right'. |
| isBackgroundImage | Boolean | false | Enables background image mode with overlay. |
| Event name (kebab) | Description |
|---|---|
click-button |
Emitted when primary button is clicked. |
click-secondary-button |
Emitted when secondary button is clicked. |
Usage:
<TvHero
:configHero="config"
@click-button="handlePrimary"
@click-secondary-button="handleSecondary"
/>The component exposes several slots to allow full customization of content areas. When using slots, the corresponding props in configHero act as defaults or can be omitted.
| Slot Name | Description |
|---|---|
image |
Replaces the hero image area. Useful for custom images or video. |
title |
Replaces the title text. Use this for rich HTML titles. |
description |
Replaces the description text. Perfect for complex HTML content. |
actions |
Replaces the buttons. Use this to add custom forms or extra buttons. |
Example of Slot Usage:
<TvHero :configHero="heroConfig">
<template #title>
Hello <span class="highlight">World</span>
</template>
<template #description>
<p>This is a <strong>custom</strong> description with HTML.</p>
</template>
<template #actions>
<button class="my-custom-btn">Join Now</button>
</template>
</TvHero>The configHero prop accepts an object with the following properties:
| Property | Type | Required | Description |
|---|---|---|---|
| title | String | Yes | Main heading text for the hero section. |
| description | String | Yes | Descriptive text displayed below the title. |
| image | String | No | URL of the hero image. |
| alt | String | No | Alt text for the image (accessibility). |
| button | String | No | Text for the primary call-to-action button. |
| buttonSecondary | String | No | Text for the optional secondary button. |
Example:
const configHero = {
title: 'TODOvue Blog',
description: 'Explore the world of Vue.js development',
button: 'View All Posts',
buttonSecondary: 'Latest Article',
image: 'https://example.com/logo.png',
alt: 'TODOvue Logo'
}The customHero prop allows you to override default colors and styles:
| Property | Type | Description |
|---|---|---|
| bgBody | String | Background color for the hero section. |
| colorBody | String | Text color for title and description. |
| bgButton | String | Background color for primary button. |
| colorButton | String | Text color for primary button. |
| bgButtonSecondary | String | Background color for secondary button. |
| colorButtonSecondary | String | Text color for secondary button. |
Example:
<TvHero
:configHero="heroConfig"
:customHero="{
bgBody: '#1e1d23',
colorBody: '#e1e2dc',
bgButton: '#8673a1',
colorButton: '#ffffff',
bgButtonSecondary: '#79308d',
colorButtonSecondary: '#ffffff'
}"
/>The component automatically:
- Generates subtle hover effects for custom button colors
- Creates a decorative separator bar below the title with matching colors
- Applies box-shadow effects for visual depth
Default layout with image on the left and content on the right:
<TvHero :configHero="{
title: 'Welcome',
description: 'Learn Vue.js',
button: 'Start',
image: '/hero.png'
}" />Omit the image property for a centered, text-focused layout:
<TvHero :configHero="{
title: 'Welcome',
description: 'Learn Vue.js',
button: 'Start'
}" />Set isEntry to true for blog post headers (buttons are hidden):
<TvHero
:configHero="articleHero"
:isEntry="true"
/><TvHero
:configHero="{
title: 'TODOvue Blog',
description: 'Discover Vue.js tips and tutorials',
button: 'View All Blogs',
image: 'https://todovue.com/logo.png',
alt: 'TODOvue Logo'
}"
@click-button="() => router.push('/blogs')"
/><TvHero
:configHero="{
title: 'TODOvue Blog',
description: 'Stay updated with the latest Vue.js content',
button: 'View All Blogs',
buttonSecondary: 'Read Latest',
image: 'https://todovue.com/logo.png',
alt: 'TODOvue Logo'
}"
@click-button="viewAll"
@click-secondary-button="viewLatest"
/><TvHero
:configHero="{
title: 'Modern Design',
description: 'Beautiful components for Vue 3',
button: 'Explore',
buttonSecondary: 'Documentation',
image: '/logo.png'
}"
:customHero="{
bgBody: '#202020',
colorBody: '#ffffff',
bgButton: '#8673a1',
colorButton: '#e1e2dc',
bgButtonSecondary: '#79308d',
colorButtonSecondary: '#e1e2dc'
}"
/><TvHero
:configHero="{
title: 'What is Vue.js?',
description: 'An introduction to the progressive JavaScript framework',
image: '/article-header.jpg',
alt: 'Vue.js Article'
}"
:isEntry="true"
/>- Semantic HTML: Uses proper heading hierarchy (
<h1>for title) - Alt text: Always provide
altproperty when using images - ARIA labels: Buttons inherit accessibility from
@todovue/tv-button - Keyboard navigation: Full keyboard support for interactive elements
- Color contrast: Default theme meets WCAG AA standards
- Zero DOM dependencies: No direct
windowordocumentaccess - Safe for SSR: Works in Nuxt 3, Vite SSR, and other server environments
- Image optimization: Works with Nuxt Image and other SSR image tools
- Composable pattern: Uses Vue 3 Composition API with computed properties
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { TvHero } from '@todovue/tv-hero'
import '@todovue/tv-hero/style.css'
const app = createApp(App)
app.component('TvHero', TvHero)
app.mount('#app')// nuxt.config.ts
export default defineNuxtConfig({
css: ['@todovue/tv-hero/style.css'],
})git clone https://github.com/TODOvue/tv-hero.git
cd tv-hero
npm install
npm run dev # run demo playground
npm run build # build libraryThe demo playground includes multiple examples showcasing different configurations and customization options.
PRs and issues welcome! See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
- @todovue/tv-button: Powers the call-to-action buttons
- Vue 3: Peer dependency (^3.0.0)
MIT © TODOvue
Crafted for the TODOvue component ecosystem
