Hocusable

A specialized Triggerable where the control is triggered on hover or focus. Useful for Tooltips and controls of this type.


Simple Example: Tooltip

For a simple tooltip, we want the target to open on hover and focus, to close when pressing ESC and to stay open when hovering its content. This is precisely the functionality the Hocusable class brings in.

We only have to extend it by adding a few roles and attributes:


<script lang="ts">
  import { Hocusable } from "chocobytes/blocks/hocusable.svelte.js";
  import { choco } from "chocobytes/index.js";
  import { nanoId } from "chocobytes/utils/index.js";
  import { role } from "chocobytes/utils/roles.js";

  export class Tooltip extends Hocusable<"generic"> {
    constructor(options?: { active: boolean }) {
      const active = options?.active ?? false;

      super({
        active,
        // We only toggle a `data-open` attribute on the target
        target: { "data-open": active },
      });

      const id = "tooltip-" + nanoId();

      // And extend the attributes for accessibility
      this.extendAttributes({
        "aria-describedby": id,
      });

      this.target.extendAttributes({
        id,
        inert: true,
        role: role.tooltip,
      });
    }
  }

  const tooltip = new Tooltip();
</script>

<button>A</button>
<div class="grid">
  <div class="relative mx-auto">
    <span use:choco={tooltip}>HTML*</span>
    <!-- `data-open` toggles the display -->
    <p
      class="invisible absolute top-2 left-1/2 -translate-x-1/2 whitespace-nowrap rounded bg-black px-1 text-xs leading-none data-[open=true]:visible"
      use:choco={tooltip.target}
    >
      Hypertext Markup Language
    </p>
  </div>
</div>
<button>B</button>

<!-- Just to see what's going on -->
<div class="mt-10 grid">
  <p>Control attributes</p>
  <pre>{JSON.stringify(tooltip.attributes, null, 2)}</pre>
  <p>Target attributes</p>
  <pre>{JSON.stringify(tooltip.target.attributes, null, 2)}</pre>
</div>

Try focusing with the keyboard, pressing ESC, hovering over the tooltip etc. In only a few lines of code, the Hocusable building block allowed us to setup a full-featured simple tooltip.

API

Constructor

A Hocusable is just a specialized Triggerable, so the constructor options are the same:

TriggerableOptions
control?: Record<string, Booleanish>
Initial booleanish state of the control
target?: Record<string, Booleanish>
Initial booleanish state of the target
active: boolean | () => boolean
Boolean or getter labelling the state as active or not. Can be bound
Default: false
setActive?: (v: boolean) => void
Setter allowing to bind the active state value
toggle?: EventName | EventName[]
Event(s) toggling the state
on?: EventName | EventName[]
Event(s) triggering the active state
off?: EventName | EventName[]
Event(s) triggering the inactive state