Search code examples
pluginscomponentstailwind-cssdarkmode

How can I add Dark Mode styles in an addComponent function TailwindCSS


I am making some button components, but I need a way to implement Dark Mode. I know that adding styles for hover, focus, etc. states can be added like in the example below. How would I go about doing this for dark mode? How can I display the button differently when Dark Mode is enabled.

addComponents({
  '.button': {
    padding: '.5rem 1rem',
    borderRadius: '.25rem',
    fontWeight: '600',
    '&:hover': {
      backgroundColor: 'red',
    },
    '&:dark': { /* something like this? */
      backgroundColor: 'blue',
    },
  },
})

Solution

  • Dark mode in TailwindCSS is not so simple feature to replicate with plain CSS. By default it based on @media (prefers-color-scheme: dark). You may pass media variants into component

    addComponents({
        '.button': {
            padding: '.5rem 1rem',
            borderRadius: '.25rem',
            fontWeight: '600',
            '&:hover': {
                backgroundColor: 'red',
            },
    
            // media strategy
            '@media (prefers-color-scheme: dark)': {
                backgroundColor: 'blue',
            }
        }
    })
    

    It will work unless user specifies its strategy as class. So you need to add this case as another component - .dark <your-component>

    addComponents({
        '.button': {
            padding: '.5rem 1rem',
            borderRadius: '.25rem',
            fontWeight: '600',
            '&:hover': {
                backgroundColor: 'red',
            },
    
            // media strategy
            '@media (prefers-color-scheme: dark)': {
                backgroundColor: 'blue',
            },
        },
    
        // class strategy
        '.dark .button': {
            backgroundColor: 'blue',
        }
    })
    

    But it can fail too - user can specify ANY selector as a base for darkmode

    This is where dark: variant can be helpful - it do the job for you defining which type of selector user specified. However you still need to make two components (button and button-dark) and use it like

    <button class="button dark:button-dark"></button>
    

    Which is not user friendly

    But what you can do (and this is not mentioned in the docs - at least I didn't found, but I can see a test in source code named "should be possible to use apply in plugins") - is to pass @apply as key and empty object as a value. You can rewrite whole component with @apply or combine both CSS and Tailwind features

    addComponents({
        '.button': {
            padding: '.5rem 1rem',
            borderRadius: '.25rem',
            fontWeight: '600',
            '&:hover': {
                backgroundColor: 'red',
            },
    
            // dark mode
            '@apply dark:bg-blue-500 dark:hover:text-white': {},
        },
    })
    

    Now dark mode will work no matter the strategy

    DEMO - switch dark mode in a browser developer tools (or use darkMode: 'class' and add .dark to a wrapper)