headlessUI with styled-components
어제 올린 글 에서 headlessUI 로 로직을 분리한다면, 스타일은 어떻게 접목시킬지에 대해 고민을 했었다.
이리저리 삽질을 해보았는데, 해결책은 Styled-components 공식문서에서 찾았다.
import { createContext, useContext, useState } from "react";
const DropdownContext = createContext();
function DropDown(props) {
const openState = useState(false);
return (
<DropdownContext.Provider value={openState}>
{props.children}
</DropdownContext.Provider>
);
}
function useDropdownContext() {
const context = useContext(DropdownContext);
return context;
}
function DropDownTrigger(props) {
const [, setOpen] = useDropdownContext();
const handleTrigger = () => {
setOpen((prev) => !prev);
};
return (
<button {...props} onClick={handleTrigger}>
Trigger!
</button>
);
}
function DropDownList(props) {
const [open] = useDropdownContext();
return open ? <ul>{props.children}</ul> : null;
}
function DropDownItem() {
return <li>hi</li>;
}
DropDown.Trigger = DropDownTrigger;
DropDown.List = DropDownList;
DropDown.Item = DropDownItem;
export default DropDown;
import DropDown from "./Dropdown";
import "./styles.css";
import styled from "styled-components";
const MyTrigger = styled(DropDown.Trigger)`
width: 150px;
height: 100px;
background-color: red;
`;
export default function App() {
return (
<div className="App">
<h1>Title</h1>
<DropDown>
<MyTrigger />
<DropDown.List>
<DropDown.Item />
<DropDown.Item />
<DropDown.Item />
</DropDown.List>
</DropDown>
</div>
);
}
뭔가 간단히 Dropdown 처럼 느껴질만한 컴포넌트를 만들고, Trigger 버튼을 누르면 DropDown 의 List 가 보여지도록 하길 원했다.
그리고 Dropdown 에는 별도의 styled 가 적용되지 않는다.
스타일링을 위한 방법으로 styled 를 third-party component 와 결합하는 방법으로 className 을 주어 사용하도록 했다. styled 를 함수형태로 사용하여 스타일링을 하고자하는 컴포넌트(DropDown.Trigger)를 인수로 주고, DropDown.Trigger 컴포넌트는 props 로 받는 className 을 스타일을 입히는 태그에 className 을 주면 된다.
Compound Component Pattern 을 활용한 Headless 를 사용해보았는데, 실제 사용하고자 하는 컴포넌트에서 사용자가 의도대로 컴포넌트를 사용할지에 대한 우려가 있다.