pwa-elements

Pre-built Web Components that give Progressive Web Apps native-quality camera, action-sheet, and toast UI.

Library
npm
v3.4.0
171stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
45/100Fair
Development Activity4
Maintenance20
Community76
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
62/100Good
Architecture72
Code Quality40
Innovation65
Learning Curve70

@ionic/pwa-elements is a small collection of framework-agnostic Web Components, built with Stencil, that give Progressive Web Apps native-quality UI for browser APIs that otherwise ship without any UI at all, most notably camera capture. It exists primarily to support Capacitor apps running as PWAs in the browser, where APIs like Camera need a visual layer that native platforms already provide for free.

The library ships four components: pwa-camera and its full-screen wrapper pwa-camera-modal, pwa-action-sheet, and pwa-toast, each a self-contained shadow-DOM custom element with no external UI framework dependency. Because Stencil compiles to standard Web Components, the same bundle drops unchanged into React, Vue, Angular, or vanilla JS apps, and ships with a dedicated loader for on-demand loading.

What You Get

  • Four production Web Components: pwa-camera, pwa-camera-modal, pwa-action-sheet, and pwa-toast
  • Shadow-DOM encapsulated styles that won’t collide with the host app’s CSS
  • A dedicated loader/ entry point for lazy, on-demand loading of individual components
  • Dual ESM and ES5 build outputs for broad browser and bundler compatibility

Common Use Cases

  • Providing camera capture UI for Capacitor apps running as installed or browser-based PWAs
  • Adding native-style action sheets to framework-agnostic web apps
  • Showing lightweight toast notifications without pulling in a full UI framework
  • Lazy-loading UI-heavy components only when a feature such as the camera is actually invoked

Under The Hood

Architecture The project is a flat, component-per-folder Stencil layout under src/components (action-sheet, camera, camera-modal, toast), each pairing a .tsx component definition with its own scoped .css and no shared framework layer beyond a small definitions.ts for shared types and an index.ts barrel export. The camera component is the most involved, composing an internal imagecapture.ts polyfill module and managing its own MediaStream, canvas, and video element references directly rather than through any shared abstraction; action-sheet and toast independently manage local open/closing state driven by requestAnimationFrame for enter/exit animations. There is no dependency injection or central store, state is entirely component-local via Stencil’s @State decorator, so the components could break independently of one another, but changing Stencil’s own @Component/@Prop/@State decorator API would ripple through every file since each implements directly against @stencil/core with nothing insulating the rest of the codebase from it.

Tech Stack TypeScript compiled through @stencil/core (^3.4.0, the sole runtime-shaping dependency), with np (^8.0.4) driving releases and workbox-build (^7.0.0) present as a devDependency though not directly referenced from src. stencil.config.ts configures a namespaced dist output with an ESM loader path plus a www preview target, an ES5 production build for older browsers/bundlers, and disabled sourcemaps. There is no server, database, or ORM layer; this is a purely client-side Web Components package with a comparatively thin, single-framework dependency tree and Node >=16/npm >=8 engine requirements.

Code Quality No .spec. or .test. files exist anywhere in the repository, and there are no CI workflow files under .github/workflows, only an ISSUE_TEMPLATE and CONTRIBUTING doc, meaning this snapshot has no automated tests or verified CI pipeline. The tsconfig enables noUnusedLocals and noUnusedParameters for some baseline hygiene, and prop/type shapes are captured in definitions.ts, but there’s no visible linter configuration. Naming is consistent (kebab-case custom element tags, PascalCase component classes), and the camera component has some defensive error handling (a dedicated deviceError state and handleNoDeviceError callback prop) but no broader formal error-handling pattern across the other components.

API Design Each component exposes itself as a plain HTML custom element with idiomatic props and attributes, facingMode and handlePhoto on pwa-camera, options and onSelection/onCanceled events on pwa-action-sheet, message and duration on pwa-toast, so consuming code is close to zero-boilerplate: import once, drop the tag into markup, and read results via callback props or DOM events. Documentation of these props lives only in source rather than in the README, which instead points to Capacitor’s own docs, so discoverability is somewhat thin, but the loader-based lazy-loading pattern meaningfully reduces the bundle-size cost of adopting these components.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search