Think in overlay-kit
Let’s explore overlay-kit
, which is based on React’s philosophy, and the Declarative Overlay Pattern that embodies it.
Why Use overlay-kit
Problems with Traditional Overlay Management
-
Complexity of State Management
- Had to manage overlay state directly using
useState
or global state. - Code became complex and less readable as state management mixed with UI logic.
- Had to manage overlay state directly using
-
Repetitive Event Handling
- Had to repeatedly write event handling code for opening, closing, and returning results.
- This led to code duplication and degraded development experience.
-
Lack of Reusability
- UI and logic were tightly coupled through callback functions to return values from overlays.
- This made it difficult to reuse components.
Goals of overlay-kit
-
Design Following React Philosophy
- React favors declarative code.
overlay-kit
helps manage overlays declaratively.
-
Improve Development Productivity
- By encapsulating state management and event handling, developers can focus solely on UI and business logic.
-
Enhance Extensibility and Reusability
- Increased overlay reusability by separating UI and behavior, and returning Promises.
Declarative Overlay Pattern
Traditional overlay management used an Imperative approach.
Code was complex and hard to maintain due to state management with useState
and mixed event handling code.
The Declarative Overlay Pattern allows writing more intuitive and declarative code by managing overlays based on behavior rather than state.
Imperative Approach
State management and event handling were mixed, leading to code duplication and less readability.
import { useState } from 'react';
function Overlay() {
const [isOpen, setIsOpen] = useState(false);
function handleOpen() {
setIsOpen(true);
}
function handleClose() {
setIsOpen(false);
}
return (
<>
<Button onClick={handleOpen}>Open</Button>
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>Imperative Overlay</DialogTitle>
<DialogActions>
<Button onClick={handleClose}>OK</Button>
<Button onClick={handleClose}>Cancel</Button>
</DialogActions>
</Dialog>
</>
);
}
Declarative Approach
State management code was removed, leading to improved readability and maintainability.
import { overlay } from 'overlay-kit';
function Overlay() {
return (
<Button
onClick={() => {
overlay.open(({ isOpen, close }) => (
<Dialog open={isOpen} onClose={close}>
<DialogTitle>Declarative Overlay</DialogTitle>
<DialogActions>
<Button onClick={close}>OK</Button>
<Button onClick={close}>Cancel</Button>
</DialogActions>
</Dialog>
));
}}
>
Open
</Button>
);
}
Core Principles
To understand the design of overlay-kit, the following principles are important:
Co-location
Related code is placed close together to make the code easier to understand.
All overlay calls, state management, and component definition are handled in one place, leading to better readability.
Minimum API
overlay-kit provides a simple and concise API. The core APIs are two:
overlay.open
: Provides functionality to open and close overlays.overlay.openAsync
: Allows processing asynchronous logic by returning values.
These two APIs leverage general JavaScript patterns to enable implementing various overlays.
For example, overlay.openAsync returns a Promise, making it easy to apply chaining patterns.