GeoLeaf Core API - v3.0.0
    Preparing search index...

    UI integration slot declared by a module.

    A module may optionally declare:

    • a mobile toolbar icon rendered in the bottom pill
    • a desktop filter tab rendered in the right-hand filter panel

    Both are opt-in. A module that declares neither simply has no UI presence (e.g. a data connector module).

    const ui: IModuleUISlot = {
    mobileIcon: {
    icon: '<svg …>…</svg>',
    labelKey: 'aria.toolbar.legend',
    profileKey: 'modules.legend.enabled',
    },
    filterTab: {
    labelKey: 'legend.filterTab',
    order: 10,
    render() { return buildLegendPanel(); },
    },
    };
    interface IModuleUISlot {
        mobileIcon?: {
            icon: string;
            labelKey: string;
            profileKey: string;
            defaultVisible?: boolean;
            requiresPlugin?: string;
            action?: string;
            order?: number;
        };
        desktopTabButton?: {
            icon: string;
            labelKey: string;
            profileKey?: string;
            defaultVisible?: boolean;
            requiresPlugin?: string;
            action?: string;
            variant?: "icon"
            | "tab";
        };
        filterTab?: { labelKey: string; order?: number; render(): HTMLElement };
    }
    Index

    Properties

    mobileIcon?: {
        icon: string;
        labelKey: string;
        profileKey: string;
        defaultVisible?: boolean;
        requiresPlugin?: string;
        action?: string;
        order?: number;
    }

    Mobile toolbar (bottom pill) integration.

    When declared, the registry renders a button in the mobile pill using the provided icon and label. The button is hidden when the profile key evaluates to false.

    Type Declaration

    • icon: string

      SVG icon markup rendered inside the pill button.

      This field must be a static, hardcoded SVG string written by the module developer. Never assign content that originates from user input, network responses, URL parameters, or profile data — SVG markup can carry executable payloads (XSS via inline event handlers, <script> elements, or href="javascript:").

      `'<svg viewBox="0 0 24 24"><path d="…"/></svg>'`
      
    • labelKey: string

      i18n key resolved at render time to produce the button's accessible label.

      `'search.buttonLabel'`
      
    • profileKey: string

      Dot-notation profile configuration key that controls visibility. When config.get(profileKey) evaluates to false, the icon is hidden.

      `'modules.legend.enabled'`
      
    • OptionaldefaultVisible?: boolean

      Whether the icon is visible when profileKey is absent from the profile.

      true
      
    • OptionalrequiresPlugin?: string

      Optional plugin identifier that must be loaded for this icon to appear. When set, GeoLeaf.plugins.isLoaded(requiresPlugin) must return true. Use for toolbar buttons backed by external plugins (not core built-ins).

      `'print'`
      
    • Optionalaction?: string

      Optional toolbar action identifier mapped to data-gl-toolbar-action. When set, the click handler dispatches the named action (e.g. "search") instead of opening a sheet modal. Also enables action-specific CSS rules.

      `'search'`
      
    • Optionalorder?: number

      Render order in the mobile pill. Lower values appear first.

      Same semantics as IModuleUISlot.filterTab.order — this field aligns the two halves of the same interface, which declared an explicit order on one side and relied on an implicit one on the other.

      ⚠️ Without it, pills render in module registration order, which is an emergent property of the manifest: presets/manifest.full.ts orders its installers for load-bearing reasons of its own (see that file's header — it is the registry), and the toolbar layout was one more meaning silently riding on the same list. Reordering the manifest for any of the others moved the buttons.

      ⚠️ This sentence carried a count and a list until 08/08/2026 — « three unrelated load-bearing reasons (topo-sort tie-breaks, sharedLifecycle sequencing, dependency edges) » — and BOTH were wrong. sharedLifecycle sequencing was refuted by socle-init 7.4 (__tests__/presets/shared-lifecycle-order.test.ts), and « dependency edges » was never one of the manifest's stated reasons at all — it was invented here, and copied from here into scripts/gen-entry.cjs. B-43: the count is gone rather than corrected, because a second copy of a list can only drift from the list.

      Modules that omit it keep the previous behaviour: they render after every ordered one, in registration order.

      undefinedrender after all ordered icons, in registration order
      
      `10`
      
    desktopTabButton?: {
        icon: string;
        labelKey: string;
        profileKey?: string;
        defaultVisible?: boolean;
        requiresPlugin?: string;
        action?: string;
        variant?: "icon" | "tab";
    }

    Desktop tab-strip button integration.

    When declared, the registry renders an icon button in the right-hand desktop tab strip (.gl-rp-tabs), inserted above the share button. On mobile the button is hidden — only mobileIcon is shown on small screens.

    Shares the same guard semantics as mobileIcon: profileKey controls config-driven visibility, requiresPlugin gates on plugin presence.

    Type Declaration

    • icon: string

      SVG icon markup. Same security constraints as mobileIcon.icon: must be a static, hardcoded string — never user-supplied content.

    • labelKey: string

      i18n key resolved at render time for the button's accessible label.

    • OptionalprofileKey?: string

      Dot-notation profile key controlling visibility. When config.get(profileKey) evaluates to false, the button is hidden.

    • OptionaldefaultVisible?: boolean

      Whether the button is visible when profileKey is absent.

      true
      
    • OptionalrequiresPlugin?: string

      Plugin identifier that must be loaded for this button to appear. Same semantics as mobileIcon.requiresPlugin.

    • Optionalaction?: string

      Toolbar action dispatched on click via geoleaf:toolbar:action.

    • Optionalvariant?: "icon" | "tab"

      Visual rendering in the desktop tab strip.

      • "icon" (default): a 28×28 icon button in the bottom stack (.gl-rp-tab-btn), using icon.
      • "tab": a vertical-text tab matching the built-in Filtrer/Couches/Légende tabs (.gl-rp-tab), showing labelKey as text (the icon is ignored). Use when the slot replaces a former core tab (e.g. the extracted Table).
    filterTab?: { labelKey: string; order?: number; render(): HTMLElement }

    Desktop filter panel tab integration.

    When declared, the registry renders a tab in the right-hand filter panel. Tabs are sorted by order (ascending) before rendering.

    render is required — it may not be omitted when filterTab is declared. TypeScript enforces this at compile time. The registry calls render() exactly once (lazy, returned element is cached), which guarantees performance and enables straightforward unit testing: const el = module.ui.filterTab.render().

    Type Declaration

    • labelKey: string

      i18n key resolved at render time to produce the tab title.

      `'search.filterTabLabel'`
      
    • Optionalorder?: number

      Insertion order relative to other filter tabs. Lower values appear first.

      0
      
    • render: function
      • Renders and returns the tab content as an HTMLElement.

        Called exactly once by the registry (returned element is cached). The module is responsible for the full lifecycle of the returned DOM — destroy() must clean up anything created here.

        Returns HTMLElement

        The root element of the tab content.