diff --git a/next-themes/src/index.tsx b/next-themes/src/index.tsx index c3dc639..f510b92 100644 --- a/next-themes/src/index.tsx +++ b/next-themes/src/index.tsx @@ -1,8 +1,8 @@ 'use client' import * as React from 'react' -import type { UseThemeProps, ThemeProviderProps } from './types' import { script } from './script' +import type { Attribute, ThemeProviderProps, UseThemeProps } from './types' const colorSchemes = ['light', 'dark'] const MEDIA = '(prefers-color-scheme: dark)' @@ -52,18 +52,22 @@ const Theme = ({ const enable = disableTransitionOnChange ? disableAnimation() : null const d = document.documentElement - if (attribute === 'class') { - d.classList.remove(...attrs) - - if (name) d.classList.add(name) - } else { - if (name) { - d.setAttribute(attribute, name) - } else { - d.removeAttribute(attribute) + const handleAttribute = (attr: Attribute) => { + if (attr === 'class') { + d.classList.remove(...attrs) + if (name) d.classList.add(name) + } else if (attr.startsWith('data-')) { + if (name) { + d.setAttribute(attr, name) + } else { + d.removeAttribute(attr) + } } } + if (Array.isArray(attribute)) attribute.forEach(handleAttribute) + else handleAttribute(attribute) + if (enableColorScheme) { const fallback = colorSchemes.includes(defaultTheme) ? defaultTheme : null const colorScheme = colorSchemes.includes(resolved) ? resolved : fallback diff --git a/next-themes/src/types.ts b/next-themes/src/types.ts index 807cec8..abbb89a 100644 --- a/next-themes/src/types.ts +++ b/next-themes/src/types.ts @@ -19,6 +19,8 @@ export interface UseThemeProps { systemTheme?: 'dark' | 'light' | undefined } +export type Attribute = `data-${string}` | 'class' + export interface ThemeProviderProps extends React.PropsWithChildren { /** List of all available theme names */ themes?: string[] | undefined @@ -34,8 +36,8 @@ export interface ThemeProviderProps extends React.PropsWithChildren { storageKey?: string | undefined /** Default theme name (for v0.0.12 and lower the default was light). If `enableSystem` is false, the default theme is light */ defaultTheme?: string | undefined - /** HTML attribute modified based on the active theme. Accepts `class` and `data-*` (meaning any data attribute, `data-mode`, `data-color`, etc.) */ - attribute?: `data-${string}` | 'class' | undefined + /** HTML attribute modified based on the active theme. Accepts `class`, `data-*` (meaning any data attribute, `data-mode`, `data-color`, etc.), or an array which could include both */ + attribute?: Attribute | Attribute[] | undefined /** Mapping of theme name to HTML attribute value. Object where key is the theme name and value is the attribute value */ value?: ValueObject | undefined /** Nonce string to pass to the inline script for CSP headers */