Atomic Angular — Doc interne

Floating panel

injectFloatingPanel keeps a popup — a combobox's list, a submenu — under or beside an anchor with Floating UI, as wide as the anchor on request and in the top layer above a dialog.

injectFloatingPanel() positions a panel against an anchor with Floating UI. It is what Select, Autocomplete, SubMenu and a combobox's popup in general need, and what each of them used to write by hand: wait for the panel and the anchor, follow them with autoUpdate, compute the position, write left and top, stop on destroy. For a panel opened by a button and light-dismissed, PopoverDirective is enough; reach for this one when the anchor is not the trigger, the panel is created later (a combobox renders its popup when it opens), or it must not close on an outside press.

Minimal example

A panel under a field, as wide as it
sample.component.ts
import { Component, ElementRef, signal, viewChild } from "@angular/core";
import { injectFloatingPanel } from "@sinequa/galactik";

@Component({
  selector: "sample-component",
  template: `
    <button #anchor type="button" (click)="open.set(!open())">Open</button>
    @if (open()) {
      <div #panel class="fixed z-50 rounded border bg-white p-3 shadow">Hung from the button.</div>
    }
  `,
})
export class SampleComponent {
  protected readonly open = signal(true);
  private readonly anchor = viewChild<ElementRef<HTMLElement>>("anchor");
  private readonly panel = viewChild<ElementRef<HTMLElement>>("panel");

  constructor() {
    injectFloatingPanel({
      panel: () => this.panel()?.nativeElement,
      anchor: () => this.anchor()?.nativeElement,
      matchAnchorWidth: true,
    });
  }
}

How it works

  • The panel must be position: fixed, as a class on it: it is then never in flow, not even on the frame it is created. Floating UI answers in viewport coordinates; without fixed they would be relative to the offset parent and the panel would drift by the page's scroll.
  • It is hidden until placed. The panel is visibility: hidden until its first position is computed, so it never paints for a frame in the corner of the page.
  • It may come and go. panel and anchor are signal reads: the panel is positioned each time it appears, and the autoUpdate of the previous one is stopped.
  • topLayer makes the panel a manual popover (popover="manual" and showPopover()): it goes above a <dialog> and outside the clipping of every ancestor, and is hidden again when it goes away. Without it, a modal dialog clips what overflows its own box.

Options

Prop

Type

Pitfalls

What's next

On this page