Skip to content

Commit e6c96ca

Browse files
feat(widgets): generic controls (#10090)
1 parent 4665ba5 commit e6c96ca

19 files changed

Lines changed: 609 additions & 306 deletions
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# IconWidget
2+
3+
<img src="https://img.shields.io/badge/from-v9.3-green.svg?style=flat-square" alt="from v9.3" />
4+
5+
This widget renders a single icon button. Use it for simple actions that should live alongside the other built-in deck.gl widgets.
6+
7+
## Usage
8+
9+
10+
```ts
11+
import {Deck} from '@deck.gl/core';
12+
import {IconWidget} from '@deck.gl/widgets';
13+
14+
new Deck({
15+
widgets: [
16+
new IconWidget({
17+
icon: `./action.svg`,
18+
label: 'Custom action',
19+
onClick: () => {
20+
// do something
21+
}
22+
})
23+
]
24+
});
25+
```
26+
27+
## Types
28+
29+
### `IconWidgetProps` {#iconwidgetprops}
30+
31+
The `IconWidget` accepts the generic [`WidgetProps`](../core/widget.md#widgetprops) and:
32+
33+
#### `icon` (string, required) {#icon}
34+
35+
Data URL used as the button icon mask.
36+
37+
#### `label` (string, optional) {#label}
38+
39+
Tooltip message displayed while hovering over the widget.
40+
41+
#### `color` (string, optional) {#color}
42+
43+
CSS color applied to the icon.
44+
45+
#### `onClick` (function, optional) {#onclick}
46+
47+
```ts
48+
() => void
49+
```
50+
51+
Callback invoked when the button is clicked.
52+
53+
## Styles
54+
55+
The `IconWidget` uses the shared button theme variables described in the [styling guide](./styling.md).
56+
57+
58+
## Source
59+
60+
[modules/widgets/src/icon-widget.tsx](https://github.com/visgl/deck.gl/tree/master/modules/widgets/src/icon-widget.tsx)

docs/api-reference/widgets/overview.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ This module contains the following widgets:
2020

2121
- [FullscreenWidget](./fullscreen-widget.md)
2222
- [SplitterWidget](./splitter-widget.md)
23-
- [ViewSelectorWidget](./view-selector-widget.md)
2423

2524
### Information Widgets
2625

@@ -29,6 +28,9 @@ This module contains the following widgets:
2928

3029
### Control Widgets
3130

31+
- [IconWidget](./icon-widget.md)
32+
- [ToggleWidget](./toggle-widget.md)
33+
- [SelectorWidget](./selector-widget.md)
3234
- [TimelineWidget](./timeline-widget.md)
3335

3436
### Utility Widgets
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# SelectorWidget
2+
3+
<img src="https://img.shields.io/badge/from-v9.3-green.svg?style=flat-square" alt="from v9.3" />
4+
5+
This widget renders an icon button that opens a popover menu of selectable options. Each option provides an icon and an optional label, and the button updates to reflect the current selection.
6+
7+
## Usage
8+
9+
```ts
10+
import {Deck} from '@deck.gl/core';
11+
import {SelectorWidget} from '@deck.gl/widgets';
12+
13+
new Deck({
14+
widgets: [
15+
new SelectorWidget({
16+
initialValue: 'single',
17+
options: [
18+
{
19+
value: 'single',
20+
label: 'Single view',
21+
icon: `./single-view.svg`
22+
},
23+
{
24+
value: 'split-horizontal',
25+
label: 'Split horizontal',
26+
icon: `./split-views-horizontal.svg`
27+
}
28+
],
29+
onChange: value => {
30+
console.log('selected:', value);
31+
}
32+
})
33+
]
34+
});
35+
```
36+
37+
## Types
38+
39+
### `SelectorWidgetProps` {#selectorwidgetprops}
40+
41+
The `SelectorWidget` accepts the generic [`WidgetProps`](../core/widget.md#widgetprops) and:
42+
43+
#### `options` (`SelectorWidgetOption[]`, required) {#options}
44+
45+
Selectable options displayed in the popover menu.
46+
47+
#### `initialValue` (any, optional) {#initialvalue}
48+
49+
* Default: value of the first option
50+
51+
Initial selected value. If it does not match any option, the first option is displayed.
52+
53+
#### `onChange` (function, optional) {#onchange}
54+
55+
```ts
56+
(value: ValueT) => void
57+
```
58+
59+
Callback invoked when a new option is selected.
60+
61+
### `SelectorWidgetOption` {#selectorwidgetoption}
62+
63+
#### `value` (any, required) {#value}
64+
65+
Value returned from `onChange` when this option is selected.
66+
67+
#### `icon` (string, required) {#optionicon}
68+
69+
Data URL used as the option icon mask.
70+
71+
#### `label` (string, optional) {#optionlabel}
72+
73+
Text shown in the menu and used as the button tooltip when selected.
74+
75+
## Styles
76+
77+
The `SelectorWidget` uses the shared button and menu theme variables described in the [styling guide](./styling.md).
78+
79+
80+
## Source
81+
82+
[modules/widgets/src/selector-widget.tsx](https://github.com/visgl/deck.gl/tree/master/modules/widgets/src/selector-widget.tsx)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# ToggleWidget
2+
3+
<img src="https://img.shields.io/badge/from-v9.3-green.svg?style=flat-square" alt="from v9.3" />
4+
5+
This widget renders an icon button with internal on/off state. It is useful for lightweight toggles such as layer visibility, mode switches, or filter controls.
6+
7+
## Usage
8+
9+
10+
```ts
11+
import {Deck} from '@deck.gl/core';
12+
import {ToggleWidget} from '@deck.gl/widgets';
13+
14+
new Deck({
15+
widgets: [
16+
new ToggleWidget({
17+
icon: `./play.png`,
18+
onIcon: `./pause.png`,
19+
label: 'Play',
20+
onLabel: 'Pause',
21+
onChange: checked => {
22+
// do something
23+
}
24+
})
25+
]
26+
});
27+
```
28+
29+
## Types
30+
31+
### `ToggleWidgetProps` {#togglewidgetprops}
32+
33+
The `ToggleWidget` accepts the generic [`WidgetProps`](../core/widget.md#widgetprops) and:
34+
35+
#### `initialChecked` (boolean, optional) {#initialchecked}
36+
37+
* Default: `false`
38+
39+
Whether the widget starts in the checked state.
40+
41+
#### `icon` (string, required) {#icon}
42+
43+
Data URL used as the default button icon mask.
44+
45+
#### `onIcon` (string, optional) {#onicon}
46+
47+
* Default: same as `icon`
48+
49+
Data URL used as the icon when the widget is checked.
50+
51+
#### `label` (string, optional) {#label}
52+
53+
Tooltip shown while the widget is unchecked.
54+
55+
#### `onLabel` (string, optional) {#onlabel}
56+
57+
* Default: same as `label`
58+
59+
Tooltip shown while the widget is checked.
60+
61+
#### `color` (string, optional) {#color}
62+
63+
CSS color applied while the widget is unchecked.
64+
65+
#### `onColor` (string, optional) {#oncolor}
66+
67+
* Default: same as `color`
68+
69+
CSS color applied while the widget is checked.
70+
71+
#### `onChange` (function, optional) {#onchange}
72+
73+
```ts
74+
(checked: boolean) => void
75+
```
76+
77+
Callback invoked after the widget toggles state.
78+
79+
## Styles
80+
81+
The `ToggleWidget` uses the shared button theme variables described in the [styling guide](./styling.md).
82+
83+
84+
## Source
85+
86+
[modules/widgets/src/toggle-widget.tsx](https://github.com/visgl/deck.gl/tree/master/modules/widgets/src/toggle-widget.tsx)

docs/api-reference/widgets/view-selector-widget.md

Lines changed: 0 additions & 62 deletions
This file was deleted.

docs/table-of-contents.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,16 +323,18 @@
323323
"api-reference/widgets/geocoder-widget",
324324
"api-reference/widgets/gimbal-widget",
325325
"api-reference/widgets/info-widget",
326+
"api-reference/widgets/icon-widget",
326327
"api-reference/widgets/loading-widget",
327328
"api-reference/widgets/popup-widget",
328329
"api-reference/widgets/reset-view-widget",
329330
"api-reference/widgets/scale-widget",
330331
"api-reference/widgets/screenshot-widget",
332+
"api-reference/widgets/selector-widget",
331333
"api-reference/widgets/splitter-widget",
332334
"api-reference/widgets/stats-widget",
333335
"api-reference/widgets/theme-widget",
334336
"api-reference/widgets/timeline-widget",
335-
"api-reference/widgets/view-selector-widget",
337+
"api-reference/widgets/toggle-widget",
336338
"api-reference/widgets/zoom-widget"
337339
]
338340
}

docs/whats-new.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Target release date: September, 2025
4848
- [StatsWidget](./api-reference/widgets/stats-widget.md)
4949
- [ThemeWidget](./api-reference/widgets/theme-widget.md)
5050
- [TimelineWidget](./api-reference/widgets/timeline-widget.md)
51-
- [ViewSelectorWidget](./api-reference/widgets/view-selector-widget.md)
51+
- ViewSelectorWidget
5252
- Pre-wrapped React components - deck.gl widgets are available via the [`@deck.gl/react`](./api-reference/react/overview.md) package
5353
- Custom widgets in pydeck - via the `custom_libraries` parameter, Python users can integrate custom deck.gl widgets seamlessly
5454
- Documentation for styling and custom themes - see [Styling Widgets](./api-reference/widgets/styling)

modules/react/src/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@ export {InfoWidget as _InfoWidget} from './widgets/info-widget';
1515
export {PopupWidget} from './widgets/popup-widget';
1616
export {ContextMenuWidget as _ContextMenuWidget} from './widgets/context-menu-widget';
1717
export {ScrollbarWidget} from './widgets/scrollbar-widget';
18+
export {IconWidget} from './widgets/icon-widget';
19+
export {ToggleWidget} from './widgets/toggle-widget';
20+
export {SelectorWidget} from './widgets/selector-widget';
1821
export {LoadingWidget as _LoadingWidget} from './widgets/loading-widget';
1922
export {ResetViewWidget as _ResetViewWidget} from './widgets/reset-view-widget';
2023
export {ScaleWidget as _ScaleWidget} from './widgets/scale-widget';
2124
export {ScreenshotWidget as _ScreenshotWidget} from './widgets/screenshot-widget';
2225
export {SplitterWidget as _SplitterWidget} from './widgets/splitter-widget';
2326
export {ThemeWidget as _ThemeWidget} from './widgets/theme-widget';
2427
export {TimelineWidget as _TimelineWidget} from './widgets/timeline-widget';
25-
export {ViewSelectorWidget as _ViewSelectorWidget} from './widgets/view-selector-widget';
2628
export {StatsWidget as _StatsWidget} from './widgets/stats-widget';
2729
export {useWidget} from './utils/use-widget';
2830
export type {
@@ -35,14 +37,16 @@ export type {
3537
PopupWidgetProps,
3638
ContextMenuWidgetProps,
3739
ScrollbarWidgetProps,
40+
IconWidgetProps,
41+
ToggleWidgetProps,
42+
SelectorWidgetProps,
3843
LoadingWidgetProps,
3944
ResetViewWidgetProps,
4045
ScaleWidgetProps,
4146
ScreenshotWidgetProps,
4247
SplitterWidgetProps,
4348
ThemeWidgetProps,
4449
TimelineWidgetProps,
45-
ViewSelectorWidgetProps,
4650
StatsWidgetProps
4751
} from '@deck.gl/widgets';
4852

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// deck.gl
2+
// SPDX-License-Identifier: MIT
3+
// Copyright (c) vis.gl contributors
4+
5+
import {IconWidget as _IconWidget} from '@deck.gl/widgets';
6+
import type {IconWidgetProps} from '@deck.gl/widgets';
7+
import {useWidget} from '../utils/use-widget';
8+
9+
export const IconWidget = (props: IconWidgetProps) => {
10+
useWidget(_IconWidget, props);
11+
return null;
12+
};

0 commit comments

Comments
 (0)