Design Systems Team/Projects/CSS-only components

Project Overview & Background
CSS-only components will be a group of Codex components that are implemented solely by creating standard, shared styles for each component, meaning JavaScript is not required to use them. For example, to use a CSS-only Message component, a developer would either write or generate the markup for the message, then apply the shared styles to their markup, resulting in a no-JS message that has visual consistency with the Vue version of the Message component.

Currently, nearly all Codex components are implemented as Vue.js components, meaning they require JavaScript running on the client to work. Eventually, we hope to have a solution for rendering Vue components on the server (server-side rendering, or SSR), but this will take time, and there still may be use cases for no-JS versions of Codex components even if we have full SSR.

Impact
End users:


 * + Users without JavaScript can see and use UIs that have a consistent design that matches our canonical design system, across wikis
 * + Users with slow connections can see and start to use visually consistent UI components while they await the fully interactive JS version of the UI to load
 * + All users benefit from simple UIs that can be rendered on the server, which load quickly and provide a consistent experience
 * + Non-WMF wikis have a way to provide consistent server-rendered UIs without having to set up SSR
 * - Easily available API could mean misuse on-wiki, e.g. applying interface styles to content, or more potential for breaking visual changes due to high usage of CSS classes

Engineers:


 * + While they await an SSR solution, or in situations where SSR cannot be used, engineers can use CSS-only Codex components to style server-rendered elements, enabling them to use the current design system and reducing the need for custom code.
 * + Engineers with no JavaScript or Vue experience can build UIs with Codex components
 * + We can eventually deprecate old, inconsistent parts of our systems in favor of a single, centralized set of styles, leading to lower maintenance costs, less confusion, and easier onboarding of new developers
 * + Abstracting styles out of Vue components will mean having a set of implementation-agnostic base styles that could be applied to a new implementation in the future (e.g. React or a new framework)
 * - Development and maintenance costs: building this set of components will require time from DST and other teams to develop and test

Designers:


 * + Since styles are shared between CSS-only and Vue components in Codex, designers will have less to review when adding or changing components
 * + Once we deprecate old systems, designers will have fewer things to keep track of and work on, leading to greater velocity on the current system
 * + Designers who know HTML and CSS can use CSS-only components for rapid prototyping or to make code changes for production UIs

Proposed implementation strategy

 * 1) Use   classes for styling ("Bootstrap-style" approach). We are already writing BEM-style CSS inside our Vue components, so we don't need to make any changes here.
 * 2) Continue writing styles within Vue single-file components (SFCs). Where necessary, components will make distinctions between two sets of styles. The first is styles that only appear in the CSS-only version, and styles that only appear in the Vue version (both SSR-ed and mounted). We can distinguish these styles by adding   to the relevant classes to target Vue-only styles. The second is styles that only appear in a no-JS environment, and styles that only appear in a JS-enabled environment. We can distinguish these styles by adding a   or   class suffix when the component is mounted. Finally, we will add a ref to most components that will be set to   on (or right before) mount, via a composition function, which can be used to conditionally show different markup depending on whether the SSR-ed component has been hydrated or not (this last part could be done in the future during SSR implementation).
 * 3) Define a series of new Codex sub-packages which are intended for use within MediaWiki. Each new package will group together a set of related components (maybe corresponding to the component groups we were considering adding to the documentation site). This will work similar to how we are handling   currently. Each new package will get built in Vite’s library-mode, so a single JS and CSS file gets built with only the data for the relevant subset of components. An example of this can be seen in this patch, which creates a demo codex-buttons package: https://gerrit.wikimedia.org/r/c/design/codex/+/865840
 * 4) Each Codex sub-package gets its own ResourceLoader module containing only its CSS and JS files. Users only need to load the packages corresponding to the components they need in their feature.
 * 5) Load CSS and JS separately: There are two ways we can do this.
 * 6) * We could update ResourceLoader so that a user can get only the styles, or only the scripts, or both, when using a module that contains both CSS and JS. Currently this is only possible through an annoying work-around.
 * 7) * Alternatively, we will have to do this work manually. Each Codex sub-package would need to have two modules in MW – one containing only the CSS, i.e., and one containing only the JS files, i.e.  . The latter package would depend on the former, but the former can be used without the latter.
 * 8) Interaction with SSR: In the future, we expect that a more robust SSR system will be available in at least some situations. SSR-based features would basically create their own bundle instead of relying on the pre-split ones that we’d be providing here. Such builds will depend on the full Codex package (which contains all CSS and JS code). The SSR tooling will be able to tree-shake out all unnecessary code for these features, so the regular Codex modules will not be needed at all. See also: Design Systems Team/Projects/Modern user interfaces for all users

Risks/Trade-offs

 * This implementation strategy will allow us to keep writing our component styles within the Vue SFCs, which is nice from a familiarity and developer productivity approach.
 * We would need to create some additional packages inside the Codex repo, but this will mostly be a one-time task. As we add new components to Codex we'll need to include them in one of the existing sub-packages or (more rarely) create a new one. But little additional code is required here and once a sub-package has been set up it will rarely change. These will be included in each release just like  is (though we may not need to publish them on NPM since they are intended only for use in MW). See https://gerrit.wikimedia.org/r/c/design/codex/+/866509/ for an example of what this would look like.
 * CSS-only implementations of components will need to be tested; VueTest is a good place to do this (maybe a new sub-page of that extension can be created for the CSS-only components)
 * We'll need to create several additional ResourceLoader modules (especially if we cannot come up with a way to get just the CSS or JS from a module that contains both). But like in the case of the additional Codex packages, most of the work here is a one-time effort.
 * We might want to include some easily copy-pastable markup snippets for users in the absence of a good way to package up CSS-only components in mustache templates or PHP.

Timeline
Project phases come from Wikimedia Foundation's Inclusive Product Development playbook.


 * CSS-only versions of most Codex components are now available for use in JS-free environments: Codex


 * Project page created


 * Implementation proposal complete T321351


 * Scoping begins T321354

How to Engage
We welcome and encourage your participation in this initiative. Here are some ways to engage:


 * Add this page to your watchlist
 * Add your questions, concerns, and ideas to the talk page
 * Subscribe to relevant Phabricator tasks, linked above
 * For Wikimedia Foundation staff: join the #talk-to-design-systems-team Slack channel