<svelte:options
  customElement={{
    // `shadowRoot` field must remain as the default, else named slots break.
    props: {
      button_aria_label: { attribute: "button-aria-label" },
      alignment: { attribute: "alignment" },
    },
    tag: "basic-dropdown",
  }}
/>

<!--
@component

A button with an associated popover, which can be styled for a variety of
purposes, such as menus, confirmation popups, and so on.

When used as a web component, this component is rendered with a shadow root in
order to correctly support named slots. As a result, it bundles its own
stylesheet, which is merely a copy of the "main" application stylesheet.

## Props

- `alignment`: When set to "right", the popover aligns with the right edge of
  the trigger. Otherwise, it aligns with the left.
-->

<script lang="ts">
  type Props = {
    alignment?: string;
    button_aria_label?: string;
    on_toggle?(ev: ToggleEvent): unknown;
  };

  let { alignment, button_aria_label, on_toggle }: Props = $props();

  let popover_element: HTMLElement | undefined = $state();
  // Hacky workaround because as of September 2025 implicit anchor association
  // is still pretty broken, at least in Firefox.
  let anchor_name = $state(`--anchor-${Math.floor(Math.random() * 1000000)}`);

  let popover_left = $derived(
    alignment?.toLocaleLowerCase("en-US") === "right"
      ? "unset"
      : "anchor(left)",
  );
  let popover_right = $derived(
    alignment?.toLocaleLowerCase("en-US") === "right"
      ? "anchor(right)"
      : "unset",
  );

  $effect(() => {
    if (on_toggle) {
      popover_element?.addEventListener("toggle", on_toggle);
      return () => {
        popover_element?.removeEventListener("toggle", on_toggle);
      };
    }
  });
</script>

<button
  aria-label={button_aria_label}
  class="basic-dropdown__button"
  id="dropdown-button"
  onclick={() => {
    popover_element?.showPopover();
  }}
  style:anchor-name={anchor_name}
  type="button"
>
  <slot name="button-contents"></slot>
</button>
<div
  aria-labelledby="dropdown-button"
  bind:this={popover_element}
  class="basic-dropdown__popover"
  style:left={popover_left}
  style:position-anchor={anchor_name}
  style:right={popover_right}
  popover="auto"
>
  <slot name="popover"></slot>
</div>

<style lang="css">
  .basic-dropdown__button {
    appearance: none;
    box-sizing: border-box;
    cursor: pointer;
    font-weight: inherit;

    background: var(--button-background);
    border: solid 1px var(--button-border-color);
    border-radius: var(--button-border-radius);
    box-shadow: var(--button-shadow);
    color: var(--button-color);
    font-family: var(--button-font-family);
    font-size: var(--button-font-size);
    padding: var(--button-padding);
    text-decoration: none;
    transition: background 0.2s ease;

    &:hover {
      border-color: oklch(from var(--button-border-color) calc(l * 0.95) c h);
      background: oklch(from var(--button-background) calc(l * 0.95) c h);
    }
  }

  .basic-dropdown__popover:popover-open {
    background: #fff;
    border: solid 1px var(--popover-border-color);
    border-radius: var(--default-border-radius--rounded);
    box-shadow: var(--popover-shadow);
    display: block;
    margin: unset;
    max-height: 90vh;
    overflow: auto;
    padding: 0;
    position: absolute;
    top: anchor(bottom);
  }
</style>
