Dated Apr 18, 2024;
last modified on Thu, 18 Apr 2024
What does it take to use web components? lists several options, and
Google’s
litis leading the pack in popularity at 1.6M
weekly downloads.
Stencil(703K,
Ionic
),
solid-js(269K,
Netlify
),
and FAST (88K,
Microsoft
) round up the
list of libraries with +50K weekly NPM downloads.
collects stats on bundle sizes and
performance. Notably, React falls in the lower end with large bundle
sizes and poor performance. Granted, React is still pretty popular
with
22M weekly NPM downloads
.
Community: Base Libraries: Open Web Components.open-wc.org.
Accessed Apr 23, 2024.
All the Ways to Make a Web Component - Feb 2022 Update.webcomponents.dev.
Accessed Apr 23, 2024.
Overview Starting with this page because it’s mostly static. The body is basically:
<div class="topnav">...</div> <div id="main_div"> <div id="study_buddy_details"> <div class="details_section">...</div> <div class="details_section">...</div> ... <div class="details_section">...</div> </div> </div> <footer>...</footer> The corresponding web components would be something along the lines of:
<nav-bar></nav-bar> <wiki-container> {Table of Contents} <wiki-section></wiki-section> <wiki-section></wiki-section> </wiki-container> <wiki-container> Maybe <wiki-section> can be a template owned by <wiki-container>? Nah, there are benefits to a separate <wiki-section> component, e.g., each component can define its title for use in the ToC....
Is there a use-case for the container that lays out the various app elements? When considering a <nav-bar> , the conclusion was that a web component wasn’t necessary.
Possible Organization The high-level picture is:
<body> <nav> <div id="topnav-banner">...</div> <ul id="topnav-items">...</ul> </nav> <div id="main_div">...</div> <footer>...</footer> </body> We should move #topnav-banner out of the <nav> so that we can potentially apply lateral spacing to #topnav-items and #main_div without it applying to #topnav-banner....
When a user lands at /browse, this UI is shown. A couple of components seem to emerge: search-bar, tags-list, card-results, and mini-card.
<search-bar> Currently, this is rendered by search_bar_dropdown.ejs, a partial that that is included in both /home and /browse. The fact that there it has JS, no server-delivered content, and has CSS makes it a good candidate for a web component. Revving up search-bar.ts.
Ran into Uncaught TypeError: Class constructor s cannot be invoked without 'new' on the export class SearchBar extends LitElement line....
UI Design Legacy card viewing UI at /browse.
This time we’ll use the more semantic and a11y-friendly <dialog> element . Centering it in the page is done by the browser, and that saves us a bit of hassle – thought it would have been feasible with how <search-bar>’s <ul> floats above the page.
CardsManager Interface The previous/next buttons make use of the CardsManager object that has the API:...
When a user lands at /home, this UI is shown. A couple of components are shareable from /browse, e.g., search-bar, search-results.
Sharing Code with /browse Components initially created for the /browse page are useful in /home as well.
The CardsViewingPage Interface This functionality can be shared between the two pages:
export class CardsViewingPage extends LitElement { @provide({ context: searchResultsContext }) @state() protected searchResults: CardSearchResult[] = []; @state() protected selectedResult: Card | null = null; @provide({ context: cardsCarouselContext }) @state() protected cardsCarousel = new CardsCarousel([]); protected cardFetcher: CardFetchEndpoint; constructor(cardFetcher: CardFetchEndpoint) { super(); this....
More than once, I’ve been surprised by a web component either showing data that should no longer be there, or not showing data that should be there. This page aims to reason through such cases for a better mental model of web components.
Rendering Lists Both <search-bar> and <search-results> need to render a collection of N items. offers two options: looping, or using the repeat(items, keyFunction, itemTemplate) directive.
const cards = html` ${cards....