Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/daisyui/functions/generateThemeFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { getFileNames } from "./getFileNames.js"

export const wrapContent = (themeName, content) => {
if (themeName === "light") {
return `:root,:root:has(input.theme-controller[value=${themeName}]:checked),[data-theme="${themeName}"] {
return `:root,:root:has(input.theme-controller[value="${themeName}"]:checked),[data-theme="${themeName}"] {
${content}}
`
}

return `:root:has(input.theme-controller[value=${themeName}]:checked),[data-theme="${themeName}"] {
return `:root:has(input.theme-controller[value="${themeName}"]:checked),[data-theme="${themeName}"] {
${content}}
`
}
Expand Down
14 changes: 4 additions & 10 deletions packages/daisyui/functions/pluginOptionsHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,15 @@ export const pluginOptionsHandler = (() => {
if (theme) {
// Use prefix for theme-controller class name
const themeControllerClass = `${prefix}theme-controller`
let selector = `${root}:has(input.${themeControllerClass}[value=${themeName}]:checked),[data-theme=${themeName}]`
let selector = `${root}:has(input.${themeControllerClass}[value="${themeName}"]:checked),[data-theme="${themeName}"]`
if (flags.includes("--default")) {
selector = `:where(${root}),${selector}`
}
addBase({ [selector]: theme })

if (flags.includes("--prefersdark")) {
// Use :root:not([data-theme]) for dark mode specificity
const darkSelector =
root === ":root" ? ":root:not([data-theme])" : `${root}:not([data-theme])`
addBase({ "@media (prefers-color-scheme: dark)": { [darkSelector]: theme } })
addBase({ "@media (prefers-color-scheme: dark)": { [`${root}:not([data-theme])`]: theme } })
}
}
}
Expand All @@ -45,9 +43,7 @@ export const pluginOptionsHandler = (() => {
}

if (themesObject["dark"]) {
const darkSelector =
root === ":root" ? ":root:not([data-theme])" : `${root}:not([data-theme])`
addBase({ "@media (prefers-color-scheme: dark)": { [darkSelector]: themesObject["dark"] } })
addBase({ "@media (prefers-color-scheme: dark)": { [`${root}:not([data-theme])`]: themesObject["dark"] } })
}

themeOrder.forEach((themeName) => {
Expand Down Expand Up @@ -77,10 +73,8 @@ export const pluginOptionsHandler = (() => {
themeArray.forEach((themeOption) => {
const [themeName, ...flags] = themeOption.split(" ")
if (flags.includes("--prefersdark")) {
const darkSelector =
root === ":root" ? ":root:not([data-theme])" : `${root}:not([data-theme])`
addBase({
"@media (prefers-color-scheme: dark)": { [darkSelector]: themesObject[themeName] },
"@media (prefers-color-scheme: dark)": { [`${root}:not([data-theme])`]: themesObject[themeName] },
})
}
})
Expand Down
18 changes: 9 additions & 9 deletions packages/daisyui/functions/pluginOptionsHandler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ test("pluginOptionsHandler should apply default themes", () => {
pluginOptionsHandler(options, mockAddBase, mockThemesObject, "1.0.0")

expect(mockAddBase).toHaveBeenCalledWith({
":where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light]": {
":where(:root),:root:has(input.theme-controller[value=\"light\"]:checked),[data-theme=\"light\"]": {
color: "white",
},
})
expect(mockAddBase).toHaveBeenCalledWith({
"@media (prefers-color-scheme: dark)": { ":root:not([data-theme])": { color: "black" } },
})
expect(mockAddBase).toHaveBeenCalledWith({
":root:has(input.theme-controller[value=dark]:checked),[data-theme=dark]": {
":root:has(input.theme-controller[value=\"dark\"]:checked),[data-theme=\"dark\"]": {
color: "black",
},
})
expect(mockAddBase).toHaveBeenCalledWith({
":root:has(input.theme-controller[value=light]:checked),[data-theme=light]": {
":root:has(input.theme-controller[value=\"light\"]:checked),[data-theme=\"light\"]": {
color: "white",
},
})
Expand All @@ -45,15 +45,15 @@ test("pluginOptionsHandler should apply all themes when 'all' is specified", ()
pluginOptionsHandler(options, mockAddBase, mockThemesObject, "1.0.0")

expect(mockAddBase).toHaveBeenCalledWith({
":where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light]": {
":where(:root),:root:has(input.theme-controller[value=\"light\"]:checked),[data-theme=\"light\"]": {
color: "white",
},
})
expect(mockAddBase).toHaveBeenCalledWith({
"@media (prefers-color-scheme: dark)": { ":root:not([data-theme])": { color: "black" } },
})
expect(mockAddBase).toHaveBeenCalledWith({
":root:has(input.theme-controller[value=dark]:checked),[data-theme=dark]": {
":root:has(input.theme-controller[value=\"dark\"]:checked),[data-theme=\"dark\"]": {
color: "black",
},
})
Expand All @@ -68,7 +68,7 @@ test("pluginOptionsHandler should handle custom themes", () => {
pluginOptionsHandler(options, mockAddBase, mockThemesObject, "1.0.0")

expect(mockAddBase).toHaveBeenCalledWith({
":root:has(input.theme-controller[value=custom]:checked),[data-theme=custom]": {
":root:has(input.theme-controller[value=\"custom\"]:checked),[data-theme=\"custom\"]": {
color: "blue",
},
})
Expand All @@ -95,7 +95,7 @@ test("pluginOptionsHandler should not create duplicate styles for single light t
// Should be called exactly once
expect(mockAddBase).toHaveBeenCalledTimes(1)
expect(mockAddBase).toHaveBeenCalledWith({
":where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light]": {
":where(:root),:root:has(input.theme-controller[value=\"light\"]:checked),[data-theme=\"light\"]": {
color: "white",
},
})
Expand All @@ -111,7 +111,7 @@ test("pluginOptionsHandler should not create duplicate styles for single dark th
// Should be called exactly once
expect(mockAddBase).toHaveBeenCalledTimes(1)
expect(mockAddBase).toHaveBeenCalledWith({
":where(:root),:root:has(input.theme-controller[value=dark]:checked),[data-theme=dark]": {
":where(:root),:root:has(input.theme-controller[value=\"dark\"]:checked),[data-theme=\"dark\"]": {
color: "black",
},
})
Expand All @@ -125,7 +125,7 @@ test("pluginOptionsHandler should prefix theme-controller class when prefix is s
pluginOptionsHandler(options, mockAddBase, mockThemesObject, "1.0.0")

expect(mockAddBase).toHaveBeenCalledWith({
":where(:root),:root:has(input.myprefix-theme-controller[value=light]:checked),[data-theme=light]":
":where(:root),:root:has(input.myprefix-theme-controller[value=\"light\"]:checked),[data-theme=\"light\"]":
{
color: "white",
},
Expand Down
7 changes: 3 additions & 4 deletions packages/daisyui/functions/themePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ export default plugin.withOptions((options = {}) => {
prefersdark = false,
"color-scheme": colorScheme = "normal",
root = ":root",
prefix = "",
...customThemeTokens
} = options

let selector = `${root}:has(input.theme-controller[value=${name}]:checked),[data-theme="${name}"]`
let selector = `${root}:has(input.${prefix}theme-controller[value="${name}"]:checked),[data-theme="${name}"]`
if (isDefault) {
selector = `:where(${root}),${selector}`
}
Expand All @@ -37,11 +38,9 @@ export default plugin.withOptions((options = {}) => {

if (prefersdark) {
// Use :root:not([data-theme]) for dark mode specificity
const darkSelector =
root === ":root" ? ":root:not([data-theme])" : `${root}:not([data-theme])`
addBase({
"@media (prefers-color-scheme: dark)": {
[darkSelector]: baseStyles[selector],
[`${root}:not([data-theme])`]: baseStyles[selector],
},
})
}
Expand Down
4 changes: 3 additions & 1 deletion packages/docs/src/routes/(routes)/docs/themes/+page.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ To add a new theme, use `@plugin "daisyui/theme" {}` in your CSS file, with the
default: true; /* set as default */
prefersdark: false; /* set as default dark mode (prefers-color-scheme:dark) */
color-scheme: light; /* color of browser-provided UI */
root: '.my-custom-root'; /* OPTIONAL - use same value used in @plugin "daisyui" if you used a custom root */
prefix: 'my-custom-prefix-'; /* OPTIONAL - use same value used in @plugin "daisyui" if you used a custom daisyui prefix */

--color-base-100: oklch(98% 0.02 240);
--color-base-200: oklch(95% 0.03 240);
Expand Down Expand Up @@ -151,7 +153,7 @@ To add a new theme, use `@plugin "daisyui/theme" {}` in your CSS file, with the
If you're using CDN and you want to use a custom theme, use it like this:

```css:app.css
:root:has(input.theme-controller[value=mytheme]:checked),[data-theme="mytheme"] { /* mytheme is the name of the custom theme */
:root:has(input.theme-controller[value="mytheme"]:checked),[data-theme="mytheme"] { /* mytheme is the name of the custom theme */
color-scheme: light;
--color-base-100: oklch(98% 0.02 240);
/* ...rest of CSS variables like above example */
Expand Down