Skip to content

Commit b6f768b

Browse files
LiaHiscockLia Hiscockcaptainbrosset
authored
Add <install> element README for OT (#116)
* spec out README * add pseuocode * update pseudocode * update issues link and versions * Update README.md * Apply suggestions from code review Co-authored-by: Patrick Brosset <patrickbrosset@gmail.com> * Revise README for install element usage instructions Updated README.md to improve clarity and fix formatting issues. * Update pwa-install-element/README.md * Update pwa-install-element/README.md * add local testing and comment out OT testing * add demo site * Update pwa-install-element/README.md --------- Co-authored-by: Lia Hiscock <liahiscock@microsoft.com> Co-authored-by: Patrick Brosset <patrickbrosset@gmail.com>
1 parent b354b19 commit b6f768b

7 files changed

Lines changed: 392 additions & 0 deletions

File tree

pwa-install-element/144x144.png

886 Bytes
Loading

pwa-install-element/48x48.png

1.31 KB
Loading

pwa-install-element/README.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Install element demos - `<install>`
2+
3+
This directory contains demos that showcase the use of the [install element](https://aka.ms/InstallElement), a new HTML element under development by the Microsoft Edge team to allow web contents to declaratively install other web apps. The element is currently supported on Windows, MacOS, Linux, and ChromeOS.
4+
5+
## Demos
6+
7+
* ➡️ **[The `<install>` Element Store](https://microsoftedge.github.io/Demos/pwa-install-element/)** ⬅️
8+
9+
## How to use the `<install>` element
10+
11+
### Detect support
12+
13+
```javascrit
14+
if ('HTMLInstallElement' in window) {
15+
// The <install> element is supported.
16+
} else {
17+
// The <install> element is not supported.
18+
}
19+
```
20+
21+
### Install the current document
22+
23+
To install the currently loaded document:
24+
25+
* The document must link to a manifest file.
26+
* The manifest file must have an `id` field defined.
27+
28+
```javascript
29+
<install id="install-button"></install>
30+
```
31+
### Install another document
32+
33+
To install a document that's not the current document, also known as a _background_ document, use either the `installurl` attribute, or both the `installurl` and `manifestid` attributes together:
34+
35+
To use the `installurl` attribute:
36+
37+
* The document at `installurl` must link to a manifest file.
38+
* The manifest file must have an `id` field defined.
39+
40+
```javascript
41+
<install installurl="https://foo.com" id="install-button"></install>
42+
```
43+
44+
To use the `installurl` and `manifestid` attributes together:
45+
46+
* The document at `installurl` must link to a manifest file.
47+
* The value of the `manifestid` attribute must match the computed id after parsing the manifest.
48+
49+
You can find the computed ID by going to **Application** > **Manifest** > **Identity** > **Computed App ID** in Microsoft Edge DevTools.
50+
51+
```javascript
52+
<install installurl="https://foo.com" manifestid="https://foo.com/someid" id="install-button"></install>
53+
```
54+
55+
### Handle installation success and errors
56+
57+
To handle the result of the web app installation process, use the `promptaction`, `promptdismiss`, and `validationstatuschanged` events:
58+
59+
```javascript
60+
if ('HTMLInstallElement' in window) {
61+
const button = document.getElementById('install-button');
62+
63+
// Listen to the promptaction event to know if the installation succeeded.
64+
button.addEventListener('promptaction', (event) => {
65+
console.log(`Install succeeded`);
66+
});
67+
68+
// Listen to the promptdismiss event to know if the installation failed.
69+
button.addEventListener('promptdismiss', (event) => {
70+
console.log(`Install failed`);
71+
});
72+
73+
// Listen to the validationstatuschanged event to detect invalid installation data.
74+
button.addEventListener('validationstatuschanged', (event) => {
75+
if (event.target.invalidReason === 'install_data_invalid') {
76+
console.log(event.target.invalidReason);
77+
}
78+
});
79+
} else {
80+
console.warn('HTMLInstallElement not supported');
81+
}
82+
```
83+
84+
## Test the feature locally
85+
86+
To test the `<install>` element feature locally, in your browser only, use Microsoft Edge version 148 or later (or another Chromium-based browser) and enable the **Web App Install Element** experiment:
87+
88+
1. In the browser, open a new tab and go to `about://flags/#web-app-install-element`.
89+
2. Enable the **Web App Install Element** flag.
90+
3. Click the **Restart** button in the bottom right. The browser restarts.
91+
92+
<!--
93+
## Test the feature in production with origin trials
94+
95+
The install element is currently available as an [Origin Trial](https://learn.microsoft.com/microsoft-edge/origin-trials/) in Microsoft Edge and Chrome versions 148 to 153. This allows you to use the feature on your production site and provide valuable feedback to browser vendors before it's finalized.
96+
97+
To use the install element on your production site, participate in the origin trial:
98+
99+
1. **Register for the origin trial:** [Install element registration page link](https://developer.chrome.com/origintrials/#/view_trial/XXXXXXXXXX)
100+
2. **Add the origin trial token:** Once you have the origin trial registration token, add the token to your pages by using a `<meta>` tag or an HTTP header. To learn more, see [Using the origin trial token at your website](https://learn.microsoft.com/microsoft-edge/origin-trials/#using-the-origin-trial-token-at-your-website).
101+
102+
```html
103+
<meta http-equiv="origin-trial" content="YOUR_TOKEN_HERE">
104+
```
105+
-->
106+
107+
## Provide feedback
108+
109+
Your feedback is crucial to the development of this feature. Please share feedback to:
110+
111+
* Report any issue you encountered.
112+
* Share improvement suggestions.
113+
* Share how you're using the `<install>` element.
114+
115+
To share feedback, [open a new issue on the WICG/install-element repo](https://github.com/WICG/install-element/issues/new?template=install-element-ot-feedback.md)
116+
117+
We look forward to hearing from you!
118+
119+
## See also
120+
121+
* [Explainer](https://aka.ms/InstallElement)
122+
* [Chrome Platform Status Entry](https://chromestatus.com/feature/5152834368700416)
123+
* [Test experimental APIs and features by using origin trials](https://learn.microsoft.com/microsoft-edge/origin-trials/#using-the-origin-trial-token-at-your-website)
124+

pwa-install-element/app.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
if ('HTMLInstallElement' in window) {
2+
const installElements = document.querySelectorAll('install');
3+
4+
installElements.forEach((button) => {
5+
button.addEventListener('promptaction', (event) => {
6+
const label = button.id || button.getAttribute('installurl') || 'same-origin';
7+
console.log(`Install succeeded: ${label}`);
8+
});
9+
10+
button.addEventListener('promptdismiss', (event) => {
11+
const label = button.id || button.getAttribute('installurl') || 'same-origin';
12+
console.log(`Install failed: ${label}`);
13+
});
14+
15+
button.addEventListener('validationstatuschanged', (event) => {
16+
if (event.target.invalidReason === 'install_data_invalid') {
17+
const label = button.id || button.getAttribute('installurl') || 'same-origin';
18+
console.log(`Install data invalid: ${label}`);
19+
}
20+
});
21+
});
22+
} else {
23+
console.warn('HTMLInstallElement not supported');
24+
}

pwa-install-element/index.html

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<link rel="manifest" href="manifest.json" />
7+
<link rel="icon" type="image/png" href="144x144.png" />
8+
<title>The &lt;install&gt; store</title>
9+
<link rel="stylesheet" href="style.css" />
10+
<script src="app.js" defer></script>
11+
</head>
12+
<body>
13+
<header>
14+
<h1>The <code>&lt;install&gt;</code> Element Store</h1>
15+
<install id="install-self" tabindex="0">Install the Store</install>
16+
</header>
17+
18+
<main>
19+
<article class="app_entry">
20+
<img src="https://microsoftedge.github.io/Demos/pwa-pwastore/images/app-icons/pwinter.png"
21+
width="75" height="75" class="app_icon">
22+
<div class="app_info">
23+
<h2><a href="https://diek.us/pwinter" target="_blank">The PWinter</a></h2>
24+
<p class="app_descrip">The PWinter is your custom PWA icon generator!</p>
25+
</div>
26+
<install installurl="https://diek.us/pwinter/" manifestid="https://diek.us/pwinter/index.html?randomize=true" tabindex="0">Install</install>
27+
</article>
28+
29+
<article class="app_entry">
30+
<img src="https://microsoftedge.github.io/Demos/pwa-pwastore/images/app-icons/pwamp.png"
31+
width="75" height="75" class="app_icon">
32+
<div class="app_info">
33+
<h2><a href="https://microsoftedge.github.io/Demos/pwamp/" target="_blank">PWAmp</a></h2>
34+
<p class="app_descrip">A music player PWA demo to play local audio files.</p>
35+
</div>
36+
<install installurl="https://microsoftedge.github.io/Demos/pwamp/" manifestid="https://microsoftedge.github.io/Demos/pwamp/" tabindex="0">Install</install>
37+
</article>
38+
39+
<article class="app_entry">
40+
<img src="https://microsoftedge.github.io/Demos/pwa-pwastore/images/app-icons/bubble.png"
41+
width="75" height="75" class="app_icon">
42+
<div class="app_info">
43+
<h2><a href="https://diek.us/bubble" target="_blank">Bubble</a></h2>
44+
<p class="app_descrip">360° equirectangular picture viewer. For images from 360 cameras.</p>
45+
</div>
46+
<install installurl="https://diek.us/bubble/" manifestid="https://diek.us/bubble/index.html" tabindex="0">Install</install>
47+
</article>
48+
49+
<article class="app_entry">
50+
<img src="https://mustjab.github.io/icon.png"
51+
width="75" height="75" class="app_icon">
52+
<div class="app_info">
53+
<h2><a href="https://mustjab.github.io/" target="_blank">Matrix PWA</a></h2>
54+
<p class="app_descrip">😎</p>
55+
</div>
56+
<install id="install-cross" installurl="https://mustjab.github.io/" tabindex="0">Install</install>
57+
</article>
58+
</main>
59+
</body>
60+
</html>

pwa-install-element/manifest.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "<install> store",
3+
"start_url": "./index.html",
4+
"theme_color": "#EF88BE",
5+
"id": "install-element-store",
6+
"display": "standalone",
7+
"background_color": "#FFFFFF",
8+
"icons": [
9+
{
10+
"src": "./48x48.png",
11+
"sizes": "48x48"
12+
},
13+
{
14+
"src": "./144x144.png",
15+
"sizes": "144x144"
16+
}
17+
]
18+
}

pwa-install-element/style.css

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
:root {
2+
color-scheme: light dark;
3+
--bg: #f5f5f5;
4+
--surface: #fff;
5+
--border: #ddd;
6+
--text: #1a1a1a;
7+
--accent: #EF88BE;
8+
--accent-secondary: #C8C8C8;
9+
--accent-hover: #e06aa3;
10+
--success: #107c10;
11+
--error: #d13438;
12+
--muted: #616161;
13+
--code-bg: rgba(0, 0, 0, 0.05);
14+
--shadow: rgba(0, 0, 0, 0.1);
15+
}
16+
17+
@media (prefers-color-scheme: dark) {
18+
:root {
19+
--bg: #1e1e1e;
20+
--surface: #2d2d2d;
21+
--border: #444;
22+
--text: #e0e0e0;
23+
--accent: #EF88BE;
24+
--accent-secondary: #C8C8C8;
25+
--accent-hover: #f4a5d0;
26+
--success: #4caf50;
27+
--error: #ef5350;
28+
--muted: #999;
29+
--code-bg: rgba(255, 255, 255, 0.08);
30+
--shadow: rgba(0, 0, 0, 0.3);
31+
}
32+
}
33+
34+
* { box-sizing: border-box; }
35+
36+
html, body {
37+
margin: 0;
38+
padding: 0;
39+
min-height: 100dvh;
40+
background: var(--bg);
41+
color: var(--text);
42+
font-family: "Segoe UI", -apple-system, BlinkMacSystemFont, sans-serif;
43+
}
44+
45+
body {
46+
display: grid;
47+
grid-template: min-content auto / 1fr;
48+
min-height: 100dvh;
49+
}
50+
51+
/* Header */
52+
header {
53+
padding: 1.5em 2em;
54+
display: flex;
55+
align-items: center;
56+
justify-content: space-between;
57+
gap: 1em;
58+
flex-wrap: wrap;
59+
}
60+
61+
header h1 {
62+
font-size: 1.6em;
63+
font-weight: 600;
64+
margin: 0;
65+
}
66+
67+
header h1 code {
68+
color: var(--accent);
69+
font-family: "Cascadia Code", "Consolas", monospace;
70+
background: none;
71+
padding: 0;
72+
}
73+
74+
/* Main grid */
75+
main {
76+
padding: 1em 2em;
77+
max-width: 700px;
78+
margin: 0 auto;
79+
display: flex;
80+
flex-direction: column;
81+
gap: 1.2rem;
82+
}
83+
84+
/* App cards */
85+
.app_entry {
86+
background: var(--surface);
87+
border: 1px solid var(--border);
88+
border-radius: 1rem;
89+
padding: 1.2rem 1.5rem;
90+
display: flex;
91+
flex-direction: row;
92+
align-items: center;
93+
gap: 1rem;
94+
text-align: left;
95+
transition: box-shadow ease-in-out 0.3s;
96+
box-shadow: 0 0 0 var(--shadow);
97+
}
98+
99+
.app_entry:hover {
100+
box-shadow: 10px 10px 20px var(--shadow);
101+
}
102+
103+
.app_icon {
104+
margin: 0;
105+
border-radius: 12px;
106+
flex-shrink: 0;
107+
}
108+
109+
.app_info {
110+
flex: 1;
111+
min-width: 0;
112+
}
113+
114+
.app_entry h2 {
115+
color: var(--accent-secondary);
116+
font-size: 1.15rem;
117+
font-weight: 600;
118+
margin: 0 0 0.2em;
119+
}
120+
121+
.app_entry h2 a {
122+
color: var(--accent-secondary);
123+
text-decoration: none;
124+
}
125+
126+
.app_entry h2 a:hover {
127+
text-decoration: underline;
128+
}
129+
130+
.app_descrip {
131+
color: var(--muted);
132+
font-size: 0.9em;
133+
line-height: 1.4;
134+
margin: 0 0 0.5em;
135+
}
136+
137+
/* The <install> element */
138+
install {
139+
display: inline-block;
140+
padding: 0.65rem 1.2rem;
141+
border: 1px solid var(--accent);
142+
border-radius: 10px;
143+
background: var(--surface);
144+
color: var(--accent);
145+
cursor: pointer;
146+
user-select: none;
147+
font-family: "Segoe UI", sans-serif;
148+
font-size: 1.05em;
149+
font-weight: 600;
150+
transition: background ease-in 0.2s;
151+
}
152+
153+
install:hover {
154+
background: var(--accent);
155+
color: var(--surface);
156+
}
157+
158+
@media only screen and (max-width: 600px) {
159+
main {
160+
grid-template-columns: 1fr;
161+
}
162+
header {
163+
flex-direction: column;
164+
text-align: center;
165+
}
166+
}

0 commit comments

Comments
 (0)