Skip to content
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

add(widgets) fullscreen widget #8024

Merged
merged 48 commits into from
Sep 25, 2023
Merged

add(widgets) fullscreen widget #8024

merged 48 commits into from
Sep 25, 2023

Conversation

chrisgervang
Copy link
Collaborator

@chrisgervang chrisgervang commented Jul 25, 2023

For #7946

Background

A fullscreen widget adds a button which users can click to make their map full screen. Click it again to exit full screen.

Design Goals

themes.ts provides 4 built-in themes, and the getting started example shows how these can be applied.

import {Deck} from '@deck.gl/core';
import {FullscreenWidget, DarkTheme} from '@deck.gl/widgets';

new Deck({
  ...
  widgets: [new FullscreenWidget({ style: DarkTheme })
})

With CSS variables it's possible for applications to make customizations, such as:

  • Light and dark mode (i.e. prefers-color-scheme media-query, or prop override)
  • Desktop/mobile sizes (i.e. max-width media-query, or prop override)
  • Total visual customization, such as glass or flat
  • Branding, such as coloring, shadows, corners, etc

Examples

Implementation Goals

  • Provide css stylesheet via NPM for applications to include
  • Themable with CSS variables and class selectors.
  • VanillaJS interface with preact UI framework internally to minimize complexity and bundle size.
  • For icons, prefer inline SVG over heavy icon fonts

Compatibility

Currently the widget assumes the Fullscreen API is supported without prefixes since it's a mature API at this point. If it's not, then a "pseudo" fullscreen is styled with css.

Change List

  • Adds FullscreenWidget
  • Adds widgets getting started example
  • docs

@chrisgervang
Copy link
Collaborator Author

Please leave design comments in our prototype. Open to suggestions!

@chrisgervang
Copy link
Collaborator Author

chrisgervang commented Jul 26, 2023

Learning a bit more about CSS variables. They aren't supported inside media queries directly, but a combination of JS and CSS can be used. See discussion.

It'd be ideal to keep variable names shorter, such as --background vs. --deckgl-widget-background. Variables can be scoped with selectors such as .deckgl-widget (or similar) instead of :root. It can be any selector name an application likely doesn't already use.

Supporting browsers that lack css variable support is straightforward. Just define each style twice with and without a variable, and the cascading will apply the latter "valid" property.

modules/widgets/src/fullscreen-widget.ts Outdated Show resolved Hide resolved
@@ -57,5 +58,6 @@ new Deck({
getTargetColor: [200, 0, 80],
getWidth: 1
})
]
],
_widgets: [new FullscreenWidget()]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assume you will create a new example for effects.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pessimistress suggested I add to the getting started, but I'm not sure if this is what she meant.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add a separate example unless you think it's a good functionality to surface on all the examples. Each get-started flavor (pure-js, react, script) demonstrate exactly the same functionality.

modules/widgets/src/fullscreen-widget.ts Outdated Show resolved Hide resolved
chrisgervang and others added 2 commits July 27, 2023 12:18
Co-authored-by: Ib Green <ib@foursquare.com>
Co-authored-by: Ib Green <ib@foursquare.com>
Copy link
Collaborator

@ibgreen ibgreen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some thoughts:

  • Do we have provisions for declaratively setting props on this component (let's say that the component offered a hideNavigationUI prop and the app wanted to change that after creating the component.

  • What if the app programmatically wants to active the effect that an interactive widget controls. Let's say that the app wanted to trigger full screen, how would it do that?

  • Docs - In documentation mention that this feature is not available on iPhones?
    https://caniuse.com/?search=requestFullscreen

  • Tests - testing the fullscreen effect may be overkill, but at least add the control to the DOM and and remove it when testing under browser?

modules/widgets/src/fullscreen-widget.ts Outdated Show resolved Hide resolved
@chrisgervang
Copy link
Collaborator Author

Thanks for the comments, @ibgreen. I'll take these into account as iteration continues in this PR. In the meantime, let us know if you have comments on #8023 since that's about to merge in.

@chrisgervang
Copy link
Collaborator Author

Evaluated RE:DOM as a lightweight html-in-js solution that is supposed to offer a JSX syntax. JSX works fine without typescript in this isolated example I made, but I'm not figuring out how to get redom JSX to work with typescript in this other example.

RE:DOM and typescript don't seem to be pretty commonly documented together. And babel seems to have moved on to a new way to building jsx plugins, which RE:DOM doesn't implement.

Resouces


Setup notes:
yarn add babel-plugin-transform-redom-jsx babel-plugin-transform-react-jsx --dev -W

// babel.config.js
...
plugins: [
  "babel-plugin-transform-redom-jsx",
  [
    "transform-react-jsx",
    {
      "pragma": "el"
    }
  ]
]
// tsconfig.json
"compilerOptions": {
  "jsx": "preserve",
  "jsxFactory": "el"
  ...
},

Base automatically changed from chr/deck-widgets-prop to master August 15, 2023 19:28
modules/widgets/src/fullscreen-widget.tsx Outdated Show resolved Hide resolved
modules/widgets/src/fullscreen-widget.tsx Outdated Show resolved Hide resolved
@@ -30,7 +30,8 @@
"prepublishOnly": "npm run build-bundle && npm run build-bundle -- --env=dev"
},
"dependencies": {
"@babel/runtime": "^7.0.0"
"@babel/runtime": "^7.0.0",
"preact": "^10.17.0"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, I haven't really being paying attention. Are we using a react style library for our pure-js implementation? And then we will have react wrappers on top?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty certain we don't want the complexity or bundle size of react, but I like its api style.

My goal has been to pick something as close to the DOM as we can while also providing some convenience over document.createElement. preact seems to serve this niche well... It give us the ability to make basic components with JSX, and implements a thin virtual dom only adding 3kb to the bundle.

Re: react wrappers, I think of a widget as a deck component that happens to have UI. In a sense, how the UI is built within it is ideally isolated from other UI on the page so that deck can manage it. Let's say we used react to make UI widgets in @deckgl/widgets... I'd still ideally want them to create their own react root separate from the rest of application and other widgets. This way all integrations work through the same interface.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood and I agree with the principle that widgets should be free to choose implementation as long as they are externally independent. That said, I would not be happy to see a pure-js deck.gl module have react as a dependency in its package.json. I would think twice before using that in a pure-js app.

For a community widget that could be a different story of course.

preact seems like a reasonable choice.

modules/widgets/src/fullscreen-widget.tsx Outdated Show resolved Hide resolved
const el = document.createElement('div');
el.classList.add('deckgl-widget', 'deckgl-widget-fullscreen');
if (className) el.classList.add(className);
Object.entries(style).map(([key, value]) => el.style.setProperty(key, value));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started with that, but it doesn't work for css variables.

Object.assign(el.style, this.props.style); results in no variables applied to the middle widget.
Screen Shot 2023-09-09 at 3 19 00 PM

el.style.setProperty has inline styles:
Screen Shot 2023-09-09 at 3 19 23 PM

I think we need to change how Deck does it so the theme variables will work.

Comment on lines +71 to +73
new FullscreenWidget({}),
new FullscreenWidget({id: 'themed', style: widgetTheme}),
new FullscreenWidget({id: 'purple', className: 'purple'})
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pessimistress I was thinking of move these variations to a test app. I want to maintain coverage for edge cases somewhere, and keep getting started very simple. Thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes agreed

@chrisgervang
Copy link
Collaborator Author

Users may want to replace the icons, so I've moved them to CSS. To replace with your own we'll document:

Icons are replaceable and their colors can be customized with CSS variables.

  • Prepare your icons as SVG urls for a CSS mask-image.
  • The color of embedded in your SVG will be ignored, but ensure it isn’t transparent. Set the color with the appropriate CSS variable.
  • Replace the icon with CSS variables like --icon-fullscreen-enter.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pessimistress, added sections for replacing icons and made other adjustments. Any comments?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chrisgervang chrisgervang merged commit 6d2c4b9 into master Sep 25, 2023
2 checks passed
Pessimistress pushed a commit that referenced this pull request Oct 5, 2023
@Pessimistress Pessimistress deleted the chr/fullscreen-widget branch October 13, 2023 17:25
@chrisgervang chrisgervang mentioned this pull request Feb 9, 2024
14 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants