Modeless

An independent work window that leaves the background interface usable.

Live preview
Interact with the component to see results here.
View code
HTML
<sy-modeless
  closable
  draggable="true"
  width="280"
  height="220"
  top="80"
  left="12"
  resizable
  minimizable
  maximizable
  animation="none"
  id="sample"
><span slot="title">Task notes</span>
  <div slot="content">
    <p>Keep this window open while using other views.</p>
    <sy-input placeholder="Enter a note" aria-label="Task notes"></sy-input>
  </div>
</sy-modeless>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Open work window</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

Usage guide

#

Use for supporting windows that stay usable alongside the main view, such as notes or tools. Use Modal for mandatory confirmation.

Title and content
Use the title and content slots to make the window's purpose clear.
Position and size
Enable movement and resizing with draggable and resizable. After minimizing or maximizing, restore with setRestore().
Manage multiple windows
Create windows with sy-modeless-group's create() and manage them with updateTitle(), updateContent(), and close(). Give each window a unique id.

Examples

#

Independent window

Background actions remain available while the window is open.

View code
HTML
<sy-modeless
  closable
  draggable="true"
  width="280"
  height="220"
  top="80"
  left="12"
  id="sample"
><span slot="title">Task notes</span>
  <div slot="content">
    <p>Keep this window open while using other views.</p>
    <sy-input placeholder="Enter a note" aria-label="Task notes"></sy-input>
  </div>
</sy-modeless>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Open work window</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

Move and resize

Drag the title to move the window and its edges to resize it.

View code
HTML
<sy-modeless
  closable
  draggable="true"
  width="280"
  height="220"
  top="80"
  left="12"
  resizable
  id="sample"
><span slot="title">Task notes</span>
  <div slot="content">
    <p>Keep this window open while using other views.</p>
    <sy-input placeholder="Enter a note" aria-label="Task notes"></sy-input>
  </div>
</sy-modeless>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Open work window</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

Minimize, maximize, and restore

Switch window states with buttons.

View code
HTML
<sy-modeless
  closable
  draggable="true"
  width="280"
  height="220"
  top="80"
  left="12"
  minimizable
  maximizable
  id="sample"
><span slot="title">Task notes</span>
  <div slot="content">
    <p>Keep this window open while using other views.</p>
    <sy-input placeholder="Enter a note" aria-label="Task notes"></sy-input>
  </div>
</sy-modeless>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Open</sy-button>
  <sy-button id="action-1" size="small">Minimize</sy-button>
  <sy-button id="action-2" size="small">Maximize</sy-button>
  <sy-button id="action-3" size="small">Restore</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget1 = document.querySelector("#sample");
  document.querySelector('#action-1').addEventListener('click', async () => {
    const result = await actionTarget1.setMinimum();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget2 = document.querySelector("#sample");
  document.querySelector('#action-2').addEventListener('click', async () => {
    const result = await actionTarget2.setMaximum();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget3 = document.querySelector("#sample");
  document.querySelector('#action-3').addEventListener('click', async () => {
    const result = await actionTarget3.setRestore();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

Manage multiple windows

Manage windows with distinct ids in a group.

View code
HTML
<sy-modeless-group id="sample"></sy-modeless-group>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">First window</sy-button>
  <sy-button id="action-1" size="small">Second window</sy-button>
  <sy-button id="action-2" size="small">Change title</sy-button>
  <sy-button id="action-3" size="small">Close all</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.create("note-a", "Task notes",
      "\u003cp>This is the first note.\u003c/p>", {
        "width": 250,
        "height": 180,
        "top": 130,
        "left": 12,
        "closable": true
      });
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget1 = document.querySelector("#sample");
  document.querySelector('#action-1').addEventListener('click', async () => {
    const result = await actionTarget1.create("note-b", "Reference material",
      "\u003cp>This is the second window.\u003c/p>", {
        "width": 250,
        "height": 180,
        "top": 180,
        "left": 55,
        "closable": true
      });
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget2 = document.querySelector("#sample");
  document.querySelector('#action-2').addEventListener('click', async () => {
    const result = await actionTarget2.updateTitle("note-a", "Updated note");
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget3 = document.querySelector("#sample");
  document.querySelector('#action-3').addEventListener('click', async () => {
    const result = await actionTarget3.closeAll();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

Events and payloads

Interact with the component and inspect the latest event name and detail. The code includes subscriptions to events emitted by this component and its children.

View code
HTML
<sy-modeless
  closable
  draggable="true"
  width="280"
  height="220"
  top="80"
  left="12"
  resizable
  minimizable
  maximizable
  animation="none"
  id="sample"
><span slot="title">Task notes</span>
  <div slot="content">
    <p>Keep this window open while using other views.</p>
    <sy-input placeholder="Enter a note" aria-label="Task notes"></sy-input>
  </div>
</sy-modeless>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Open work window</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>
<output id="demo-events" aria-live="polite">Interact with the component to see
  its latest event and payload.</output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  for (const name of ["closed", "statusChanged", "positionChanged"]) {
    document.addEventListener(name, event => {
      document.querySelector('#demo-events').textContent =
        `${event.target.localName} · ${name}: ${describeResult(event.detail)}`;
    });
  }
</script>

Minimum size and transition speed

Limit resizing with minWidth and minHeight. Open the window and drag a corner to test its minimum size.

View code
HTML
<sy-modeless
  closable
  draggable="true"
  width="280"
  height="220"
  top="80"
  left="12"
  resizable
  minimizable
  maximizable
  animation="fade"
  minwidth="240"
  minheight="180"
  animation-speed="fast"
  id="sample"
><span slot="title">Task notes</span>
  <div slot="content">
    <p>Keep this window open while using other views.</p>
    <sy-input placeholder="Enter a note" aria-label="Task notes"></sy-input>
  </div>
</sy-modeless>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Open work window</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const component1 = document.querySelector("#sample");
  Object.assign(component1, {
    "minWidth": 240,
    "minHeight": 180,
    "animation": "fade",
    "animationSpeed": "fast",
    "resizable": true
  });
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

Supporting information beside the title

The header slot provides space to the right of the title. Set open to show the window initially. Use maximum, minimum, or their corresponding methods to change its state.

View code
HTML
<sy-modeless
  closable
  draggable="true"
  width="280"
  height="220"
  top="80"
  left="12"
  resizable
  minimizable
  maximizable
  animation="none"
  open
  id="sample"
><span slot="title">Task notes</span>
  <div slot="content">
    <p>Keep this window open while using other views.</p>
    <sy-input placeholder="Enter a note" aria-label="Task notes"></sy-input>
  </div><span slot="header">Saved</span>
</sy-modeless>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Open work window</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const component1 = document.querySelector("#sample");
  Object.assign(component1, {
    "open": true,
    "maximum": false,
    "minimum": false
  });
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

Fixed window

Open a window with dragging and resizing disabled.

View code
HTML
<sy-modeless
  closable
  width="280"
  height="220"
  top="80"
  left="12"
  minimizable
  maximizable
  animation="none"
  id="sample"
><span slot="title">Task notes</span>
  <div slot="content">
    <p>Keep this window open while using other views.</p>
    <sy-input placeholder="Enter a note" aria-label="Task notes"></sy-input>
  </div>
</sy-modeless>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Open work window</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const component1 = document.querySelector("#sample");
  Object.assign(component1, {
    "isDraggable": false,
    "resizable": false
  });
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.setOpen();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
</script>

API reference

#

Hover over a name or focus it with the keyboard to see the code. On touch screens, tap the name.

<sy-modeless>

Properties

Attribute / PropertyTypeDefaultDescription
booleanfalseWhether the submenu is expanded.
| 'none' | 'fade' | 'fade-scale' | 'zoom' | 'pop' | 'slide-top' | 'slide-bottom' | 'slide-left' | 'slide-right' | 'slide-fade-top' | 'slide-fade-bottom' | 'slide-fade-left' | 'slide-fade-right' | 'reveal-top' | 'reveal-bottom' | 'reveal-left' | 'reveal-right' | 'flip-x' | 'flip-y' | 'bounce' | 'spin''none'Enter/exit animation type. `none` (default) toggles instantly.
'x-fast' | 'fast' | 'medium' | 'slow' | 'x-slow''fast'Animation playback speed token. Maps to `--transition-*` global tokens.
booleanfalseAllow the window to be moved by dragging its title.
booleanfalseAllow resizing from the window edges.
booleanfalseShow the close button.
booleanfalseShow the minimize button.
booleanfalseShow the maximize button.
booleanfalseApply window border styling.
booleanfalseMaximized state.
booleanfalseMinimized state.
number | undefinedundefinedPosition from the top of the screen, in pixels.
number | undefinedundefinedPosition from the left of the screen, in pixels.
number200Window width in pixels.
number150Window height in pixels.
unknownDEFAULT_MIN_WIDTHMinimum window width in pixels.
unknownDEFAULT_MIN_HEIGHTMinimum window height in pixels.

Events

EventDetailDescription
CustomEvent<{ id: string }>Read the result from the event's detail.
CustomEvent<{ id: string; status: string }>Read the result from the event's detail.
CustomEvent<ModelessPositionChangedDetail>Read the result from the event's detail.

Methods

MethodReturnsDescription
Promise<void>Expand the submenu.
Promise<void>Close the item.
Promise<void>Maximize the window.
Promise<void>Restore the window to its original size.
Promise<void>Minimize the window.

Slots

SlotDescription
Content displayed in the title area.
Content displayed in the header area.
Content displayed in the content area.

<sy-modeless-group>

Methods

MethodReturnsDescription
Promise<void>Create a new Modeless window with a unique id.
Promise<void>Change the content of the window with the specified id.
Promise<void>Change the title of the window with the specified id.
Promise<void>Change settings such as position and size for the window with the specified id.
Promise<void>Close the open panel.
Promise<void>Collapse all panels.

Slots

SlotDescription
Component body or child items.