TODOvue Hero (TvHero)

January 20, 2026 · View on GitHub

TODOvue logo

TODOvue Hero (TvHero)

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.

npm npm downloads npm total downloads License Release Date Bundle Size Node Version Last Commit Stars

Demo: https://ui.todovue.blog/hero

Table of Contents

Features

  • 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

Installation

Using npm:

npm install @todovue/tv-hero

Using yarn:

yarn add @todovue/tv-hero

Using pnpm:

pnpm add @todovue/tv-hero

Quick Start (SPA)

Global 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>

Nuxt 4 / SSR Usage

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>

Component Registration Options

ApproachWhen 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

Props

PropTypeDefaultDescription
configHeroObject{}Main configuration object with title, description, buttons, and image.
customHeroObject{}Custom styling object for colors and themes.
isEntryBooleanfalseEnables entry/article layout mode (full-width, no buttons).
imagePositionString'left'Controls image position: 'left' or 'right'.
isBackgroundImageBooleanfalseEnables background image mode with overlay.

Events

Event name (kebab)Description
click-buttonEmitted when primary button is clicked.
click-secondary-buttonEmitted when secondary button is clicked.

Usage:

<TvHero 
  :configHero="config" 
  @click-button="handlePrimary" 
  @click-secondary-button="handleSecondary" 
/>

Slots

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 NameDescription
imageReplaces the hero image area. Useful for custom images or video.
titleReplaces the title text. Use this for rich HTML titles.
descriptionReplaces the description text. Perfect for complex HTML content.
actionsReplaces 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>

Configuration Object (configHero)

The configHero prop accepts an object with the following properties:

PropertyTypeRequiredDescription
titleStringYesMain heading text for the hero section.
descriptionStringYesDescriptive text displayed below the title.
imageStringNoURL of the hero image.
altStringNoAlt text for the image (accessibility).
buttonStringNoText for the primary call-to-action button.
buttonSecondaryStringNoText 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'
}

Customization (Styles / Theming)

The customHero prop allows you to override default colors and styles:

PropertyTypeDescription
bgBodyStringBackground color for the hero section.
colorBodyStringText color for title and description.
bgButtonStringBackground color for primary button.
colorButtonStringText color for primary button.
bgButtonSecondaryStringBackground color for secondary button.
colorButtonSecondaryStringText 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

Layout Modes

Standard Hero (with image)

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' 
}" />

Full-width Hero (without image)

Omit the image property for a centered, text-focused layout:

<TvHero :configHero="{ 
  title: 'Welcome', 
  description: 'Learn Vue.js',
  button: 'Start'
}" />

Entry/Article Mode

Set isEntry to true for blog post headers (buttons are hidden):

<TvHero 
  :configHero="articleHero" 
  :isEntry="true" 
/>

Examples

Basic Hero

<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')"
/>

Hero with Secondary Button

<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"
/>

Custom Themed Hero

<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'
  }"
/>

Entry/Article Hero

<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"
/>

Accessibility

  • Semantic HTML: Uses proper heading hierarchy (<h1> for title)
  • Alt text: Always provide alt property 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

SSR Notes

  • Zero DOM dependencies: No direct window or document access
  • 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

Styles Usage

Vue 3 / Vite SPA

// 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 3 / 4

// nuxt.config.ts
export default defineNuxtConfig({
  css: ['@todovue/tv-hero/style.css'],
})

Development

git clone https://github.com/TODOvue/tv-hero.git
cd tv-hero
npm install
npm run dev     # run demo playground
npm run build   # build library

The demo playground includes multiple examples showcasing different configurations and customization options.

Contributing

PRs and issues welcome! See CONTRIBUTING.md and CODE_OF_CONDUCT.md.

Dependencies

License

MIT © TODOvue

Attributions

Crafted for the TODOvue component ecosystem