arcgis-widgets-ui

ArcGIS Widgets & UI

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "arcgis-widgets-ui" with this command: npx skills add saschabrunnerch/arcgis-maps-sdk-js-ai-context/saschabrunnerch-arcgis-maps-sdk-js-ai-context-arcgis-widgets-ui

ArcGIS Widgets & UI

Use this skill when building user interfaces with widgets, Map Components, and Calcite.

Best Practice: Prefer Map Components (web components like arcgis-legend , arcgis-search ) over Core API widgets when possible. Esri is transitioning to web components, and some widgets are already deprecated. See Esri's component transition plan.

Map Components Approach

Available Map Components

Component Purpose

arcgis-map

2D map container

arcgis-scene

3D scene container

arcgis-zoom

Zoom in/out buttons

arcgis-compass

Orientation indicator

arcgis-home

Return to initial extent

arcgis-locate

Find user location

arcgis-track

Track user location

arcgis-navigation-toggle

Pan/rotate mode (3D)

arcgis-floor-filter

Filter indoor map by floor level

arcgis-fullscreen

Toggle fullscreen

arcgis-grid-controls

Grid controls for feature tables

arcgis-scale-bar

Display map scale

arcgis-scale-range-slider

Set visible scale range for layers

arcgis-legend

Layer symbology legend

arcgis-layer-list

Layer visibility control

arcgis-basemap-gallery

Switch basemaps

arcgis-basemap-layer-list

Layer list for basemap layers

arcgis-basemap-toggle

Toggle two basemaps

arcgis-catalog-layer-list

Browse and toggle CatalogLayer sublayers

arcgis-search

Location search

arcgis-placement

Control widget placement on the view

arcgis-popup

Feature popups

arcgis-editor

Feature editing

arcgis-feature

Display feature information without a popup

arcgis-feature-form

Form-based attribute editing

arcgis-features

Display multiple features information

arcgis-sketch

Draw geometries

arcgis-feature-table

Tabular data view

arcgis-time-slider

Temporal navigation

arcgis-time-zone-label

Display time zone

arcgis-expand

Collapsible container

arcgis-print

Map printing

arcgis-table-list

List and manage feature tables

arcgis-bookmarks

Navigate to bookmarks

arcgis-directions

Turn-by-turn routing

arcgis-swipe

Compare layers

arcgis-coordinate-conversion

Coordinate formats

arcgis-daylight

3D lighting control

arcgis-weather

3D weather effects

arcgis-distance-measurement-2d

2D distance measurement

arcgis-area-measurement-2d

2D area measurement

arcgis-direct-line-measurement-3d

3D line measurement

arcgis-area-measurement-3d

3D area measurement

arcgis-directional-pad

Directional pad for camera navigation

arcgis-elevation-profile

Elevation profile along a path

arcgis-line-of-sight

Line of sight analysis (3D)

arcgis-slice

Slice through 3D data

arcgis-shadow-cast

Shadow cast analysis (3D)

arcgis-oriented-imagery-viewer

View oriented imagery

arcgis-video-player

Play video feeds from video layers

arcgis-link-chart

Link chart visualization

arcgis-link-chart-layout-switcher

Switch link chart layouts

arcgis-version-management

Manage geodatabase versions

arcgis-utility-network-trace

Utility network tracing

arcgis-utility-network-associations

Utility associations

arcgis-utility-network-validate-topology

Validate utility network topology

Note: Not all widgets have component equivalents yet. Histogram and some specialized widgets only have Core API versions. FeatureForm has the arcgis-feature-form component.

Slot-Based Positioning

<arcgis-map basemap="streets-vector"> <!-- Position widgets using slots --> <arcgis-zoom slot="top-left"></arcgis-zoom> <arcgis-home slot="top-left"></arcgis-home> <arcgis-compass slot="top-left"></arcgis-compass>

<arcgis-search slot="top-right"></arcgis-search> <arcgis-layer-list slot="top-right"></arcgis-layer-list>

<arcgis-legend slot="bottom-left"></arcgis-legend> <arcgis-scale-bar slot="bottom-right"></arcgis-scale-bar>

<!-- Popup must use popup slot --> <arcgis-popup slot="popup"></arcgis-popup> </arcgis-map>

Available slots: top-left , top-right , bottom-left , bottom-right , top-start , top-end , bottom-start , bottom-end , popup

Expand Component

Wrap widgets in arcgis-expand for collapsible behavior:

<arcgis-map basemap="streets-vector"> <arcgis-expand slot="top-right" expand-tooltip="Show Legend" mode="floating"> <arcgis-legend></arcgis-legend> </arcgis-expand>

<arcgis-expand slot="top-left" expanded> <arcgis-layer-list></arcgis-layer-list> </arcgis-expand> </arcgis-map>

Reference Element (External Components)

Place components outside the map and reference them:

<calcite-shell> <calcite-shell-panel slot="panel-start"> <arcgis-legend reference-element="arcgis-map"></arcgis-legend> </calcite-shell-panel>

<arcgis-map id="arcgis-map" basemap="topo-vector"> <arcgis-zoom slot="top-left"></arcgis-zoom> </arcgis-map> </calcite-shell>

Core Widget Approach

Adding Widgets to View

import Legend from "@arcgis/core/widgets/Legend.js"; import LayerList from "@arcgis/core/widgets/LayerList.js"; import Search from "@arcgis/core/widgets/Search.js";

// Create widget const legend = new Legend({ view: view });

// Add to view UI view.ui.add(legend, "bottom-left");

// Add multiple widgets view.ui.add([ { component: legend, position: "bottom-left" }, { component: search, position: "top-right" } ]);

// Add to specific index (order in position) view.ui.add(legend, { position: "bottom-left", index: 0 });

// Remove widget view.ui.remove(legend);

Widget in Custom Container

<div id="legendDiv"></div>

<script type="module"> import Legend from "@arcgis/core/widgets/Legend.js";

const legend = new Legend({ view: view, container: "legendDiv" // Or document.getElementById("legendDiv") }); </script>

Common Widgets

Legend

<!-- Map Component --> <arcgis-legend slot="bottom-left"></arcgis-legend>

// Core API import Legend from "@arcgis/core/widgets/Legend.js";

const legend = new Legend({ view: view, layerInfos: [{ layer: featureLayer, title: "Custom Title" }] });

view.ui.add(legend, "bottom-left");

LayerList

<!-- Map Component --> <arcgis-layer-list slot="top-right"></arcgis-layer-list>

// Core API with actions import LayerList from "@arcgis/core/widgets/LayerList.js";

const layerList = new LayerList({ view: view, listItemCreatedFunction: (event) => { const item = event.item; item.actionsSections = [[{ title: "Zoom to layer", icon: "zoom-to-object", id: "zoom-to" }]]; } });

layerList.on("trigger-action", (event) => { if (event.action.id === "zoom-to") { view.goTo(event.item.layer.fullExtent); } });

view.ui.add(layerList, "top-right");

BasemapGallery

<!-- Map Component --> <arcgis-basemap-gallery slot="top-right"></arcgis-basemap-gallery>

// Core API import BasemapGallery from "@arcgis/core/widgets/BasemapGallery.js";

const basemapGallery = new BasemapGallery({ view: view });

view.ui.add(basemapGallery, "top-right");

Search

<!-- Map Component --> <arcgis-search slot="top-right"></arcgis-search>

// Core API with custom sources import Search from "@arcgis/core/widgets/Search.js";

const search = new Search({ view: view, sources: [{ layer: featureLayer, searchFields: ["name", "address"], displayField: "name", exactMatch: false, outFields: ["*"], name: "My Layer", placeholder: "Search features" }] });

view.ui.add(search, "top-right");

// Events search.on("select-result", (event) => { console.log("Selected:", event.result); });

FeatureTable

<!-- Map Component --> <arcgis-feature-table reference-element="arcgis-map"></arcgis-feature-table>

// Core API import FeatureTable from "@arcgis/core/widgets/FeatureTable.js";

const featureTable = new FeatureTable({ view: view, layer: featureLayer, container: "tableDiv", visibleElements: { header: true, columnMenus: true, selectionColumn: true }, tableTemplate: { columnTemplates: [ { fieldName: "name", label: "Name" }, { fieldName: "population", label: "Population" } ] } });

// Watch selection via highlightIds featureTable.highlightIds.on("change", (event) => { console.log("Selected IDs:", featureTable.highlightIds.toArray()); });

TimeSlider

<!-- Map Component --> <arcgis-time-slider slot="bottom-right" layout="auto" mode="time-window" time-visible loop> </arcgis-time-slider>

<script type="module"> const timeSlider = document.querySelector("arcgis-time-slider"); await layer.load();

timeSlider.fullTimeExtent = layer.timeInfo.fullTimeExtent; timeSlider.stops = { interval: layer.timeInfo.interval }; </script>

// Core API import TimeSlider from "@arcgis/core/widgets/TimeSlider.js";

const timeSlider = new TimeSlider({ view: view, mode: "time-window", // instant, time-window, cumulative-from-start, cumulative-from-end fullTimeExtent: layer.timeInfo.fullTimeExtent, stops: { interval: { value: 1, unit: "hours" } }, playRate: 1000, // ms between stops loop: true });

view.ui.add(timeSlider, "bottom-right");

// Events timeSlider.watch("timeExtent", (timeExtent) => { console.log("Time changed:", timeExtent.start, timeExtent.end); });

Print

<!-- Map Component --> <arcgis-print slot="top-right"></arcgis-print>

// Core API import Print from "@arcgis/core/widgets/Print.js";

const print = new Print({ view: view, printServiceUrl: "https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task" });

view.ui.add(print, "top-right");

Calcite Design System Integration

Basic Layout with Calcite

<!DOCTYPE html> <html> <head> <script type="module" src="https://js.arcgis.com/calcite-components/3.3.3/calcite.esm.js">&#x3C;/script> <script src="https://js.arcgis.com/4.34/">&#x3C;/script> <script type="module" src="https://js.arcgis.com/4.34/map-components/">&#x3C;/script> <style> html, body { height: 100%; margin: 0; } </style> </head> <body class="calcite-mode-light"> <calcite-shell> <!-- Header --> <calcite-navigation slot="header"> <calcite-navigation-logo slot="logo" heading="My Map App"></calcite-navigation-logo> </calcite-navigation>

&#x3C;!-- Side Panel -->
&#x3C;calcite-shell-panel slot="panel-start">
  &#x3C;calcite-panel heading="Layers">
    &#x3C;arcgis-layer-list reference-element="map">&#x3C;/arcgis-layer-list>
  &#x3C;/calcite-panel>
&#x3C;/calcite-shell-panel>

&#x3C;!-- Map -->
&#x3C;arcgis-map id="map" basemap="streets-vector">
  &#x3C;arcgis-zoom slot="top-left">&#x3C;/arcgis-zoom>
&#x3C;/arcgis-map>

&#x3C;!-- End Panel -->
&#x3C;calcite-shell-panel slot="panel-end">
  &#x3C;calcite-panel heading="Legend">
    &#x3C;arcgis-legend reference-element="map">&#x3C;/arcgis-legend>
  &#x3C;/calcite-panel>
&#x3C;/calcite-shell-panel>

</calcite-shell> </body> </html>

Calcite Action Bar

<calcite-shell> <calcite-shell-panel slot="panel-start"> <calcite-action-bar slot="action-bar"> <calcite-action icon="layers" text="Layers" data-panel="layers"></calcite-action> <calcite-action icon="legend" text="Legend" data-panel="legend"></calcite-action> <calcite-action icon="bookmark" text="Bookmarks" data-panel="bookmarks"></calcite-action> </calcite-action-bar>

&#x3C;calcite-panel id="layers" heading="Layers">
  &#x3C;arcgis-layer-list reference-element="map">&#x3C;/arcgis-layer-list>
&#x3C;/calcite-panel>

&#x3C;calcite-panel id="legend" heading="Legend" hidden>
  &#x3C;arcgis-legend reference-element="map">&#x3C;/arcgis-legend>
&#x3C;/calcite-panel>

</calcite-shell-panel>

<arcgis-map id="map" basemap="topo-vector"></arcgis-map> </calcite-shell>

<script> // Toggle panels on action click document.querySelectorAll("calcite-action").forEach(action => { action.addEventListener("click", () => { const panelId = action.dataset.panel; document.querySelectorAll("calcite-panel").forEach(panel => { panel.hidden = panel.id !== panelId; }); }); }); </script>

Common Calcite Components

Component Purpose

calcite-shell

App layout container

calcite-shell-panel

Side panels

calcite-panel

Content panel

calcite-navigation

Header/footer

calcite-action-bar

Icon button bar

calcite-action

Icon button

calcite-button

Standard button

calcite-input

Text input

calcite-list

List container

calcite-list-item

List item

calcite-card

Card container

calcite-modal

Modal dialog

calcite-alert

Alert message

calcite-loader

Loading indicator

Theming

<!-- Light mode --> <body class="calcite-mode-light">

<!-- Dark mode --> <body class="calcite-mode-dark">

<!-- Custom theme colors --> <style> :root { --calcite-color-brand: #007ac2; --calcite-color-brand-hover: #005a8e; --calcite-color-text-1: #323232; } </style>

Custom Widget Placement

Manual Positioning

// Add widget at specific position view.ui.add(widget, { position: "manual", index: 0 });

// Position with CSS document.getElementById("myWidget").style.cssText = position: absolute; top: 10px; left: 50%; transform: translateX(-50%);;

DOM Container

<div id="mapDiv" style="position: relative;"> <div id="customWidget" style="position: absolute; top: 10px; right: 10px; z-index: 1;"> <!-- Custom content --> </div> </div>

Widget Events

// Search select search.on("select-result", (event) => { console.log(event.result); });

// LayerList trigger action layerList.on("trigger-action", (event) => { console.log(event.action, event.item); });

// TimeSlider time change timeSlider.watch("timeExtent", (value) => { console.log(value.start, value.end); });

// FeatureTable selection featureTable.highlightIds.on("change", (event) => { console.log(event.added, event.removed); });

TypeScript Usage

Widget configurations use autocasting with type properties. For TypeScript safety, use as const :

// Use 'as const' for widget configurations const layerList = new LayerList({ view: view, listItemCreatedFunction: (event) => { const item = event.item; item.actionsSections = [[{ title: "Zoom to layer", icon: "zoom-to-object", id: "zoom-to" }]]; } });

// For layer configurations in widgets const featureTable = new FeatureTable({ view: view, layer: featureLayer, tableTemplate: { columnTemplates: [ { fieldName: "name", label: "Name" }, { fieldName: "population", label: "Population" } ] } });

Tip: See arcgis-core-maps skill for detailed guidance on autocasting vs explicit classes.

Reference Samples

  • legend

  • Legend widget for layer symbology

  • widgets-layerlist

  • LayerList widget for layer management

  • widgets-search-multiplesource

  • Search widget with multiple sources

  • widgets-featuretable

  • FeatureTable widget integration

  • basemap-gallery

  • BasemapGallery for switching basemaps

Common Pitfalls

Missing reference-element: Components placed outside the <arcgis-map> tag cannot find the view without an explicit reference.

<!-- Anti-pattern: component outside arcgis-map with no reference --> <arcgis-map id="myMap" basemap="topo-vector"></arcgis-map> <arcgis-search></arcgis-search> <!-- Cannot find the view, does not render -->

<!-- Correct: use reference-element to link to the map --> <arcgis-map id="myMap" basemap="topo-vector"></arcgis-map> <arcgis-search reference-element="myMap"></arcgis-search>

Impact: The component cannot discover the associated view. It either does not render at all, renders in a broken state, or throws an error about a missing view reference.

Slot names are specific: Use exact slot names (top-left , not topleft )

Calcite CSS not loading: Ensure Calcite script is loaded before using Calcite components

Widget container conflicts: Do not add the same widget to both a DOM container element and view.ui .

// Anti-pattern: widget added to both a container div AND view.ui const legend = new Legend({ view: view, container: "legendDiv" // Renders into the DOM element }); view.ui.add(legend, "bottom-right"); // Also adds to the view UI

// Correct: pick one placement strategy // Option A: Let view.ui manage placement const legend = new Legend({ view: view }); view.ui.add(legend, "bottom-right");

// Option B: Place in a specific DOM element const legend = new Legend({ view: view, container: "legendDiv" });

Impact: The widget renders twice on the page, or the layout breaks because the view UI and the container element compete for control of the widget's DOM node.

Dark/light mode mismatch: Add calcite-mode-light or calcite-mode-dark class to body

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

arcgis-popup-templates

No summary provided by upstream source.

Repository SourceNeeds Review
General

arcgis-geometry-operations

No summary provided by upstream source.

Repository SourceNeeds Review
General

arcgis-core-maps

No summary provided by upstream source.

Repository SourceNeeds Review
General

arcgis-authentication

No summary provided by upstream source.

Repository SourceNeeds Review