Skip to content

Commit

Permalink
Patch update demo (#272)
Browse files Browse the repository at this point in the history
* Changing the demo to be a same origin use case

* Optimize the animation to use GPU acceleration
  • Loading branch information
uskay authored Jul 6, 2021
1 parent 87b1728 commit 66aedaa
Show file tree
Hide file tree
Showing 9 changed files with 949 additions and 1,021 deletions.
1 change: 1 addition & 0 deletions demos/portal-embed-demo/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
"sourceType": "module"
},
"rules": {
"indent": ["error", 4]
}
}
140 changes: 35 additions & 105 deletions demos/portal-embed-demo/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
# portal-embed-demo
This demo demonstrates how Portals can enable a seamless user experience between a website and third-party embedded content. Be creative and have fun!!
This demo demonstrates how a \<portal\> element can enable a seamless user experience between two different pages.


## TL;DR;
- This demo consists of two websites (different origin):
- **PORTALOG**, a blog service,
- and **TTT Archive**, a podcast service.
- TTT Archive is embedded in one of PORTALOG's articles using **Portals**.
- Portals enables a **seamless experience** between the two websites.

**[This short explainer video](https://youtu.be/4JkipxFVE9k)** is a great place to start from.
![hero img](https://cdn.glitch.com/98449704-33d8-49b2-88f2-aa6d2aeba5d3%2Fhero_img.png?1556394393372)
- This demo consists of two pages (same origin):
- **PORTALOG**, an article page,
- and **TTT Archive**, a podcast page.
- TTT Archive is embedded in the PORTALOG article page using **the \<portal\> element**.
- \<portal\> enables a **seamless navigation experience** between the two pages.

![hero img](https://cdn.glitch.com/98449704-33d8-49b2-88f2-aa6d2aeba5d3%2Fportal-demo.gif?v=1625501108442)

## Running the demo
### 1. Run the app
Expand All @@ -20,120 +18,52 @@ $ git clone https://github.com/WICG/portals.git
$ cd portals/demos/portal-embed-demo
$ npm install
$ npm run demo
💻 Portal Demo has launched: http://localhost:3000/?portalpath=/ttt
```
Two local servers will start running.
A local server will start running.

```bash
$ npm run demo
📝 PORTALOG has launched: http://localhost:3000?portalport=3001
🎧 TTT Archive has launched: http://localhost:3001
```
### 2. Open a browser that supports \<portal\>
Learn the supported envirionments [here](https://web.dev/hands-on-portals/#enable-flags).

### 2. Open a browser that supports Portals
As of May 2019, Chrome Canary is the only platform that supports Portals. You can try out Portals in Chrome Canary by flipping an experimental flag (chrome://flags/#enable-portals).
### 3. Access [http://localhost:3000/?portalpath=/ttt](http://localhost:3000/?portalpath=/ttt)
You will see PORTALOG with TTT Archive embedded.

### 3. Access [ http://localhost:3000/?portalport=3001]( http://localhost:3000/?portalport=3001)
...and you will see PORTALOG with TTT Archive embedded.
> Note that HTMLPortalElement has not implemented the `autoplay` policies yet. The first time you access PORTALOG, audio might not play. In that case, try reloading PORTALOG, access TTT Archive directly and click on any buttons and go back.
> Note that HTMLPortalElement has not implemented the autoplay policies yet. The first time you access PORTALOG, audio might not play. In that case, try reloading PORTALOG, access TTT Archive directly and click on any buttons and go back, or disable the chrome://flags/#autoplay-policy while playing around with the demo.
## Design

### 4. Play around with it ;-)
😎😎😎
### Purpose of the demo
This is a demo to showcase what's possible with the \<portal\> element using [the same-origin message channel](https://github.com/WICG/portals#same-origin-communication-channels), [portal activation](https://wicg.github.io/portals/#dom-htmlportalelement-activate) and [the portal predecessor instance](https://wicg.github.io/portals/#dom-portalactivateevent-adoptpredecessor). The goal is to build a SPA-like smooth navigational experience with consistent state in a MPA (Multi-Page Application) architecture.

### Page design
The demo consists of two pages:
- PORTALOG ([https://localhost:3000/](https://localhost:3000/)) - a mock article page
- TTT Archive ([https://localhost:3000/ttt](https://localhost:3000/ttt)) - a mock podcast page that has the feature to select and play an audio

## Explainer
This is to show how you can use Portals in cross origin situations. The demo runs a two local express servers for PORTALOG and TTT Archive to simulate a cross origin use case. By default, PORTALOG is available at [http://localhost:3000/](http://localhost:3000/) and TTT Archive is available at [http://localhost:3001/](http://localhost:3001/).
> For the folks who don't know TTT (Totally Tooling Tips), please check out the [YouTube play list](https://www.youtube.com/playlist?list=PLNYkxOF6rcIB3ci6nwNyLYNU6RDOU3YyL).
The basic structure of the demo is explained below.
PORTALOG loads TTT Archive via the \<portal\> element to embed the audio player and seamlessly navigate back and forth between the two pages while playing the audio consistently. While TTT Archive is a single page, it has multiple UI style based on the state of the page:

![explainer](https://cdn.glitch.com/98449704-33d8-49b2-88f2-aa6d2aeba5d3%2Fportal_explainer.png?1556377936083)
![explainer-1](https://cdn.glitch.com/98449704-33d8-49b2-88f2-aa6d2aeba5d3%2Fportal-explainer-1.png?v=1625504903796)

Before getting into details... this could be the current experience w/o Portals
![withoutportals](https://cdn.glitch.com/98449704-33d8-49b2-88f2-aa6d2aeba5d3%2Fw_o_portals_new.gif?1556394769252)
- You can embed third party contents with **iframes**.
- But if you want to visit the content, a browser navigation starts and it needs to render all the content again which often leads to a **slow page load experience**.
- If you are playing the audio, **it just stops** due to page navigation.
### Basic use case and the sequence
- **Use case 1: Controling the audio** - While TTT Archive is being embeded via the \<portal\> element, use the same origin message channel to communicate between the host and the portal content i.e. `sendMessage` to command the audio player.

**...But with having Portals** 🚪🏃💨
![withportals](https://cdn.glitch.com/98449704-33d8-49b2-88f2-aa6d2aeba5d3%2Fw_portals.gif?1556394385809)
![explainer-2](https://cdn.glitch.com/98449704-33d8-49b2-88f2-aa6d2aeba5d3%2Fportal-explainer-2.png?v=1625504902812)

You can embed third party content just like an `iframe`.
```html
<!-- You can use it like iframes -->
<portal src='https://example.com'></portal>
```
OR
```javascript
// From JavaScript
const portal = document.createElement('portal');
portal.src = 'https://example.com';
```
> Demo code reference: [creating a portal element](public/js/portalog/portals-controller.js#L53)
A page can detect if it is inside a portal and, if so, modify its UI accordingly.
```javascript
// Detect whether this page is hosted in a portal
if (window.portalHost) {
// Customize the UI when being embedded as a portal
}
```
> Demo code reference: [Check if window.portalHost is available](public/js/ttt/ttt-controller.js#L181) and [change the style](public/js/ttt/ttt-controller.js#L183)
For now, portals do not respond to user input. If you want to interact with portals (like playing the audio in the demo), use `postMessage`.
```javascript
// Send message to the portal element
const portal = document.querySelector('portal');
portal.postMessage({someKey: someValue}, ORIGIN);

// Receive message via window.portalHost
window.portalHost.addEventListener('message', evt => {
const data = evt.data.someKey;
// handle the event
});
```
> Demo code reference: interacting with the audio player ([sending messages](public/js/portalog/portals-controller.js#L160) and [receiving messages](public/js/ttt/ttt-controller.js#L56))
- **Use case 2: Navigating into the embeded content** - When the user taps on the \<portal\> element, navigate to TTT Archive adding CSS transition animation.

When the user decides to navigate the the portal content i.e. click, it is a good opportunity to animate the portal and then call the `activate` function. User will be navigated to the portal content seamlessly (but the URL changes). The content continues running uninterrupted, and the audio even keeps playing after activation.
```javascript
// do some fancy animations and after animations are complete, activate the portal.
const portal = document.querySelector('portal');
portal.activate();
```
> Demo code reference: [animating the portal on click](public/js/portalog/portals-controller.js#L61) and [activating the portal](public/js/portalog/portals-controller.js#L98) (note that you can optionally pass [custom data](public/js/portalog/portals-controller.js#L99) to the portal)
Inside the portal content, you can listen to the `portalactivate` event to be notified when the page is activated. You can retrieve the previous page as a `<portal>` element by calling the `adoptPredecessor` function on the event. By leveraging the predecessor portal element, you can implement a seamless navigation experience when going back and forth between the two pages.
```javascript
// Listen to the portalactivate event
window.addEventListener('portalactivate', evt => {
// ... and creatively use the predecessor
const portal = evt.adoptPredecessor();
document.querySelector('someElm').appendChild(portal);
});
```
> Demo code reference: [listening to `portalactivate`](public/js/ttt/ttt-controller.js#L25) and [reusing the predecessor](public/js/ttt/ttt-controller.js#L35)
`activate` returns a promise that resolves when activation has completed.
```javascript
// The activate function returns a Promise.
// When the promise resolves, it means that the portal has been activated.
// If this document was adopted by it, then window.portalHost will exist.
portal.activate().then(_ => {
// Check if this document was adopted into a portal element.
if (window.portalHost) {
// You can start communicating with the portal element i.e. listen to messages
window.portalHost.addEventListener('message', evt => {
// handle the event
});
}
});
```
> Demo code reference: [sending messages to follow](public/js/ttt/writer-follow.js#L106) the writer of PORTALOG and [handling the event in the article page](public/js/portalog/portals-controller.js#L122)
![explainer-3](https://cdn.glitch.com/98449704-33d8-49b2-88f2-aa6d2aeba5d3%2Fportal-explainer-3.png?v=1625504903756)

- **Use case 3: Going back to the previous page** - When the user taps on the predecessor instance in TTT Archive (the background), activate the predecessor and navigate back to PORTALOG with animation.

Pleae also check how to use the \<portal\> element [here](https://web.dev/hands-on-portals/).


## Disclaimer
The code base is built for demo purpose only (non production ready code). It uses [Web Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components) (Shadow DOM v1, Custom Elements v1), [JS modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) (import/export) and written in ES6 syntax. To make the demo simple, it is not transpiled to ES5 and does not include any polyfills. If you access the demo with a browser that does not support Portals, it will show a message as below with an iframe fallback (and the UI could break).
The code base is built for demo purpose only (non production ready code). It uses [Web Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components) (Shadow DOM v1, Custom Elements v1), [JS modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) (import/export) and written in ES6 syntax. To make the demo simple, it is not transpiled to ES5 and does not include any polyfills. If you access the demo with a browser that does not support the \<portal\> element, it will show a message as below with an iframe fallback (and the UI could break).

![fallback](https://cdn.glitch.com/98449704-33d8-49b2-88f2-aa6d2aeba5d3%2Ffallback.png?1556379460425)
![fallback](https://cdn.glitch.com/98449704-33d8-49b2-88f2-aa6d2aeba5d3%2Fportal-fallback.png?v=1625507318099)

## TTT Archive creatives
Some of the images and mp3 files used in the TTT Archive demo are modifications based on work created and [shared by Google](https://developers.google.com/terms/site-policies) and used according to terms described in the [Creative Commons 3.0 Attribution License](https://creativecommons.org/licenses/by/3.0/).
Expand Down
Loading

0 comments on commit 66aedaa

Please sign in to comment.