GithubHelp home page GithubHelp logo

react18-tools / nextjs-themes-ultra Goto Github PK

View Code? Open in Web Editor NEW
4.0 1.0 1.0 1003 KB

๐ŸคŸ ๐Ÿ‘‰ Theme with confidence and [Unleash the Power of React Server Components](https://medium.com/javascript-in-plain-english/unleash-the-power-of-react-server-components-eb3fe7201231)

Home Page: https://nextjs-themes-ultra.vercel.app

License: MIT License

JavaScript 11.38% TypeScript 66.72% CSS 20.25% Handlebars 1.65%
nextjs nextjs13 nextjs14 react18 theme frontend javascript nodejs

nextjs-themes-ultra's Introduction

Nextjs-Themes-Ultra

test Maintainability codecov Version Downloads npm bundle size Gitpod ready-to-code

๐ŸคŸ ๐Ÿ‘‰ Unleash the Power of React Server Components

A canonical package with a longer and more descriptive name is also published - nextjs-themes-ultra

Motivation

I created nextjs-themes library to achieve functionality like next-themes with React Server Components. It worked well, however, I noticed issues with tree-shaking and also found that some functions that are rarely used can be removed or replaced to improve overall performance and readability.

I will update the main library nextjs-themes. However, it requires ensuring minimal changes to the existing APIs. And thus I created a new library, which has the potential to be a better alternative in most cases.

Features

โœ… Perfect dark mode in 2 lines of code

โœ… Works with Tailwind CSS

โœ… Fully Treeshakable (import from nthul/client/theme-switcher)

โœ… Designed for excellence

โœ… Full TypeScript Support

โœ… Unleash the full power of React18 Server components

โœ… System setting with prefers-color-scheme

โœ… Themed browser UI with color-scheme

โœ… Support for Next.js 13 & Next.js 14 appDir

โœ… No flash on load (for all - SSG, SSR, ISG, Server Components)

โœ… Sync theme across tabs and windows - can opt-out by passing dontSync to ThemeSwitcher

โœ… Apply custom transition when changing themes

โœ… Force pages to specific themes - requires assigning className (detailed techniques comming soon...)

โœ… Manipulate theme via useTheme hook

โœ… Documented with Typedoc (Docs)

โœ… Use combinations of th- and dark or light classes for dark/light variants of themes

โœ… Automatically avoids storing cookies when not using the corresponding ServerTarget

โœ… Works with all build systems/tools/frameworks for React18

Feel free to request or discuss new features or report bugs.

Install

A canonical package with a longer and more descriptive name is also published - nextjs-themes-ultra

$ pnpm add nthul

or

$ npm install nthul

or

$ yarn add nthul

Want Lite Version? npm bundle size Version Downloads

$ pnpm add nthul-lite

or

$ npm install nthul-lite

or

$ yarn add nthul-lite

You need r18gs as a peer-dependency

Usage

Please explore examples and packages/shared-ui for working examples. (updates coming soon...)

SPA (e.g., Vite, CRA) and Next.js pages directory (No server components)

The best way is to add a Custom App to use by modifying _app as follows:

Adding dark mode support takes 2 lines of code:

import { ThemeSwitcher, ColorSwitch } from "nthul/client"; // for better tree-shaking

function MyApp({ Component, pageProps }) {
  return (
    <>
      <ThemeSwitcher />
      {/* to add a switch */}
      <header>
        <ColorSwitch />
      </header>
      <Component {...pageProps} />
    </>
  );
}

export default MyApp;

โšก๐ŸŽ‰Boom! Just a couple of lines and your dark mode is ready! That too with an awesome color switch for user preferred settings.

Check out examples for advanced usage.

For vite or any other build tool you can find a similar root component. E.g., component in CRA and vite.

With Next.js app router (Server Components)

If your app is mostly serving static content, you do not want the overhead of SSR.

When using this approach, you need to use CSS general sibling Combinator (~) to make sure your themed CSS is properly applied. See (HTML & CSS)[#html--css].

Update your app/layout.jsx to add ThemeSwitcher, and ServerTarget. ServerTarget is required to avoid a flash of un-themed content on reload.

// app/layout.jsx
import { ThemeSwitcher } from "nthul/client/theme-switcher"; // for better tree-shaking
import { ServerTarget } from "nthul/server/nextjs";

export default function Layout({ children }) {
  return (
    <html lang="en">
      <head />
      <body>
        /** use ServerTarget as first element inside body */
        <ServerTarget />
        <ThemeSwitcher />
        {children}
      </body>
    </html>
  );
}

โšก๐ŸŽ‰ Woohoo! You just added multiple theme and color-scheme modes and you can also use Server Component! Isn't that awesome?

ColorSwitch

An elegant color-switch to toggle coloe-schemes ("dark" | "light" | "system").

<ColorSwitch />

HTML & CSS

That's it, your Next.js app fully supports dark mode, including System preference with prefers-color-scheme. The theme is also immediately synced between tabs. By default, nthul modifies the className on the html element, which you can easily use to style your app:

:root {
  /* Your default theme */
  --background: white;
  --foreground: black;
}

.dark {
  --background: black;
  --foreground: white;
}

/* for custom themes */

.th-theme1 {
  --background: red;
  --foreground: yellow;
}

/* for custom theme with dark and light variants */

.dark.th-theme2 {
  --background: blue;
  --foreground: white;
}

.light.th-theme2 {
  --background: white;
  --foreground: blue;
}

/* for scoped containers add .nth-scoped call as well - required only when using containerised themes. */
.nth-scoped.th-.dark { /* use th- to make sure outer theme is not applied to container with no theme  */
  ...
}

.nth-scoped.th-theme.dark {
  ...
}

Also see Example CSS file.

When using ServerTarget

when using ServerTarget, you need to use CSS general sibling Combinator (~) as ServerTarget is not wrapping your app.

Replace .selector with a combination of selectors from the description above.

/*
for the target element itself, e.g., the html tag.
in most cases, this is inherited by all child elements.
*/
.selector,

/* for forcing to the child elements. */
.selector *,

/* when using ServerTarget */

.selector ~ *, // for all following siblings

.selector ~ * * // for all the children of the following siblings
{
  // ...your styles
}

Please note that we have not added a comma (',') after the last selector.

Without comments, it should look like following.

.selector,
.selector *,
.selector ~ *,
.selector ~ * * {
  --th-variable: value;
}

We encourage you to use this pattern for defining your theme variables in CSS to avoid any unwanted overrides.

Images

You can also show different images based on the current theme.

import Image from "next/image";
import { useTheme } from "nthul/hooks";

function ThemedImage() {
  const { resolvedColorScheme } = useTheme();
  let src;

  switch (resolvedColorScheme) {
    case "light":
      src = "/light.png";
      break;
    case "dark":
      src = "/dark.png";
      break;
    default:
      src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
      break;
  }

  return <Image src={src} width={400} height={400} />;
}

export default ThemedImage;

useTheme

In case your components need to know the current theme and be able to change it. The useTheme hook provides theme information:

import { useTheme } from "nthul";

const ThemeChanger = () => {
  const { theme, setTheme } = useTheme();

  return (
    <div>
      The current theme is: {theme}
      <button onClick={() => setTheme("light")}>Light Mode</button>
      <button onClick={() => setTheme("dark")}>Dark Mode</button>
    </div>
  );
};

useTheme hook will return following object.

interface UseTheme {
  theme: string;
  colorSchemePreference: "dark" | "light" | "system";
  systemColorScheme: "dark" | "light";
  resolvedColorScheme: "dark" | "light";
  setColorSchemePreference: (colorSchemePreference: ColorSchemePreference) => void;
  setTheme: (theme: string) => void;
}

Force per page theme and color-scheme

We have not added any components or hooks for forcing theme and color-scheme per page or per element basis. As this is a rarely used scenario. However, you can acheive this by applying appropreate calssNames.

// force a theme for the page
export default function Page() {
  return <div className="dark nth-scoped th-theme1">...</div>;
}

We are open to listening your feedback - Discussions

With Styled Components and any CSS-in-JS

Next Themes is completely CSS independent, it will work with any library. For example, with Styled Components you just need to createGlobalStyle in your custom App:

// pages/_app.js
import { createGlobalStyle } from "styled-components";
import { ThemeSwitcher } from "nthul";

// Your themeing variables
const GlobalStyle = createGlobalStyle`
  :root {
    --fg: #000;
    --bg: #fff;
  }

  [data-theme="dark"] {
    --fg: #fff;
    --bg: #000;
  }
`;

function MyApp({ Component, pageProps }) {
  return (
    <>
      <GlobalStyle />
      <ThemeSwitcher />
      <Component {...pageProps} />
    </>
  );
}

With Tailwind

In your tailwind.config.js, set the dark mode property to class:

// tailwind.config.js
module.exports = {
  darkMode: "class",
};

โšก๐ŸŽ‰Boom! You are ready to use darkTheme in tailwind.

Caution! Your class must be set to "dark", which is the default value we have used for this library. Tailwind, as of now, requires that class name must be "dark" for dark-theme.

That's it! Now you can use dark-mode specific classes:

<h1 className="text-black dark:text-white">

Contributing

What's inside?

Utilities

This Turborepo template includes pre-configured tools:

  • TypeScript for static type checking
  • ESLint for code linting
  • Prettier for code formatting
  • Plop based code generator for scaffolding new components
  • Automatically rebrand this template to match your repo name

Apps and Packages

This Turborepo includes the following packages/examples/lib:

  • nextjs: a Next.js app
  • vite: a Vite.js app
  • fork-me: a React component library shared by both Next.js and Vite examples
  • eslint-config-custom: ESLint configurations (includes eslint-config-next and eslint-config-prettier)
  • tsconfig: tsconfig.jsons used throughout the monorepo

Each package/example is 100% TypeScript.

Build

To build all apps and packages, run the following command:

cd nthul
pnpm build

Develop

To develop all apps and packages, run the following command:

cd nthul
pnpm dev

๐Ÿคฉ Don't forger to start this repo!

Want hands-on course for getting started with Turborepo? Check out React and Next.js with TypeScript and The Game of Chess with Next.js, React and TypeScrypt

Repo Stats

License

Licensed as MIT open source.


with ๐Ÿ’– by Mayank Kumar Chaudhari

nextjs-themes-ultra's People

Contributors

mayank1513 avatar deepsource-autofix[bot] avatar

Stargazers

Santiago Laight avatar Mark avatar nuttycc avatar  avatar

Watchers

 avatar

Forkers

mayank1513

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.