DocumentationGuidesThink in overlay-kit

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

  1. 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.
  2. 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.
  3. 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

  1. Design Following React Philosophy

    • React favors declarative code.
    • overlay-kit helps manage overlays declaratively.
  2. Improve Development Productivity

    • By encapsulating state management and event handling, developers can focus solely on UI and business logic.
  3. 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:

  1. overlay.open: Provides functionality to open and close overlays.
  2. 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.