diff --git a/packages/preset-mini/src/index.ts b/packages/preset-mini/src/index.ts index 67514b4b21..d8c0d221ee 100644 --- a/packages/preset-mini/src/index.ts +++ b/packages/preset-mini/src/index.ts @@ -11,16 +11,38 @@ export { parseColor } from './utils' export type { ThemeAnimation, Theme } +export interface DarkModeSelectors { + /** + * Selector for light variant. + * + * @default '.light' + */ + light?: string + + /** + * Selector for dark variant. + * + * @default '.dark' + */ + dark?: string +} + export interface PresetMiniOptions extends PresetOptions { /** + * Dark mode options + * * @default 'class' */ - dark?: 'class' | 'media' + dark?: 'class' | 'media' | DarkModeSelectors /** + * Generate pesudo selector as `[group=""]` instead of `.group` + * * @default false */ attributifyPseudo?: Boolean /** + * Prefix for CSS variables. + * * @default 'un-' */ variablePrefix?: string diff --git a/packages/preset-mini/src/variants/dark.ts b/packages/preset-mini/src/variants/dark.ts index ebfb2397ac..6a34d3cf13 100644 --- a/packages/preset-mini/src/variants/dark.ts +++ b/packages/preset-mini/src/variants/dark.ts @@ -3,10 +3,14 @@ import type { PresetMiniOptions } from '..' import { variantMatcher, variantParentMatcher } from '../utils' export const variantColorsMediaOrClass = (options: PresetMiniOptions = {}): Variant[] => { - if (options?.dark === 'class') { + if (options?.dark === 'class' || typeof options.dark === 'object') { + const { dark = '.dark', light = '.light' } = typeof options.dark === 'string' + ? {} + : options.dark + return [ - variantMatcher('dark', input => ({ prefix: `.dark $$ ${input.prefix}` })), - variantMatcher('light', input => ({ prefix: `.light $$ ${input.prefix}` })), + variantMatcher('dark', input => ({ prefix: `${dark} $$ ${input.prefix}` })), + variantMatcher('light', input => ({ prefix: `${light} $$ ${input.prefix}` })), ] } diff --git a/test/__snapshots__/preset-mini.test.ts.snap b/test/__snapshots__/preset-mini.test.ts.snap index ece9a09915..d81ea07926 100644 --- a/test/__snapshots__/preset-mini.test.ts.snap +++ b/test/__snapshots__/preset-mini.test.ts.snap @@ -7,6 +7,16 @@ exports[`preset-mini > custom var prefix 1`] = ` .scale-100{--hi-scale-x:1;--hi-scale-y:1;transform:translateX(var(--hi-translate-x)) translateY(var(--hi-translate-y)) translateZ(var(--hi-translate-z)) rotate(var(--hi-rotate)) rotateX(var(--hi-rotate-x)) rotateY(var(--hi-rotate-y)) rotateZ(var(--hi-rotate-z)) skewX(var(--hi-skew-x)) skewY(var(--hi-skew-y)) scaleX(var(--hi-scale-x)) scaleY(var(--hi-scale-y)) scaleZ(var(--hi-scale-z));}" `; +exports[`preset-mini > dark customizing selector 1`] = ` +"/* layer: default */ +[data-mode=\\"dark\\"] .dark\\\\:bg-white{--un-bg-opacity:1;background-color:rgba(255,255,255,var(--un-bg-opacity));} +[data-mode=\\"light\\"] .light\\\\:bg-black{--un-bg-opacity:1;background-color:rgba(0,0,0,var(--un-bg-opacity));} +[data-mode=\\"dark\\"] .dark\\\\:hover\\\\:rounded:hover{border-radius:0.25rem;} +[data-mode=\\"dark\\"] .dark\\\\:text-lg{font-size:1.125rem;line-height:1.75rem;} +[data-mode=\\"light\\"] .light\\\\:text-sm{font-size:0.875rem;line-height:1.25rem;} +[data-mode=\\"light\\"] .light\\\\:disabled\\\\:w-full:disabled{width:100%;}" +`; + exports[`preset-mini > nested theme colors 1`] = ` "/* layer: default */ .bg-a-b-c{--un-bg-opacity:1;background-color:rgba(81,69,67,var(--un-bg-opacity));} diff --git a/test/preset-mini.test.ts b/test/preset-mini.test.ts index 4b713fb850..89558da446 100644 --- a/test/preset-mini.test.ts +++ b/test/preset-mini.test.ts @@ -27,6 +27,32 @@ const uno = createGenerator({ }) describe('preset-mini', () => { + test('dark customizing selector', async () => { + const uno = createGenerator({ + presets: [ + presetMini({ + dark: { + dark: '[data-mode="dark"]', + light: '[data-mode="light"]', + }, + }), + ], + }) + + const { css } = await uno.generate([ + 'dark:bg-white', + 'dark:text-lg', + 'dark:hover:rounded', + 'light:bg-black', + 'light:text-sm', + 'light:disabled:w-full', + ].join(' '), { + preflights: false, + }) + + expect(css).toMatchSnapshot() + }) + test('targets', async () => { const code = presetMiniTargets.join(' ') const { css } = await uno.generate(code)