k8ordo
  • UI
  • Form
  • State
  • Router
  • Static
  • Server
Switch to dark mode
  • Get Started
  • Theming
  • i18n
  • Components
  • Hooks
  • Helpers
  • AI
Open navigation
Buttons
  • Button
  • IconButton
Navigation
  • Anchor
  • Tabs
  • Breadcrumb
  • Pagination
Forms
  • TextField
  • Textarea
  • NumberField
  • Select
  • Checkbox
  • CheckboxCard
  • CheckboxGroup
  • Switch
  • PasswordInput
  • Radio
  • RadioCard
  • Autocomplete
  • Slider
  • FileField
  • FormControl
  • Form
Data Display
  • Accordion
  • Avatar
  • Badge
  • Card
  • Code
  • Table
  • Heading
Feedback
  • Alert
  • Skeleton
  • Spinner
  • Toast
  • Progress
Overlays
  • Dialog
  • Drawer
  • Modal
  • Popover
  • DropdownMenu
  • Tooltip
  • ListBox
Layout
  • Stack
  • Grid
  • Separator
  • ScrollLinked
Media
  • Icons
k8ordo

React libraries that use Baseline features without holding back.

Packages
  • @k8ordo/ui
  • @k8ordo/form
  • @k8ordo/state
  • @k8ordo/router
  • @k8ordo/static
  • @k8ordo/server
UI
  • Get Started
  • Theming
  • i18n
  • Components
  • Hooks
  • Helpers
  • AI Chat
  • Generative UI
  • AI Agents
  • Storybook
Resources
  • GitHub
  • npm

© 2026 k8o — MIT License

Typeset in Noto Sans JP & M PLUS 2

Components

Buttons
  • Button
  • IconButton
Navigation
  • Anchor
  • Tabs
  • Breadcrumb
  • Pagination
Forms
  • TextField
  • Textarea
  • NumberField
  • Select
  • Checkbox
  • CheckboxCard
  • CheckboxGroup
  • Switch
  • PasswordInput
  • Radio
  • RadioCard
  • Autocomplete
  • Slider
  • FileField
  • FormControl
  • Form
Data Display
  • Accordion
  • Avatar
  • Badge
  • Card
  • Code
  • Table
  • Heading
Feedback
  • Alert
  • Skeleton
  • Spinner
  • Toast
  • Progress
Overlays
  • Dialog
  • Drawer
  • Modal
  • Popover
  • DropdownMenu
  • Tooltip
  • ListBox
Layout
  • Stack
  • Grid
  • Separator
  • ScrollLinked
Media
  • Icons

Modal

A modal dialog component.

View in Storybook

Import

Usage

Basic Usage

Confirmation

Are you sure you want to proceed?

Side

Center Modal

Centered on screen

Bottom Modal

Slides up from bottom

Right Modal

Slides in from right

Default Open

Top Layer & Portals

Modal renders in the browser top layer (a dialog element), so anything portaled to document.body ends up hidden behind it. Modal provides its own dialog element as a portal root via context — read it with usePortalRoot and portal there so floating UI stays on top inside a Modal. useToast inside a Modal already uses this mechanism automatically; you only need it for your own portals.

Props

aria-describedby?
Type: string
Default: -
aria-label?
Type: string
Default: -
aria-labelledby?
Type: string
Default: -
children?
Type: ReactNode
Default: -
defaultOpen?
Type: boolean
Default: -
isOpen?
Type: boolean
Default: -
onClose?
Type:
() => void
Default: -
ref?
Type: Ref<HTMLDialogElement>
Default: -
side?
Type: ModalSide
Default: 'center'
PropTypeDefault
aria-describedby?string-
aria-label?string-
aria-labelledby?string-
children?ReactNode-
defaultOpen?boolean-
isOpen?boolean-
onClose?() => void-
ref?Ref<HTMLDialogElement>-
side?
ModalSide
'center'
import { Modal } from '@k8ordo/ui';
const [isOpen, setIsOpen] = useState(false);

<Button onClick={() => setIsOpen(true)}>
  Open Modal
</Button>
<Modal
  isOpen={isOpen}
  onClose={() => setIsOpen(false)}
  side="center"
>
  <Dialog.Root>
    <Dialog.Header
      onClose={() => setIsOpen(false)}
      title="Confirmation"
    />
    <Dialog.Content>
      <p>Are you sure you want to proceed?</p>
    </Dialog.Content>
  </Dialog.Root>
</Modal>
<Button onClick={() => setCenterOpen(true)}>Center</Button>
<Button onClick={() => setBottomOpen(true)}>Bottom</Button>
<Button onClick={() => setRightOpen(true)}>Right</Button>

<Modal isOpen={centerOpen} onClose={() => setCenterOpen(false)} side="center">
  <Dialog.Root>
    <Dialog.Header onClose={() => setCenterOpen(false)} title="Center Modal" />
    <Dialog.Content>Centered on screen</Dialog.Content>
  </Dialog.Root>
</Modal>

<Modal isOpen={bottomOpen} onClose={() => setBottomOpen(false)} side="bottom">
  <Dialog.Root>
    <Dialog.Header onClose={() => setBottomOpen(false)} title="Bottom Modal" />
    <Dialog.Content>Slides up from bottom</Dialog.Content>
  </Dialog.Root>
</Modal>

<Modal isOpen={rightOpen} onClose={() => setRightOpen(false)} side="right">
  <Dialog.Root>
    <Dialog.Header onClose={() => setRightOpen(false)} title="Right Modal" />
    <Dialog.Content>Slides in from right</Dialog.Content>
  </Dialog.Root>
</Modal>
<Modal defaultOpen side="center">
  <Dialog.Root>
    <Dialog.Header
      onClose={() => {}}
      title="Default Open Modal"
    />
    <Dialog.Content>
      <p>This modal is open by default.</p>
    </Dialog.Content>
  </Dialog.Root>
</Modal>
import { usePortalRoot } from '@k8ordo/ui';
import { createPortal } from 'react-dom';

function FloatingLayer({ children }) {
  // Inside a Modal this is the top-layer <dialog>; outside it is undefined.
  const portalRoot = usePortalRoot();
  return createPortal(children, portalRoot?.current ?? document.body);
}