-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs(widgets) Custom Widget Developer Guide #9304
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job ❤️
{layers.filter(layer => ( | ||
this.deck?.props.layerFilter({layer, viewport}) | ||
)).map((layer) => { | ||
<li key={layer.id}>{layer.id}</li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be much more code to show how control the layers in some way? For example, have a checkbox next to each layer to toggle visibility in that view?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can try it.. but controlling anything the user sets starts to get into a territory where user state and internal state can get out of sync. At least, there's nothing preventing user-space from just overriding any changes a widget makes to a layer. And there's some risk of introducing a race condition.
I think what this would look like with our current API is something like:
this.deck?.setProps({ layers: layers.map(layer => layer.clone({ visible: isVisible }) })
This could cause events to fire in the app that in-turn call setProps
. Is there a way to draw the layers without alerting the user? Perhaps:
this.deck?._drawLayers('layer-list-widget', { layers: ... })
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome work.
FWIW - One thing that I suspect will make widgets critical for me over the next year is the ability to use them in Python/pydeck. It could be a next step, making these available in python.
/** | ||
* Widget positioning within the view. Default: 'top-left'. | ||
*/ | ||
placement?: WidgetPlacement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider exporting a set of base WidgetProps
so that widget writers don't need to retype all of that?
placement?: WidgetPlacement; | |
export type WidgetProps = { | |
id?: string; | |
placement?: WidgetPlacement; | |
viewId?: string | null; | |
}; | |
... | |
export type AwesomeWidgetProps = WidgetProps & { | |
customText: string; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea to encourage consistency, though it's still 100% up to the widget authors to decide how they implement this since we're only defining an interface.
} | ||
``` | ||
|
||
## Best Practices |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section looks a little "lost" here at the very end of the page. Maybe lead with something like this before all the examples?. Or maybe the section will grow and it will look more natural.
|
||
## Handling View Interaction Events | ||
|
||
A widget can update in response to a user interacting with the deck.gl view the widget is attached to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is easily the most important section and needs its own page IMHO. (I do understand that we have work to do here.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Say more? What kind of example would you like to see?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been struggling to port the graph layers controller React component to a widget, I was looking for docs on how to implement zooms and pans
|
||
Below is a comprehensive example demonstrating a layer list widget implemented using Preact for dynamic UI rendering: | ||
|
||
```tsx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should really use MDX capabilities and make these widgets live on the pages...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Pessimistress suggested I can embed CodePen (e.g. LightingEffect) and found a react template too https://codepen.io/AdventureBear/pen/LYqwbwx
Co-authored-by: Ib Green <7025232+ibgreen@users.noreply.github.com>
Co-authored-by: Ib Green <7025232+ibgreen@users.noreply.github.com>
Co-authored-by: felixpalmer <felixpalmer@gmail.com>
} | ||
``` | ||
|
||
##### Applying the deck.gl widget design system |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should applying the design system be it's own page?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, the styling system is an important (top-level) part of your design!
Mutating the dom via ref is a react anti-pattern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is getting quite good.
I believe that a couple of iterative passes to make this even more logical and incremental to readers and would improve it further.
I added some suggestions to show what I mean.
Define a prop for adding a CSS class | ||
|
||
```ts | ||
interface AwesomeWidgetProps { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Total nit: Maybe tone it down somewhat and call it CustomWidget
? "Awesome" seems a bit out of style with rest of the docs.
@@ -0,0 +1,77 @@ | |||
# Writing Your Own Widget | |||
|
|||
## Preparations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
## Preparations | |
## Preliminaries |
|
||
* **[Implement a universal widget](./universal-widgets.md)** - A "universal widget" is a widget compatible with any deck.gl application and is UI framework agnostic. This is the best option for developing widgets intended to work across the deck.gl ecosystem. | ||
* **[Use Preact in a universal widget](./preact-widgets.md)** - Preact is a lightweight virtual DOM library commonly used to implement dynamic widget UI. It enables you to create highly interactive widgets without tightly coupling their internals to an application’s UI framework. | ||
* **[Wrap widgets in a React component](./react-widgets.md)** - If you are developing a custom Widget for a React application, you can use React to build the UI. This approach allows you to use React components and can coexist alongside other widgets. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These bullets do not fully explain the situation the way I see it.
It seems to me that there are two types of widgets - "universal" and "react".
* **[Wrap widgets in a React component](./react-widgets.md)** - If you are developing a custom Widget for a React application, you can use React to build the UI. This approach allows you to use React components and can coexist alongside other widgets. | |
- universal widgets can be 1) used in React apps 2) wrapped into React widgets, but the reverse is not true. | |
For React specifically, you have several options: | |
- You can use the universal widgets by supplying them to the `<DeckGL widgets={[new Widget()]} />` prop. | |
- You can wrap universal components into React components using the `useWidget()` hook. This way you can specify your components using JSX syntax.. | |
- If you are creating new components, can also create your own React components that implement the DeckGL widget interface. The advantage is that you write your code in the same style as the rest of your React application, however, these components would not be reusable in non-React applications.``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Even calling it "react" doesn't really say what this is.. it's fine, but people could use other frameworks, in theory.
Really, they're making the choice between implementing UI within the widget class, or outside of it.
Do any of these terms pair better? "universal", "internal", or "portable" for UI within the widget.
"react", "external", or "BYOF" (bring your own framework) for UI injected into the widget class.
* **[Use Preact in a universal widget](./preact-widgets.md)** - Preact is a lightweight virtual DOM library commonly used to implement dynamic widget UI. It enables you to create highly interactive widgets without tightly coupling their internals to an application’s UI framework. | ||
* **[Wrap widgets in a React component](./react-widgets.md)** - If you are developing a custom Widget for a React application, you can use React to build the UI. This approach allows you to use React components and can coexist alongside other widgets. | ||
|
||
## Creating The Widget class |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
## Creating The Widget class | |
## Creating a new Widget |
@@ -0,0 +1,215 @@ | |||
# Wrapping Widgets with React Components |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# Wrapping Widgets with React Components | |
# React Widgets | |
## Wrapping Widgets with React Components |
} | ||
``` | ||
|
||
##### Applying the deck.gl widget design system |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, the styling system is an important (top-level) part of your design!
|
||
Widgets in deck.gl allow developers to create custom UI elements that are deeply integrated into the deck.gl rendering system. This guide covers the steps to implement widgets that are framework-agnostic, ensuring compatibility across various applications. | ||
|
||
## Implementing the Widget Lifecycle Functions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be worth having a separate first page describing the widget lifecycle and interface before listing all the sundry ways of implementing this lifecycle/interface.
@@ -0,0 +1,374 @@ | |||
# Universal Widgets | |||
|
|||
Widgets in deck.gl allow developers to create custom UI elements that are deeply integrated into the deck.gl rendering system. This guide covers the steps to implement widgets that are framework-agnostic, ensuring compatibility across various applications. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move the first sentence into an introductory page (about-widgets.md).
Widgets in deck.gl allow developers to create custom UI elements that are deeply integrated into the deck.gl rendering system. This guide covers the steps to implement widgets that are framework-agnostic, ensuring compatibility across various applications. | |
This guide covers the steps to implement widgets that are "universal" or framework-agnostic, ensuring compatibility across various applications. | |
(Widgets in deck.gl allow developers to create custom UI elements that are deeply integrated into the deck.gl rendering system. ) |
|
||
### Adding a Widget | ||
|
||
[`onAdd({deck, viewId}): HTMLElement?`](../../api-reference/core/widget.md#onadd) - This method provides deck.gl with the root DOM element of your widget. This element is positioned based on `placement` and `viewId` members. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a lifecycle method, Deck.gl calls this method at some point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's called when the widget is first added.
Co-authored-by: Ib Green <7025232+ibgreen@users.noreply.github.com>
For #7946
Background
Adding developer guide to include more advanced examples about how to write both react and non-react widgets. This way our getting-started examples can be very simple, and we can have something to point more advanced users to when they're writing their own widgets.
Change List