Making of paint.js.org
A Web Component-based Productivity
PWA
Christian Liebel
@christianliebel
Consultant
Slide 2
Slide 2 text
Hello, it’s me.
Making of paint.js.org
A Web Component-based Productivity PWA
Christian Liebel
Twitter:
@christianliebel
Email:
christian.liebel
@thinktecture.com
Angular & PWA
Slides:
thinktecture.com
/christian-liebel
Slide 3
Slide 3 text
https://paint.js.org
– Productivity app
– Draw images
– Lots of actions & tools
– Installable
– Read/save files
– Copy/paste images
from/to clipboard
– Share files to other apps
– Register for file extensions
Making of paint.js.org
A Web Component-based Productivity PWA
Demo
Slide 4
Slide 4 text
Web
Components
and Architecture
Canvas and
Input
Offline
Capability and
Installability
Copy and Paste
File Access and
File Handling
Dark Mode
Making of paint.js.org
A Web Component-based Productivity PWA
Agenda
Slide 5
Slide 5 text
Web
Components
and Architecture
Canvas and
Input
Offline
Capability and
Installability
Copy and Paste
File Access and
File Handling
Dark Mode
Making of paint.js.org
A Web Component-based Productivity PWA
Agenda
Slide 6
Slide 6 text
Web Components
– The web’s native component
model
– Easy interop
– Very basic: No data binding,
dependency injection, …
Making of paint.js.org
A Web Component-based Productivity PWA
Web Components and Architecture
Slide 7
Slide 7 text
Related APIs
Custom
Elements API
Definition of custom
HTML elements
Interaction via custom
DOM attributes,
properties, and events
Shadow DOM
Can prevent DOM
access from outside
Can prevent CSS
manipulation from
outside
HTML
Templates
(not used in this
demo)
Making of paint.js.org
A Web Component-based Productivity PWA
Web Components and Architecture
Slide 8
Slide 8 text
Lit
– Provided by Google
– Lightweight library (5 KB)
– Custom lifecycle on top of Web
Components
– Tagged template literals for HTML
and CSS to prevent XSS attacks
including support for data binding
– TypeScript decorators for
component registration and
attribute/property declaration
Making of paint.js.org
A Web Component-based Productivity PWA
Web Components and Architecture
Slide 9
Slide 9 text
Lit
@customElement('paint-tool-box')
export class ToolBox {
render(): TemplateResult {
return html`
${tools.map(
(tool) => html` this.selectTool(tool)}"
>`,
)}
`;
}
}
Making of paint.js.org
A Web Component-based Productivity PWA
Web Components and Architecture
Slide 10
Slide 10 text
Web Components
Making of paint.js.org
A Web Component-based Productivity PWA
Web Components and Architecture
Slide 11
Slide 11 text
Store Pattern
Making of paint.js.org
A Web Component-based Productivity PWA
Web Components and Architecture
Slide 12
Slide 12 text
Embedded
https://node-projects.github.io/web-component-designer-demo/index.html
Making of paint.js.org
A Web Component-based Productivity PWA
Web Components and Architecture
Slide 13
Slide 13 text
Web
Components
and Architecture
Canvas and
Input
Offline
Capability and
Installability
Copy and Paste
File Access and
File Handling
Dark Mode
Making of paint.js.org
A Web Component-based Productivity PWA
Agenda
Slide 14
Slide 14 text
Canvas
– Plain bitmap for the web
– Cross-platform, hardware-
accelerated graphics
operations
– Supports different contexts
(2D, 3D: WebGL, WebGL 2.0)
– Supported on all evergreen
browsers and on IE 9+
Making of paint.js.org
A Web Component-based Productivity PWA
Canvas and Input
Slide 15
Slide 15 text
Canvas 2D Context
fillRect(x, y, width, height)
strokeRect(x, y, width, height)
beginPath()
moveTo(x, y)
lineTo(x, y)
fill()
stroke()
Making of paint.js.org
A Web Component-based Productivity PWA
Canvas and Input
Slide 16
Slide 16 text
Pointer Events
Making of paint.js.org
A Web Component-based Productivity PWA
Canvas and Input
Users nowadays use different
input methods, cross-platform
apps should cover all of them
Pointer Events offer an
abstract interface to catch all
input methods (pointerdown,
pointermove, pointerup)
event.offsetX/event.offsetY
contain the pointer’s position
relative to the listener
Slide 17
Slide 17 text
Web
Components
and Architecture
Canvas and
Input
Offline
Capability and
Installability
Copy and Paste
File Access and
File Handling
Dark Mode
Making of paint.js.org
A Web Component-based Productivity PWA
Agenda
Slide 18
Slide 18 text
A Web Component-based Productivity PWA
Making of paint.js.org
Responsive Linkable Discoverable Installable App-like
Connectivity
Independent
Fresh Safe Re-engageable Progressive
Slide 19
Slide 19 text
Making of paint.js.org
A Web Component-based Productivity PWA
Web App
Manifest
Service
Worker
Slide 20
Slide 20 text
Web App Manifest
Distinguishes Web Apps from
Websites
JSON-based file containing
metadata for apps only
Apps can be identified by search
engines, app store providers, etc.
Making of paint.js.org
A Web Component-based Productivity PWA
Offline Capability and Installability
Slide 21
Slide 21 text
manifest.webmanifest
{
"short_name": "Paint",
"name": "Paint Workshop",
"theme_color": "white",
"icons": [{
"src": "icon.png",
"sizes": "512x512"
}],
"start_url": "/index.html",
"display": "standalone",
"shortcuts": [/* … */]
}
Making of paint.js.org
A Web Component-based Productivity PWA
Offline Capability and Installability
Names
Icons
Display Mode
Shortcuts
Start URL
Theme color (status bar/window bar)
Slide 22
Slide 22 text
Service Worker
JavaScript snippet executed in an
own thread, registered by the website
Acts as a controller, proxy, or
interceptor
Has a cache to store responses (for
offline availability and performance)
Can wake up even when the website
is closed and perform background
tasks (e.g., push notifications or sync)
Making of paint.js.org
A Web Component-based Productivity PWA
Offline Capability and Installability
Slide 23
Slide 23 text
Service Worker
Making of paint.js.org
A Web Component-based Productivity PWA
Offline Capability and Installability
Service
Worker
Internet
Website
HTML/JS
Cache
fetch
Slide 24
Slide 24 text
Web
Components
and Architecture
Canvas and
Input
Offline
Capability and
Installability
Copy and Paste
File Access and
File Handling
Dark Mode
Making of paint.js.org
A Web Component-based Productivity PWA
Agenda
Slide 25
Slide 25 text
Making of paint.js.org
A Web Component-based Productivity PWA
Slide 26
Slide 26 text
Project Fugu
Making of paint.js.org
A Web Component-based Productivity PWA
Capabilities
»Let’s bring the web
back – API by API«
Thomas Steiner, Google
Slide 27
Slide 27 text
Making of paint.js.org
A Web Component-based Productivity PWA
Capabilities
https://goo.gle/fugu-api-tracker
Slide 28
Slide 28 text
Browser
Making of paint.js.org
A Web Component-based Productivity PWA
Capabilities
navigator.share({ url: 'http://example.com' });
ShareIntent DataTransferManager
…
NSSharingServicePicker
Slide 29
Slide 29 text
Async Clipboard API
Allows reading from/writing to
the clipboard in an
asynchronous manner (UI won’t
freeze during long-running
operations)
Reading from the clipboard
requires user consent first
(privacy!)
Supported by Chrome, Edge
and Safari
Making of paint.js.org
A Web Component-based Productivity PWA
Copy and Paste
Slide 30
Slide 30 text
Async Clipboard API
const btnCopy = document.querySelector('#copy');
btnCopy.addEventListener('click', async () => {
const blob = await toBlob(canvas);
await navigator.clipboard.write([
new ClipboardItem({[blob.type]: blob})
]);
});
Making of paint.js.org
A Web Component-based Productivity PWA
Copy and Paste
Slide 31
Slide 31 text
Async Clipboard API
const btnPaste = document.querySelector('#paste');
btnPaste.addEventListener('click', async () => {
const clipboardItems = await navigator.clipboard.read();
for (const clipboardItem of clipboardItems) {
for (const type of clipboardItem.types) {
if (type === 'image/png') {
const blob = await clipboardItem.getType(type);
const image = await getImage(blob);
ctx.drawImage(image, 0, 0);
}
}
}
});
Making of paint.js.org
A Web Component-based Productivity PWA
Copy and Paste
Slide 32
Slide 32 text
Web
Components
and Architecture
Canvas and
Input
Offline
Capability and
Installability
Copy and Paste
File Access and
File Handling
Dark Mode
Making of paint.js.org
A Web Component-based Productivity PWA
Agenda
Slide 33
Slide 33 text
File System Access API
Some applications heavily rely
on working with files (e.g.
Visual Studio Code, Adobe
Photoshop, …)
File System Access API allows
you to open, save and override
files and directories
Supported by Chrome, Edge
Making of paint.js.org
A Web Component-based Productivity PWA
File Access and File Handling
Slide 34
Slide 34 text
File System Access API
btnSave.addEventListener('click', async () => {
const blob = await toBlob(canvas);
const handle = await window.showSaveFilePicker(fileOptions);
const writable = await handle.createWritable();
await writable.write(blob);
await writable.close();
});
Making of paint.js.org
A Web Component-based Productivity PWA
File Access and File Handling
Slide 35
Slide 35 text
File System Access API
btnOpen.addEventListener('click', async () => {
const [handle] = await window.showOpenFilePicker(fileOptions);
const file = await handle.getFile();
const image = await getImage(file);
ctx.drawImage(image, 0, 0);
});
Making of paint.js.org
A Web Component-based Productivity PWA
File Access and File Handling
Slide 36
Slide 36 text
File Handling API
Register your PWA as a
handler for file extensions
Requires installing the
application first
Declare supported extensions
in Web App Manifest and add
imperative code to your
application logic
Making of paint.js.org
A Web Component-based Productivity PWA
File Access and File Handling
Slide 37
Slide 37 text
File Handling API
"file_handlers": [{
"action": "/index.html",
"accept": {
"image/png": [".png"]
}
}]
Making of paint.js.org
A Web Component-based Productivity PWA
File Access and File Handling
Slide 38
Slide 38 text
File Handling API
if ('launchQueue' in window) {
launchQueue.setConsumer(async params => {
const [handle] = params.files;
if (handle) {
const file = await handle.getFile();
const image = await getImage(file);
ctx.drawImage(image, 0, 0);
}
});
}
Making of paint.js.org
A Web Component-based Productivity PWA
File Access and File Handling
Slide 39
Slide 39 text
Web
Components
and Architecture
Canvas and
Input
Offline
Capability and
Installability
Copy and Paste
File Access and
File Handling
Dark Mode
Making of paint.js.org
A Web Component-based Productivity PWA
Agenda
Slide 40
Slide 40 text
CSS Custom Properties
– Also known as “CSS variables”
– Cascade even through
Shadow DOM boundaries, i.e.
they can be accessed by
subordinate components
– Paint.js.org defines the
Windows 95 color scheme on
app root level
:host {
--button-face: rgb(192 192 192);
--button-light: white;
--button-dark: rgb(128 128 128);
--button-darker: black;
--button-text: black;
}
Making of paint.js.org
A Web Component-based Productivity PWA
Dark Mode
Slide 41
Slide 41 text
prefers-color-scheme CSS Media Feature
– The prefers-color-scheme CSS media feature indicates which color
scheme the user prefers
– Takes two values:
– light, if the user prefers a dark-on-light color scheme (or didn’t
actively make a decision)
– dark, if the user prefers a light-on-dark color scheme
– Preference is usually inherited form the operating system’s settings
– Changes are automatically reflected (e.g., when the operating system
switches between light and dark mode based on time)
Making of paint.js.org
A Web Component-based Productivity PWA
Dark Mode
Slide 42
Slide 42 text
CSS-Only
Light Mode
:host {
--button-face: rgb(192 192 192);
--button-light: white;
--button-dark: rgb(128 128 128);
--button-darker: black;
--button-text: black;
}
Dark Mode
@media (prefers-color-scheme: dark) {
:host {
--button-face: rgb(64 64 64);
--button-light: rgb(128 128 128);
--button-dark: rgb(32 32 32);
--button-text: white;
}
}
Making of paint.js.org
A Web Component-based Productivity PWA
Dark Mode
Slide 43
Slide 43 text
Making of paint.js.org
A Web Component-based Productivity PWA
Dark Mode
Slide 44
Slide 44 text
Web Components: Very robust, works consistently across evergreen
browsers, perfect for integration scenarios.
Lit: Shares basic concepts with other frameworks/libraries (such as
Angular), but is much more lightweight. Paint.js.org is smaller (=
transferred bytes) than the Windows 95 of Paint (320K)!
Capabilities: Powerful APIs available on Chromium and WebKit-based
browsers, fallbacks are used for other browsers.
Conclusion: Successful project! 🥳 You can perfectly implement web-
based (= cross-platform), desktop-class productivity applications.
Making of paint.js.org
A Web Component-based Productivity PWA
Summary
Slide 45
Slide 45 text
Making of paint.js.org
A Web Component-based Productivity PWA
Outlook
Slide 46
Slide 46 text
Thank you
for your kind attention!
Christian Liebel
@christianliebel
[email protected]