Desenvolvedores
src_
components_
ModeToggle.jsx

Explicação do código:

Esse componente ModeToggle permite que o usuário alterne entre os temas "light", "dark" e "system" (que segue a configuração do sistema do usuário). Ele usa a biblioteca next-themes para lidar com a troca de temas.

Como o componente funciona:

  • Uso de useTheme do next-themes: O hook useTheme é utilizado para acessar e modificar o tema da aplicação. Ele possui o método setTheme que define o tema desejado.

  • Modo de operação diferente para a sidebar e navbar: Dependendo do contexto (passado como props), o componente renderiza de maneira diferente:

    • Sidebar: Usando um DropdownMenu com botões para alternar os temas.
    • Navbar: Um botão de alternância com ícones de Sol (☀️) e Lua (🌙) que muda de acordo com o tema atual.

Detalhamento do código:

  1. Importações:

    • O componente importa ícones (Moon, Sun) da biblioteca lucide-react.
    • O useTheme do next-themes para gerenciar os temas.
    • Componentes de UI como Button, DropdownMenu, SidebarMenuItem, e outros para a estrutura visual.
  2. Condicional de Contexto:

    • Se o contexto for "sidebar", o componente renderiza o DropdownMenu dentro de um item da sidebar.
    • Se o contexto for diferente (como na navbar), ele renderiza apenas um botão de alternância de tema.
  3. Mudança de Tema:

    • O botão de alternância chama a função setTheme com o tema desejado ('light', 'dark', 'system').
    • Ícones de Sol e Lua são animados para indicar o tema atual e para um efeito visual ao alternar entre os temas.

Código completo:

'use client'
 
import * as React from 'react'
import { Moon, Sun } from 'lucide-react'
import { useTheme } from 'next-themes'
 
import { Button } from '@/components/ui/button'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { SidebarMenuItem, SidebarMenuButton } from '@/components/ui/sidebar'
 
export function ModeToggle({ context = 'navbar' }) {
  const { setTheme } = useTheme()
 
  if (context === 'sidebar') {
    // Estilo para sidebar com DropdownMenu
    return (
      <SidebarMenuItem className="list-none">
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <SidebarMenuButton size="sm">
              <div className="flex items-center">
                <div className="h-[1.2rem] w-[1.2rem] flex items-center justify-center">
                  <Sun className="transition-all dark:rotate-90 dark:scale-0" />
                  <Moon className="absolute transition-all scale-0 dark:scale-100 dark:rotate-0" />
                </div>
                <span className="ml-3">Toggle theme</span>
              </div>
            </SidebarMenuButton>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="start">
            <DropdownMenuItem onClick={() => setTheme('light')}>Light</DropdownMenuItem>
            <DropdownMenuItem onClick={() => setTheme('dark')}>Dark</DropdownMenuItem>
            <DropdownMenuItem onClick={() => setTheme('system')}>System</DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </SidebarMenuItem>
    )
  }
 
  // Estilo para a navbar
  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="outline" size="icon">
          <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
          <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
          <span className="sr-only">Toggle theme</span>
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end">
        <DropdownMenuItem onClick={() => setTheme('light')}>Light</DropdownMenuItem>
        <DropdownMenuItem onClick={() => setTheme('dark')}>Dark</DropdownMenuItem>
        <DropdownMenuItem onClick={() => setTheme('system')}>System</DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

Emojis:

  • ☀️ para o Sol (modo claro)
  • 🌙 para a Lua (modo escuro)