My Design System

Why I Created a Design System

I was using Material UI for a project, and the bundle size, combined with the css-in-js approach to styling, resulted in an application that was difficult to render on the server and that had a pretty poor initial load time. I wanted to create a design system that was similar to Material UI / Flutter but that emphasized semantic HTML and a small bundle size.

Also, when creating a Rich Text Editor with Lexical, I found that it was best to not use highly abstracted components, so I tried to create a library of simple components that can be easily rendered on the server and that doesn't use too much CSS and JavaScript.

In summary, the goal of the design system is to create a look that is comparable to other popular design libraries used today while minimizing load time, bundle size, and complexity.

Assumptions

The design system assumes that:

  • you want to use HTMX to create a SPA (Single Page Application),
  • you want to use semantic html, but that you want to style components primarily with CSS classes and inline styling,
  • your Content Security Policy allows for inline styling,
  • you want to use Floating UI for tooltips, menus, dropdowns, and the like,
  • you want to have slightly different layouts for desktop and mobile,
  • you want to prioritize mobile devices (you want the application that you show the user to always be similar to the mobile device view),
  • you do not want to listen to resize events on mobile

Explore the Design System

If you are looking for information about specific components or utility classes, use the links in the list below to find more information about those aspects of the system. Each aspect of the design system should describe the styling, accessability, and JavaScript concerns that go along with it.

If you are looking to learn more about the design system and the decisions made, continue reading below or navigate to the 'General' page for the design system.

If you want the code, navigate to the resources section.

Tabs

About Tabs
This section includes a Stepper, Mobile Stepper (like), and Tabs Component.
Stepper

Steppers consist of multiple "steps" which need to be completed by the user in pursuit of completing some larger task. The version of a stepper in this design system assumes that you want to touch the server every time the user completes some subtask (a step).
Steppers consist of a wrapper <div class="stepper-container">, an <ol class="stepper">, and list items which either contain an svg + a span denoting what the task is about or just an svg that draws the line between two steps.
Each list item in the ordered list has an aria-current attribute that communicates which step the user is currently working on.
All list items that are prior to the aria-current="step" should have a data-completeattribute on them, which sets their color / fill to be var(--secondary).
Since we assume that you want to touch the server in between completion of steps, there really is no client-side JavaScript that applies to the Stepper.

Mobile Stepper

When new content is loaded, the client side JavaScript gets all <div class="mobile-stepper"> elements, and:

  1. adds a keydown listener to the wrapper div
  2. checks if they have <button data-step-back> and <button data-step-forward> buttons. If they do, listeners are added to the buttons to change the current tab when clicked.
  3. gets all tabs (<button role="tab">), and adds click listeners to them to change tabs when clicked.
  4. gets the tab panels (the next element sibling of the mobile stepper wrapper), and sets their visibility based on which tab has an aria-selected attribute equal to true
  5. sets disabled the forward button and back button based on whether or not the current tab is the first or last tab
Tabs

The JavaScript for the tabs is basically the same as the JavaScript for the Mobile Stepper except for the fact that the Tabs hav no forward and back buttons.

Make sure that the number of tab panels is equal to the number of tabs. If this is not the case, there will be an error.

JavaScript for Tabs
Changing Tabs Here is the process for changing tabs:
  1. Get the currently selected tab's index (based on the order of tabs inside the <ul>), and get the tabindex of the newly selected tab.
  2. Set the styling and aria-selected attributes of the tabs and set the visibility of the tabpanels - look into the function switchTabs() of the shared JavaScript code.
Handling Keydown Due to accessability reasons, this design system allows you to navigate tabs using the forward and back arrow keys.
Accessability

Look into the examples below for the aria-roles, roles, and data-attributes that re required for tabs.
The Cauldron Docs are the reference for Stepper Accessability, and this youtube video is the reference for tabs accessability.

Stepper

  1. Enter Poll Questions
  2. Select Communities
  3. Review And Submit
  1. Enter Poll Questions
  2. Select Communities
  3. Review And Submit
  1. Enter Poll Questions
  2. Select Communities
  3. Review And Submit

Mobile Stepper

Here is the first tab panel. Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad cupiditate ullam, libero beatae velit inventore dolor minima ipsam dicta esse non exercitationem quidem qui deleniti maxime dolorem officia odio minus.

Image Carousel Example:

Example Picture 1

Tabs

Here is the second tab panel. Lorem, ipsum dolor sit amet consectetur adipisicing elit. Hic quidem quaerat similique? Sunt in natus, unde libero, qui officia rem quis facilis suscipit quasi ipsum magnam aspernatur voluptates voluptatum perferendis?''

Resources

Click on the individual buttons to download separate files, or click on the All Files button to download a ZIP file of all the code. The code is sent pre-transpiled for readability.
Click on the VSCode Snippet button to download a copy of the html.json file that will make implementing this design system simpler.