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:
