Common UI Components - JessicaOPRD/docs GitHub Wiki
I feel this is a good foundational breakdown, based on Google's many resources and research. You can spend time with Google's Material Design UI library and implementation (browseable demos here). The latest version is 3. There are many popular Material Design libraries implemented atop Angular, React, and Vue, of varying quality. It took me many years to discover Google did provide actual web implementations, not just design guidelines.
One risk in adopting Material Design is that many apps and websites begin to look alike. The Material Design studies show ways personality and marketing can still be applied to base components.
The components alone also do not create a beautiful app. A designer is still needed to determine layout, composition, flow, colors, etc. But the components do serve as popular, familiar conventions to build on.
Component | Version | Type | Notes | Examples |
---|---|---|---|---|
Badge | 3 | Navigational Feedback, Alert | ||
Bottom App Bar | 3 | Multi-item Navigation | ⚪ Mobile | |
Bottom Sheet | 1 | Multi-item Navigation, Collapsible Navigation, Modal, Surface | ⚪ Mobile ⚪ Standard or modal form (overlay) ⚪ Top corners rounded ⚪ Appears separate from "Navigation Drawer" in that it supplements current view/state and is not top-level navigation | |
Top Nav Bar | 1 | Multi-item Navigation | ||
Backdrop | 2 | Multi-item Navigation, Collapsible Navigation, Modal | ⚪ Mostly replaced bottom sheet in V2, but not V3 | |
Banner | 1 | Feedback, Alert | ⚪ Medium-priority feedback ⚪ Can be dismissed, hidden, or tied to another action that would remove the banner ⚪ Google warns not to stack them, however conditions-related alerts in parks are not the same as app or account-level alerts that might be queued ⚪ We currently stack 1-3 alerts based on Sharepoint conventions and it is amazing how much administrative pressure there is to have many "top-most" alerts | |
Button | 1 | Button | ⚪ Curiously uppercase text is default, but we have switched to normal case ⚪ Highest to lowest emphasis: Extended FAB, FAB (floating action button), filled, filled tonal, elevated, outlined, text, segmented (grouped), icon ⚪ Should it be a button or a link? | |
Breadcrumbs | ❌ | Multi-item Navigation | ⚪ Not in Material Design, but popularly supported by many libraries | |
Floating Action Button: FAB | 1 | Button | ||
Card | 1 | Grouping, Listing | ⚪ Stacks nicely on smaller devices ⚪ Actions buttons can be easy to miss depending on card ⚪ Alignment of action buttons sometimes feels off to me | |
Carousel | 3 | Listing | ⚪ Scroll horizontally ⚪ Primarily visual, with some text ⚪ Partially previewed or squished slide indicates more | |
Checkbox | 2 | Input, Selection Control | ⚪ Selection control in V1 | |
Chip | 1 | Input? | ⚪ Is it an input, button, link, or Bootstrap-style label? Each have different states/accessibility needs, and I see a lot of confusion in implementation especially at the screen reader level ⚪ Google calls horizontally-aligned cards chips, as seen in the Owl Material Design study | |
Data Table | 1 | Listing | ⚪ Goto for lists that need comparison ⚪ Unnatural stacking issues on smaller devices ⚪ Consider lists first if you can ⚪ CMS devs gravitate toward because it's familiar ⚪ Removed in V3 | |
Date Picker | 2 | Input | ⚪ Under "Picker" in V1 ⚪ Many implementations bypass native date picking UI which has historically been very poor, but on mobile I feel this is not true (at least for iPhone users) ⚪ Date range picker much trickier ⚪ I increasingly feel a mobile date picker if not native should be a full-screen dialog, especially if date range | |
Dialog | 1 | Modal, Alert | ⚪ Basic and fullscreen ⚪ For anything complicated consider full-screen variant ⚪ If for feedback, should be high-priority feedback only | |
Divider | 1 | Grouping | ⚪ An ancient web component ⚪ Can create airy groupings | |
Image lists | 2 only | Media, Listing | ⚪ What most of us call "image gallery" ⚪ Same gutter types: standard, quilted, masonry (Pinterest-style) ⚪ Varying gutter type: weave ⚪ I find the type names very helpful and visually descriptive ⚪ To avoid getting nailed on low-level accessibility scans that disqualify aria labels, make sure responsive imagery components use images and not backgrounds |
|
List | 1 | Listing | ⚪ Inevitable card vs. list debate -- cards tend to take up more space and work well for "discovery", listings are good when many list items are expected for "findability" ⚪ Horizontally compresses on mobile -- does not stack well and I often have to hide certain data in the list item | |
Menu | 1 | Multi-item Navigation, Collapsible Navigation, Input | ⚪ Intended to play role similar to what's seen in desktop apps, with nested behavior ⚪ However nested behavior often missing in implementations ⚪ Can be drop-down select or context menu ⚪ Often used to create Bootstrap-style popovers, but I would argue a popover is a different component depending on what it does? | |
Navigation Bar | 1 | Multi-item Navigation | ⚪ Replaced "Bottom Navigation" in previous versions ⚪ Web | |
Navigation Drawer | 1 | Multi-item Navigation, Collapsible Navigation, Modal | ⚪ Standard and fullscreen ⚪ I often want to fiddle with these to do something different on the web (full-screen, offset) ⚪ Popularly used for filtering options on small devices ⚪ Bottom variant very helpful but sometimes missing from existing libraries — look for "Bottom Sheet" | Nordstrom filters, mobile only |
Navigation Rail | 2 | Multi-item Navigation, Subnav | ⚪ More narrow and icon-driven that navigation drawer ⚪ Popular on tablet and desktop apps | |
Progress Indicator | 1 | Feedback | ⚪ Linear, circular ⚪ May be tied to actual progress or spin indefinitely until hidden | |
Radio Button | 2 | Input | ⚪ Selection control in V1 ⚪ Not to be used alone | |
Search | 3 | Navigation | ⚪ Alternative to other forms of navigation ⚪ Search bar and search view ⚪ Will likely be fulfilled through an autocomplete component | |
Sheet | 1 | Multi-item Navigation, Collapsible Navigation, Modal, Surface | ⚪ Filled containing elements similar to HTML <div> ⚪ Are sheets intended to be used as base components for cards, drawers, etc? Vuetify uses them this way with light/dark theme variants and it's probably smart to do this |
|
Side Sheet | 2 | Multi-item Navigation, Collapsible Navigation, Modal, Surface | ⚪ Introduced as "Sheet: Side" in V2 and "Side Sheet" in V3 ⚪ Appears separate from "Navigation Drawer" in that it supplements current view/state and is not top-level navigation ⚪ Standard or modal | |
Slider | 1 | Input | ⚪ Select from range of values ⚪ Continuous or discrete/stepped 🔴 Should update state immediately | |
Snackbar | 1 | Feedback, Alert | ⚪ Low-priority feedback ⚪ Toast if it appears from the bottom screen, although increasingly I don't see this terminology used — perhaps because it needs to be placed wherever makes the most sense per the design ⚪ Dismissive (disappear on timeout) and non-dismissive (disappear on user interaction) | |
Switch | 2 | Input | ⚪ Selection control in V1 ⚪ Boolean on/off indicator ⚪ Use when single item will be turned on/off | |
Tabs | 1 | Multi-item Navigation, Subnav | ⚪ Primary tabs (have icons above) and secondary tabs (only text) ⚪ Scrollable ⚪ I love tabs but find more than 3 problematic on mobile views — many users don't seem to understand scrollable tabs, and good implementation is very tricky (ideally a tab is straddled at the horizontal fold so it's clear there's more tabs) ⚪ I have resorted to replacing them with a menu on mobile (with peer navigation being maintained by prev/next buttons and a hamburger menu, which I think is a fair solution) ⚪ V2 says not for sequential content like "Chapter 1," "Chapter 2," etc | |
Text Fields | 1 | Input | ⚪ Remember when the default used to be a simple line? This doesn't appear to be recommended anymore — and we always had to use outline ⚪ Many complications: should user be able to type beyond character limit, should pattern be enforced on typing? My experience: stopping at character limit is good (or better highlight text beyond limit), pattern matching is difficult to implement and frustrating to the user — better to create more simple multiple inputs or allow free-form and indicate problem after timeout or blur | |
Time Pickers | 1 | Input | ⚪ Under "Picker" in V1 ⚪ Time picker dial and time picker input (V2) | |
Tooltip | 1 | Feedback | ⚪ I do kind of miss the little arrow ⚪ V1-V2: Problematic when description must be longer than 4-5 words, and there does not seem to be a multi-line solution ⚪ V3: Finally Google conceded tooltips do sometimes need to be more than 4-5 words on a single line: plain tooltip vs. rich tooltip |
Component | Google MD 3 | Bootstrap 5 | Vuetify | MudBlazor |
---|---|---|---|---|
Badge | Planned | ✔️ Badges and chips/labels are similar | ✔️ | ✔️ |
Bottom Sheet | ❌ | ✔️ As Offcanvas | ❌ | |
Card | Planned | ✔️ | ✔️ | ✔️ |
Carousel | Planned | ❌ Only supports traditional carousel | 🟡 As slide group, many issues in V2 | ❌ Only supports traditional carousel |
Checkbox | Planned | 🟡 As styled checkbox | ✔️ | ✔️ |
Data Table | ❌ | 🟡 Styled table only? | ✔️ As Data Grid? | ✔️ As Data Grid |
Date Picker | Planned | ❌ | ✔️ | ✔️ Under Pickers |
Dialog | ❌ | ✔️ As Modal | ✔️ | ✔️ |
Divider | Planned | 🟡 Likely styled HR | ✔️ | ✔️ |
Image and/or Image List | ❌ | ❌ | ✔️ | ✔️ |
List | Planned | ✔️ As List Group | ✔️ | ✔️ |
Menu | Planned | ❌ | ✔️ | ✔️ |
Navigation Bar | Planned | ✔️ As positioned Navbar | ✔️ | ✔️ As positioned AppBar |
Navigation Drawer | Planned | ✔️ As Offcanvas | ✔️ | ✔️ As Drawer |
Navigation Rail | Planned | ❌ | ✔️ As Navigation Drawer variant | 🟡 As Drawer variant? |
Progress Indicator | Planned | 🟡 Horizontal bar only, with spinners built into buttons | ✔️ | ✔️ |
Radio Button | Planned | 🟡 As styled radio button | ✔️ | ✔️ |
Search | Planned | ❌ | ✔️ As Autocomplete or Combobox | ✔️ As Autocomplete |
Side Sheet | Planned | ✔️ As Offcanvas | ✔️ As Navigation Drawer | ✔️ As Drawer |
Slider | Planned | ✔️ As Range | ✔️ As Slider | ✔️ As Slider |
Snackbar | Planned | ✔️ As Toast | ✔️ | ✔️ |
Switch | Planned | ❌ | ✔️ | ✔️ |
Tabs | Planned | 🟡 Not scrollable | ✔️ | ✔️ |
Time Picker | Planned | ❌ | 🟡 Dial only? | 🟡 Dial only? |
Tooltip | ❔ | ✔️ As Tooltip or Popover (must be clicked?) | ✔️ | ✔️ |
Other popular UI trends and conventions:
Not included in Material Design, but included in both Bootstrap, Vuetify, and MudBlazor. Curious why the exclusion?
Now included in Material Design as of V3. Popularly used to list cards horizontally. Essentially content carousels that ideally have touch/drag capability and straddle content along a fold that indicates more content exists. These are tricky to get right. A popular free option is Swiper. A popular standalone paid option is Flickity. As seen on the MET Museum. Another option is Slick. Glide is a slider/carousel that focuses on a center card/slide.
Material Design tabs are technically a slide group.
This non-native input has become popular when a start and end date must be selected as part of a search. Airbnb especially popularized beautiful date range pickers, and even released its original React component on GitHub. It is used in many projects including Recreation.gov. In January 2022, Airbnb released this component to its own repo for community development, as the Airbnb date range picker has changed considerably since its development.
Not formally accounted for in Material Design, but Material Design libraries often support an "Expansion Panels."
An example here (found by our dev friends over at Business Oregon)
Because form elements (dropdowns, date pickers, etc) are tied to the operating system and browser, there is a lot of variability in quality. However, sometimes the native feature is more intuitive or preferred for a certain device. I have long thought that I prefer native selection tools on an iPhone, for instance.
One approach is to develop different input components for different screens.
Input | Notes | Examples |
---|---|---|
Select/Dropdown | Nordstrom sort order, mobile only |
I have written my own dialogs to warn users about unsaved content. Increasingly I do see this implemented with a native dialog. Stubbing this to look into reasons this is preferred (guessing better use of built-in browser feature, convenience).