Repository: h2oai/wave
File: ui/src/side_panel.tsx (TypeScript)

Code before:

import * as Fluent from '@fluentui/react'
import { B, Box, box, Id, S } from 'h2o-wave'
import React from 'react'
import { Component, XComponents } from './form'
import { bond, wave } from './ui'

export const sidePanelB: Box<SidePanel | null> = box(null)

/**
 * A dialog box (Dialog) is a temporary pop-up that takes focus from the page or app
 * and requires people to interact with it. It’s primarily used for confirming actions,
 * such as deleting a file, or asking people to make a choice.
 */
export interface SidePanel {
  /** The side panel's title. */
  title: S
  /** The components displayed in this side panel. */
  items: Component[]
  /** The width of the dialog, e.g. '400px'. Defaults to '600px'. */
  width?: S
  /** An identifying name for this component. */
  name?: Id
  /** The events to capture on this side panel. */
  events?: S[]
  /** True to disable close by clicking or tapping the area outside the panel. Defaults to False. */
  blocking?: B
}

export default bond(() => {
  const
    onDismiss = () => {
      const
        { blocking, name, events } = sidePanelB() || {},
        ev = events?.find(e => e === 'dismissed')

      if (!blocking && ev && name) wave.emit(name, ev, true)
      sidePanelB(null)
    },
    render = () => {
      const { title, width = '600px', items = [], blocking = false } = sidePanelB() || {}
      return (
        <Fluent.Panel
          isOpen={!!sidePanelB()}
          headerText={title}
          type={Fluent.PanelType.custom}
          customWidth={width}
          onDismiss={onDismiss}
          overlayProps={blocking ? { style: { cursor: 'default' } } : undefined}
          isBlocking={true}
          isLightDismiss={!blocking}>

Review comment (suggestion):
```suggestion
  /** True to prevent closing when clicking or tapping outside the side panel. Prevents interacting with the page behind the side panel. Defaults to False. */
```

Code after:

import * as Fluent from '@fluentui/react'
import { B, Box, box, Id, S } from 'h2o-wave'
import React from 'react'
import { Component, XComponents } from './form'
import { bond, wave } from './ui'

export const sidePanelB: Box<SidePanel | null> = box(null)

/**
 * A dialog box (Dialog) is a temporary pop-up that takes focus from the page or app
 * and requires people to interact with it. It’s primarily used for confirming actions,
 * such as deleting a file, or asking people to make a choice.
 */
export interface SidePanel {
  /** The side panel's title. */
  title: S
  /** The components displayed in this side panel. */
  items: Component[]
  /** The width of the dialog, e.g. '400px'. Defaults to '600px'. */
  width?: S
  /** An identifying name for this component. */
  name?: Id
  /** The events to capture on this side panel. */
  events?: S[]
  /** True to prevent closing when clicking or tapping outside the side panel. Prevents interacting with the page behind the side panel. Defaults to False. */
  blocking?: B
}

export default bond(() => {
  const
    onDismiss = () => {
      const
        { blocking, name, events } = sidePanelB() || {},
        ev = events?.find(e => e === 'dismissed')

      if (!blocking && ev && name) wave.emit(name, ev, true)
      sidePanelB(null)
    },
    render = () => {
      const { title, width = '600px', items = [], blocking = false } = sidePanelB() || {}
      return (
        <Fluent.Panel
          isOpen={!!sidePanelB()}
          headerText={title}
          type={Fluent.PanelType.custom}
          customWidth={width}
          onDismiss={onDismiss}
          overlayProps={blocking ? { style: { cursor: 'default' } } : undefined}
          isBlocking
          isLightDismiss={!blocking}>