React中HeadlessUI模态框无法继承Tailwind暗色模式样式
问题原因
HeadlessUI的Dialog.Panel默认会通过Portal渲染到document.body节点下,而你的主题类(dark)是添加在<main>标签上的。由于Dialog的DOM层级不在<main>内部,无法继承到dark类,导致Tailwind的dark:前缀样式无法触发。
解决方案
方案1:将主题类添加到根元素(推荐)
把主题类直接加到html或body标签上,这样所有组件(包括通过Portal挂载的Dialog)都能继承主题样式。修改App组件的代码:
import React, { useState, useEffect } from 'react'; const App = () => { const [themeMode, setThemeMode] = useState('dark'); useEffect(() => { // 将主题类设置到html根元素 document.documentElement.className = themeMode; }, [themeMode]); return ( <main> <p className="bg-white text-black dark:bg-black dark:text-white"> hello world </p> {/* 其他组件 */} </main> ); }; export default App;
方案2:指定Dialog的挂载父元素
通过HeadlessUI Dialog的portal属性,将Dialog渲染到你添加了主题类的DOM层级下:
import { useState, useRef } from 'react' import { Dialog } from '@headlessui/react' function MyDialog() { let [isOpen, setIsOpen] = useState(true) // 创建ref指向主题类所在层级的容器 const dialogContainerRef = useRef(null) return ( <> {/* 这个容器必须在带有dark类的父元素内部 */} <div ref={dialogContainerRef}></div> <Dialog open={isOpen} onClose={() => setIsOpen(false)} portal={dialogContainerRef.current} // 指定Dialog挂载到该容器 > <Dialog.Panel> <Dialog.Title>Deactivate account</Dialog.Title> <Dialog.Description> This will permanently deactivate your account </Dialog.Description> <p className="bg-white text-black dark:bg-black dark:text-white"> Are you sure you want to deactivate your account? All of your data will be permanently removed. This action cannot be undone. </p> <button onClick={() => setIsOpen(false)}>Deactivate</button> <button onClick={() => setIsOpen(false)}>Cancel</button> </Dialog.Panel> </Dialog> </> ) }
方案3:手动给Dialog.Panel添加主题类
将当前的主题模式传递给Dialog组件,直接给Dialog.Panel加上主题类:
// 父组件中传递themeMode function App() { const [themeMode, setThemeMode] = useState('dark'); return ( <main className={themeMode}> <MyDialog themeMode={themeMode} /> </main> ) } // MyDialog组件接收并应用主题类 function MyDialog({ themeMode }) { let [isOpen, setIsOpen] = useState(true) return ( <Dialog open={isOpen} onClose={() => setIsOpen(false)}> <Dialog.Panel className={themeMode}> <Dialog.Title>Deactivate account</Dialog.Title> <Dialog.Description> This will permanently deactivate your account </Dialog.Description> <p className="bg-white text-black dark:bg-black dark:text-white"> Are you sure you want to deactivate your account? All of your data will be permanently removed. This action cannot be undone. </p> <button onClick={() => setIsOpen(false)}>Deactivate</button> <button onClick={() => setIsOpen(false)}>Cancel</button> </Dialog.Panel> </Dialog> ) }
内容的提问来源于stack exchange,提问作者Ahmer Saud
相关产品推荐
相关产品推荐

