Configurando HeroUI
Ya tenemos Next instalado, pero ahora necesitamos integrar el resto de componentes que vamos a necesitar para trabajar.
HeroUI¶
Esta librería de componentes se apoya en TailwindCSS con lo que su instalación nos dará muy pocos problemas y viene bien descrita en la web oficial. En cualquier caso, vamos a instalarlo con el paquete @heroicons/react, que nos permitirá tener un paquete de iconos en la aplicación y con next-themes para poder aplicar tema oscuro o
claro.
Ahora necesitamos configurar el fichero de estilos de tailwindcss para que soporte los componentes de HeroUI. Creamos el siguiente archivo:
E instalamos el plugin en el fichero de estilos de Next. Borramos todo el contenido y lo dejamos así:
@import "tailwindcss";
@plugin "./hero.ts";
@source "../../node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}";
@custom-variant dark (&:is(.dark *));
Dark theme¶
Para poder aplicar el tema oscuro o claro en nuestra aplicación, necesitamos configurar una librería llamada next-theme. En este caso HeroUI también lo explica en la web oficial.
Necesitamos, en cualquier caso crear un nuevo fichero con los providers de HeroUI con el siguiente contenido:
'use client'
import { HeroUIProvider } from '@heroui/system'
import { useRouter } from 'next/navigation'
import type { ThemeProviderProps } from 'next-themes'
import { ThemeProvider as NextThemesProvider } from 'next-themes'
import type * as React from 'react'
export interface ProvidersProps {
  children: React.ReactNode
  themeProps?: ThemeProviderProps
}
declare module '@react-types/shared' {
  interface RouterConfig {
    routerOptions: NonNullable<
      Parameters<ReturnType<typeof useRouter>['push']>[1]
    >
  }
}
export function Providers({ children, themeProps }: ProvidersProps) {
  const router = useRouter()
  return (
    <HeroUIProvider navigate={router.push}>
      <NextThemesProvider {...themeProps}>{children}</NextThemesProvider>
    </HeroUIProvider>
  )
}
Info
La notación 'use client' es exclusiva de algunos frameworks con soporte de React Server Components. Se verá su uso durante el curso.
Y este archivo de providers se debe cargar en el layout principal:
import type { Metadata, Viewport } from 'next'
import { Geist, Geist_Mono } from 'next/font/google'
import './globals.css'
import { Providers } from './providers'
const geistSans = Geist({
  variable: '--font-geist-sans',
  subsets: ['latin'],
})
const geistMono = Geist_Mono({
  variable: '--font-geist-mono',
  subsets: ['latin'],
})
export const metadata: Metadata = {
  description: 'Aplicación del taller de Next del Aula de Software Libre',
  title: 'Taller de Next con Typescript',
}
export const viewport: Viewport = {
  themeColor: [
    { media: '(prefers-color-scheme: light)', color: 'white' },
    { media: '(prefers-color-scheme: dark)', color: 'black' },
  ],
}
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode
}>) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body
        className={`${geistSans.variable} ${geistMono.variable} bg-background text-foreground antialiased`}
      >
        <Providers themeProps={{ attribute: 'class', defaultTheme: 'dark' }}>
          {children}
        </Providers>
      </body>
    </html>
  )
}
Nuestro primer componente: ThemeSwitcher¶
Para poder ver en funcionamiento el selector de tema claro/oscuro, vamos a crear un switch para cambiar de un tema a otro.
Para eso crearemos el siguiente componente:
'use client'
import { MoonIcon, SunIcon } from '@heroicons/react/24/solid'
import { Switch } from '@heroui/react'
import { useTheme } from 'next-themes'
import { useEffect, useState } from 'react'
/**
 * Theme dark/light switcher
 */
export function ThemeSwitcher() {
  const [mounted, setMounted] = useState(false) // (1)
  const { setTheme, theme } = useTheme() // (2)
  useEffect(() => {
    setMounted(true) // (3)
  }, [setMounted])
  if (!mounted) return null
  return (
    <Switch
      defaultSelected={theme === 'light'}
      size="md"
      color="secondary"
      onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
      startContent={<SunIcon />}
      endContent={<MoonIcon />}
    />
  )
}
- Hook para comprobar si el componente ya ha sido montado.
 - Hook proporcionado por next-themes para conocer el tema y cambiarlo.
 - Esta función se ejecuta una sola vez, justo después de que el componente se haya montado, y cambia el estado del hook a true.
 
Vamos a probar a añadir nuestro componente a la pagina principal:
- Añadimos el componente después del logo de Vercel. El IDE importará automáticamente el componente.
 
Warning
En este caso no puedes copiar y pegar el código. Aprende a importar y usar componentes.
Hay dos maneras de escribir una marca HTML. Si la marca tiene contenido:
Y si no lo tiene, como es el caso de nuestro componente:
Ahora, ya tendremos la página principal con nuestro componente para cambiar al tema claro:
