0.0.6 • Published 2 months ago

next-super-themes v0.0.6

Weekly downloads
-
License
MIT
Repository
github
Last release
2 months ago

Apply multi themes on your Next.JS project.

This is an extension of Next /pacocoursey/next-themes repository

Why?

The /pacocoursey/next-themes repository give us the possibility to change set the theme to light, dark, and system by default.

The library also provide a way to apply custom themes but when using it, it is not possible to set the correct invert options for Tailwind.

So, this library is compatible with:

  • Next
  • Tailwind
  • Radix
  • Shadcn ui

Which gives us a flexibility to set custom themes.

How does it work?

Tailwind sometimes use the dark: flag to invert image colors.

dark:invert

So, when your theme has another name then not dark the invertion will not work. The solution is to use a theme-mode with a theme-name.

setTheme('dark', 'gym')

An abstraction for themes in your Next.js app.

Check out the Example to try it for yourself.

Install

$ npm install next-many-themes
# or
$ yarn add next-many-themes

Use

// src/context/theme-context.tsx
'use client'
import { ThemeProvider } from 'next-super-themes'
import { ThemeProviderProps } from 'next-super-themes/dist/types'

export default function CustomThemeProvider({ children, ...props }: ThemeProviderProps) {
  return <ThemeProvider {...props}>{children}</ThemeProvider>
}
// app/layout.tsx

import { Exo_2 } from 'next/font/google'
import './globals.css'
import ThemeProvider from 'src/context/theme-context'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body className={exo2.className}>
        <ThemeProvider defaultMode="system" enableSystem>
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}
//src/app/theme-changer.tsx
// import this component in your page to see the button to change the theme
'use client'

import { Wand } from 'lucide-react'
import { useTheme } from 'next-super-themes'
import { useEffect, useState } from 'react'
import { Button } from 'src/components/ui/button'

const themes: { mode: 'light' | 'dark'; theme: string | undefined }[] = [
  {
    mode: 'light',
    theme: undefined
  },
  {
    mode: 'dark',
    theme: undefined
  },
  {
    mode: 'dark',
    theme: 'gym'
  },
  {
    mode: 'dark',
    theme: 'carservice'
  },
  {
    mode: 'light',
    theme: 'clinic'
  },
  {
    mode: 'light',
    theme: 'aesthetics'
  },
  {
    mode: 'light',
    theme: 'food'
  }
]

export default function ThemeChager() {
  const { setTheme, themeMode } = useTheme()
  const [position, setPosition] = useState(-1)

  function setNextTheme() {
    if (position === themes.length - 1) {
      setPosition(0)
    } else {
      setPosition(position + 1)
    }
  }

  useEffect(() => {
    if (position > -1) {
      const theme = themes[position]
      setTheme(theme.mode, theme.theme)
    }
  }, [position, setTheme])

  return (
    <div className="w-full flex justify-end">
      <Button
        className="bg-background hover:bg-background"
        variant="ghost"
        onClick={() => {
          setNextTheme()
        }}
      >
        <Wand />
      </Button>
    </div>
  )
}
import ThemeChager from './theme-changer'

export default function Page() {
  return (
    <>
      <AuthThemeChager />
    </>
  )
}
/* globals.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    /* Colors */

    /*End Colors*/

    --background: 0 0% 100%;
    --foreground: 222.2 84% 4.9%;

    --card: 0 0% 100%;
    --card-foreground: 222.2 84% 4.9%;

    --popover: 0 0% 100%;
    --popover-foreground: 222.2 84% 4.9%;

    --primary: 173 79% 52%;
    --primary-foreground: 210 40% 2%;

    --secondary: 221 92% 52%;
    --secondary-foreground: 222.2 47.4% 11.2%;

    --muted: 210 40% 96.1%;
    --muted-foreground: 215.4 16.3% 46.9%;

    --accent: 210 40% 96.1%;
    --accent-foreground: 222.2 47.4% 11.2%;

    --destructive: 0 84.2% 60.2%;
    --destructive-foreground: 210 40% 98%;

    --success: 138 87% 40%;
    --success-foreground: 210 40% 98%;

    --border: 214.3 31.8% 91.4%;
    --input: 214.3 31.8% 71.4%;
    --ring: 222.2 84% 4.9%;

    --radius: 1.5rem;
  }

  .dark {
    --background: 255 3% 10%;
    --foreground: 210 60% 100%;

    --card: 222.2 84% 4.9%;
    --card-foreground: 210 40% 98%;

    --popover: 222.2 84% 4.9%;
    --popover-foreground: 210 40% 98%;

    --primary: 244 100% 60%;
    --primary-foreground: 0 100% 100%;

    --secondary: 173 100% 56%;
    --secondary-foreground: 210 40% 98%;

    --muted: 217.2 32.6% 17.5%;
    --muted-foreground: 215 20.2% 65.1%;

    --accent: 217.2 32.6% 17.5%;
    --accent-foreground: 210 40% 98%;

    --destructive: 0 55% 60.6%;
    --destructive-foreground: 210 40% 98%;

    --success: 138 87% 50%;
    --success-foreground: 210 40% 98%;

    --border: 217.2 0% 50%;
    --input: 217.2 0% 50%;
    --ring: 212.7 26.8% 83.9%;
  }

  .dark.gym {
    --background: 0 0% 8%;
    --foreground: 210 20% 80%;

    --primary: 118 100% 50%;
    --primary-foreground: 100 20% 10%;

    --secondary: 38 100% 50%;
    --secondary-foreground: 210 40% 98%;

    --input: var(--secondary);
    --radius: 0.3rem;
  }

  .dark.carservice {
    --background: 255 3% 10%;
    --foreground: 210 60% 100%;

    --primary: 0 100% 50%;
    --primary-foreground: 255 100% 100%;

    --secondary: 25 100% 65%;
    --secondary-foreground: 210 40% 98%;
  }

  .light.clinic {
    --background: 0 0% 100%;
    --foreground: 222.2 84% 4.9%;

    --primary: 210 100% 52%;
    --primary-foreground: 210 40% 100%;

    --secondary: 182 100% 25%;
    --secondary-foreground: 222.2 47.4% 11.2%;

    --radius: 0.5rem;
  }

  .light.aesthetics {
    --background: 310 100% 99%;
    --foreground: 222.2 84% 4.9%;

    --primary: 310 100% 70%;
    --primary-foreground: 210 40% 100%;

    --secondary: 216 100% 70%;
    --secondary-foreground: 222.2 47.4% 11.2%;

    --radius: 0.8rem;
  }

  .light.food {
    --background: 50 100% 50%;
    --foreground: 222.2 84% 4.9%;

    --primary: 15 100% 50%;
    --primary-foreground: 210 40% 100%;

    --secondary: 0 100% 50%;
    --secondary-foreground: 222.2 47.4% 11.2%;

    --radius: 0.8rem;
    --input: var(--foreground);
  }
}

@layer base {
  * {
    @apply border-border;
  }
  body {
    @apply bg-background text-foreground;
  }
}

html,
body {
  width: 100%;
  height: 100%;
}
0.0.6

2 months ago

0.0.5

2 months ago

0.0.4

2 months ago

0.0.3

8 months ago