Grunfeld
νΉμ§
- π κ°λ¨ν API: 볡μ‘ν μν κ΄λ¦¬ μμ΄ λͺ μ€μ μ½λλ‘ λνμμλ₯Ό κ΄λ¦¬ν μ μμ΅λλ€
- π― λκΈ°/λΉλκΈ° μ§μ: μΌλ°μ μΈ μλ¦ΌλΆν° μ¬μ©μ μλ΅μ΄ νμν νμΈ λνμμκΉμ§ λͺ¨λ μλ리μ€λ₯Ό μ§μν©λλ€
- π± μ μ°ν μμΉ μ€μ : μ€μ λͺ¨λ¬, νλ¨ μνΈ λ± λ€μν UI ν¨ν΄μ λ§μΆ° μμΉλ₯Ό μ‘°μ ν μ μμ΅λλ€
- π μ€λ§νΈν μ€ν κ΄λ¦¬: μ¬λ¬ λνμμκ° μ΄λ¦΄ λ λ Όλ¦¬μ μΈ LIFO(Last In First Out) μμλ‘ κ΄λ¦¬λ©λλ€
- π¨ 컀μ€ν μ€νμΌλ§: λ°±λλ‘ μ€νμΌλΆν° κ°λ³ λνμμ μ€νμΌκΉμ§ μμ λ‘κ² μ»€μ€ν°λ§μ΄μ§ κ°λ₯ν©λλ€
- π μ§κ΄μ μΈ UX: λ°°κ²½ ν΄λ¦μΌλ‘ λ«κΈ°, μλ ν¬μ»€μ€ κ΄λ¦¬ λ± μ¬μ©μ κ²½νμ κ³ λ €ν κΈ°λ₯λ€μ μ 곡ν©λλ€λ React μ ν리μΌμ΄μ μ μν κ°λ¨νκ³ κ°λ²Όμ΄ λνμμ(dialog) κ΄λ¦¬ λΌμ΄λΈλ¬λ¦¬μ λλ€.
μ€μΉ
npm install grunfeld
# λλ
yarn add grunfeld
νΉμ§
- π κ°λ¨ν APIλ‘ λνμμ κ΄λ¦¬
- οΏ½ λκΈ°/λΉλκΈ° λνμμ μ§μ
- π± μμΉ μ€μ κ°λ₯ ('center' λλ 'bottom')
- π λ€μ€ λνμμ μ€ν μ§μ
- π¨ 컀μ€ν μ€νμΌλ§ μ§μ
- π Light dismiss (λ°°κ²½ ν΄λ¦μΌλ‘ λ«κΈ°) μ΅μ
μ¬μ©λ²
κΈ°λ³Έ μ€μ
μ ν리μΌμ΄μ
μ μ΅μμ λ 벨μ GrunfeldProvider
λ₯Ό μΆκ°νμΈμ. μ΄ μ»΄ν¬λνΈλ λͺ¨λ λνμμλ₯Ό λ λλ§νκ³ κ΄λ¦¬νλ 컨ν
μ€νΈλ₯Ό μ 곡ν©λλ€:
import { GrunfeldProvider } from "grunfeld";
function App() {
return (
<GrunfeldProvider
options={{
defaultPosition: "center",
defaultDismiss: true,
backdropStyle: {
/* 컀μ€ν
λ°±λλ‘ μ€νμΌ */
},
}}
>
{/* μ ν리μΌμ΄μ
λ΄μ© */}
</GrunfeldProvider>
);
}
κΈ°λ³Έ λνμμ νμ
κ°μ₯ κΈ°λ³Έμ μΈ ννμ λνμμμ λλ€. μ¬μ©μμκ² μ 보λ₯Ό 보μ¬μ£Όκ±°λ κ°λ¨ν μνΈμμ©μ΄ νμν λ μ¬μ©ν©λλ€:
import { grunfeld } from "grunfeld";
function YourComponent() {
const showDialog = () => {
grunfeld.add({
element: <div>μλ
νμΈμ!</div>,
position: "center",
lightDismiss: true,
});
};
return <button onClick={showDialog}>λνμμ μ΄κΈ°</button>;
}
λΉλκΈ° λνμμ (μ¬μ©μ μλ΅ λκΈ°)
μ¬μ©μμ μ νμ΄λ μ λ ₯μ κΈ°λ€λ €μΌ ν λ μ¬μ©ν©λλ€. Promiseλ₯Ό λ°ννλ―λ‘ async/await ν¨ν΄μΌλ‘ μ¬μ©μμ μλ΅μ μ²λ¦¬ν μ μμ΅λλ€:
import { grunfeld } from "grunfeld";
function YourComponent() {
const showConfirmDialog = async () => {
const result = await grunfeld.addAsync((removeWith) => ({
element: (
<div>
<p>μ λ§ μμ νμκ² μ΅λκΉ?</p>
<button onClick={() => removeWith(true)}>νμΈ</button>
<button onClick={() => removeWith(false)}>μ·¨μ</button>
</div>
),
position: "center",
}));
if (result) {
console.log("μ¬μ©μκ° νμΈμ ν΄λ¦νμ΅λλ€");
} else {
console.log("μ¬μ©μκ° μ·¨μλ₯Ό ν΄λ¦νμ΅λλ€");
}
};
return <button onClick={showConfirmDialog}>νμΈ λνμμ</button>;
}
κ°λ¨ν λνμμ (ReactNodeλ§ μ λ¬)
볡μ‘ν μ€μ μμ΄ JSX μμλ λ¬Έμμ΄μ μ§μ μ λ¬νμ¬ λΉ λ₯΄κ² λνμμλ₯Ό νμν μ μμ΅λλ€:
import { grunfeld } from "grunfeld";
function YourComponent() {
const showSimpleDialog = () => {
// ReactNodeλ₯Ό μ§μ μ λ¬ν μ μμ΅λλ€
grunfeld.add(<div>κ°λ¨ν λ©μμ§</div>);
};
return <button onClick={showSimpleDialog}>κ°λ¨ν λνμμ</button>;
}
λνμμ μ κ±°
Grunfeldλ λνμμλ€μ μ€ν(Stack) κ΅¬μ‘°λ‘ κ΄λ¦¬ν©λλ€. μ΄λ λνμμλ€ κ°μ λ§₯λ½μ κ΄κ³λ₯Ό μ μ§νκΈ° μν¨μ λλ€.
μλ₯Ό λ€μ΄, A λνμμμμ B λνμμλ₯Ό μ΄μλ€λ©΄, Bκ° Aμ κ²°κ³Όλ‘ μμ±λ κ²μ΄λ―λ‘ Bκ° λ¨Όμ λ«νμΌ λ
Όλ¦¬μ μΌλ‘ μ¬λ°λ¦
λλ€. μ΄λ¬ν μμΉμ λ°λΌ remove()
λ νμ κ°μ₯ μ΅κ·Όμ μ΄λ¦° λνμμλΆν° μ κ±°ν©λλ€.
import { grunfeld } from "grunfeld";
// κ°μ₯ μ΅κ·Ό λνμμ μ κ±°
grunfeld.remove();
// λͺ¨λ λνμμ μ κ±°
grunfeld.clear();
API μ°Έμ‘°
GrunfeldProvider
μμ± | νμ | κΈ°λ³Έκ° | μ€λͺ |
---|---|---|---|
children | ReactNode | νμ | μμ μ»΄ν¬λνΈ |
options | GrunfeldProviderOptions | - | κΈ°λ³Έ μ€μ μ΅μ |
GrunfeldProviderOptions
μμ± | νμ | κΈ°λ³Έκ° | μ€λͺ | |
---|---|---|---|---|
defaultPosition | 'center' \ | 'bottom' | 'center' | λνμμμ κΈ°λ³Έ μμΉ |
defaultDismiss | boolean | true | κΈ°λ³Έ light dismiss μ€μ | |
backdropStyle | CSSProperties | - | λ°±λλ‘ μ»€μ€ν μ€νμΌ |
grunfeld κ°μ²΄
grunfeld.add(dialog)
μλ‘μ΄ λνμμλ₯Ό μΆκ°ν©λλ€.
λ§€κ°λ³μ:
dialog: GrunfeldProps
- λνμμ μ€μ
GrunfeldProps:
type GrunfeldProps =
| {
element: React.ReactNode;
position?: "center" | "bottom";
lightDismiss?: boolean;
dismissCallback?: () => unknown;
}
| React.ReactNode;
grunfeld.addAsync<T>(dialog)
λΉλκΈ° λνμμλ₯Ό μΆκ°νκ³ μ¬μ©μ μλ΅μ κΈ°λ€λ¦½λλ€.
λ§€κ°λ³μ:
dialog: (removeWith: (data: T) => T) => GrunfeldProps
- λνμμ ν©ν 리 ν¨μ
λ°νκ°:
Promise<T>
- μ¬μ©μκ°removeWith
λ₯Ό νΈμΆν λ μ λ¬ν λ°μ΄ν°
grunfeld.remove()
κ°μ₯ μ΅κ·Όμ μΆκ°λ λνμμλ₯Ό μ κ±°ν©λλ€.
μ΄ λ©μλλ LIFO(Last In First Out) μμΉμ λ°λ¦ λλ€. μ¬λ¬ λνμμκ° μ΄λ €μμ λ, κ°μ₯ λ§μ§λ§μ μ΄λ¦° λνμμλΆν° μμλλ‘ λ«νλλ€. μ΄λ λνμμλ€ κ°μ λ§₯λ½μ κ΄κ³λ₯Ό μ μ§νκΈ° μν μ€κ³μ λλ€.
// μμ: A β B β C μμλ‘ μ΄λ¦° κ²½μ°
grunfeld.remove(); // Cκ° λ«ν
grunfeld.remove(); // Bκ° λ«ν
grunfeld.remove(); // Aκ° λ«ν
grunfeld.clear()
λͺ¨λ λνμμλ₯Ό ν λ²μ μ κ±°ν©λλ€.
κΈ΄κΈν μν©μ΄λ νμ΄μ§ μ ν μ λͺ¨λ λνμμλ₯Ό μ 리ν΄μΌ ν λ μ¬μ©ν©λλ€. κ° λνμμμ dismissCallback
μ΄ μλ€λ©΄ λͺ¨λ μ€νλ ν μ κ±°λ©λλ€.
κ³ κΈ μ¬μ©λ²
컀μ€ν dismiss μ½λ°±
λνμμκ° λ«ν λ νΉμ λ‘μ§μ μ€νν΄μΌ νλ κ²½μ° dismissCallback
μ μ¬μ©ν©λλ€. μ΄λ μ 리 μμ
, μν μ
λ°μ΄νΈ, λΆμ μ΄λ²€νΈ μ μ‘ λ±μ μ μ©ν©λλ€:
grunfeld.add({
element: <MyDialog />,
dismissCallback: () => {
console.log("λνμμκ° λ«νμ΅λλ€");
// μ 리 μμ
μν
},
});
μμΉλ³ λνμμ
λ€μν UI ν¨ν΄μ λ§μΆ° λνμμμ μμΉλ₯Ό μ‘°μ ν μ μμ΅λλ€. κ° μμΉλ μλ‘ λ€λ₯Έ μ¬μ©μ κ²½νμ μ 곡ν©λλ€:
// μ€μμ νμ
grunfeld.add({
element: <CenterDialog />,
position: "center",
});
// νλ¨μ νμ (λ°ν
μνΈ μ€νμΌ)
grunfeld.add({
element: <BottomSheet />,
position: "bottom",
});