Skip to content

Layer List

Turns layers on and off, with a menu on each row for zoom, labels, transparency, filters and export. Layers appear in their layers.json order, grouped by their group field. The same order sets which layer draws on top (see Adding Layers).

  • id: layer-list
  • Surfaces: side-panel

Place it

"sidePanelWidgets": [{ "widgetName": "layer-list" }]

Behavior

  • Each layer has an eye (or checkbox) toggle. With rowClickToggle on, the default, clicking anywhere on the row toggles the layer. While a layer's data is still on its way, a small spinner takes the eye's place: on the first toggle of a layer deferred by map.onlyVisibleOnLoad, and while DuckDB layers refill after a basemap switch.
  • The ⋮ button on each row opens the layer's menu:
    • Zoom to Extent fits the map to the layer's data, or to the filtered features if a filter is on. Esri raster services read their extent from the service. Extents in Web Mercator are converted to degrees; when the service gives no extent, or one in another projection, the item does nothing.
    • Labels turns the layer's labels on and off. Only on layers with a label config.
    • Adjust Transparency opens an opacity slider under the row; ✕ closes it. It starts at 100% and fades the whole layer (fill and outline together) on top of the opacity set in its symbology.
    • Filter opens the filter panel. Only on layers with filters.
    • Export Data asks which format to download (see Exporting data). Only on geojson and geoparquet layers; a GeoParquet layer with a limit exports only the rows it loaded.
  • Layers with the same group sit under a header with its own toggle, which shows a half state when only some of them are on. Click the header to expand or collapse the group. An open group's layers sit on a faintly tinted band with a guide line, their toggles lined up under the header's.
  • A PMTiles layer that draws several source layers looks like any other row, plus a chevron. It starts collapsed (set "collapsed": false on the layer to start it open). Expanded, its source layers appear one step further in, in draw order, on the same tinted band, each with its own toggle and menu (Zoom to Extent, Labels, Adjust Transparency). The parent's toggle works like a group header's, with a half state when only some are on, and its menu has Zoom to Extent (the whole archive) and Adjust Transparency (sets every source layer at once). These rows can sit inside a group.
  • A layer's name turns gray when the map's zoom is outside its minZoom/maxZoom range.

Visibility, opacity, labels and filters all carry over when the basemap changes.

Exporting data

Export Data opens a pop-up with the formats in ui.layerList.exportFormats (all four by default). Every format contains the layer's features with all their properties; if a filter is on, only the features that pass it, and the pop-up says so. The file is named after the layer.

Format What you get
GeoJSON Geometry and every property, no styling
KML Opens in Google Earth. Keeps the layer's colors for simple symbology (see below), every property under each placemark
GeoParquet Compact, typed columns (whole numbers, decimals, true/false, text) and GeoParquet 1.1 metadata, so QGIS, GeoPandas and DuckDB read it as GeoParquet. The geometry column is geometry, so a property with that name is written as geometry_attr, and whole numbers too large for a 64-bit integer are written as decimals. Written in the browser, loaded the first time it's used
CSV A table for spreadsheets: every property as a column, plus longitude / latitude for points and a wkt column for lines and polygons. A property already named one of those is renamed (longitude_1, …), so no column name repeats. Opens correctly in Excel, accents included

With one format in exportFormats, Export Data downloads it directly instead of asking.

KML styling only covers simple symbology

A layer with simple symbology exports its line color, width and opacity, polygon fill and border, and point color and size. Categorized or graduated layers (raw symbology) export with the viewer's default styling, since that would need a separate style per feature. This is a deliberate limit; if you need it, app/src/core/writeKML.ts (featuresToKML) is the place to add a style per category.

Filtering

Filter swaps the list for that layer's filter panel; the back arrow returns to the list. The panel has one filter for each column in the layer's filters.

  • Toggles. "Filter this layer" turns the whole layer's filtering on and off, and each column has its own toggle. The layer toggle turns on the first time you open the panel; column toggles start off. Turning a toggle off pauses that filter but keeps its values.
  • Categorical columns show a checklist of the column's values, all unchecked at first. Check the values to show; with nothing checked, the column doesn't filter. Checked values move to the top, lists of more than 10 values get a search box, and Clear unchecks everything.
  • Numeric columns take one condition: >, ≥, <, ≤, =, ≠ or between (inclusive). It applies on Enter, when the box loses focus, or after a short pause in typing. Invalid input, like text or a minimum above the maximum, gets a red outline and is ignored.

Filters on different columns combine with AND, and every change applies right away. While a filter is on, a funnel icon appears next to the row's ⋮ button; click it to go back to the panel.

A filter also limits Zoom to Extent, Export Data, layer search and popups, since only visible features can be clicked. The legend doesn't change. Filters reset when the page reloads.

Configuration

Defaults come from ui.layerList:

ui: {
  layerList: {
    groupsCollapsedByDefault: true,
    toggleStyle: 'eye',
    actions: { opacity: true, labels: true, zoomToExtent: true, filter: true, export: true },
    rowClickToggle: true,
    exportFormats: ['geojson', 'kml', 'geoparquet', 'csv'],
  },
},

Set collapse per group with the top-level layerGroups block, and override menu items per layer with the layer's actions field. A layer's setting wins over the global one. The Draw widget's "Drawings" row, for example, sets "actions": { "opacity": false }, so it only offers Zoom to Extent.