diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index c4a8fee5514..00000000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
- "parser": "@typescript-eslint/parser",
- "parserOptions": {
- "ecmaVersion": 2018,
- "sourceType": "module",
- "ecmaFeatures": {
- "jsx": true
- }
- },
- "plugins": ["@typescript-eslint"],
- "rules": {
- "@typescript-eslint/ban-types": "off",
- "@typescript-eslint/explicit-module-boundary-types": "off",
- "@typescript-eslint/no-explicit-any": "off",
- "@typescript-eslint/no-non-null-assertion": "off",
- "@typescript-eslint/no-unused-vars": "off",
- "no-prototype-builtins": "off",
- "no-useless-escape": "off",
- "prefer-spread": "off"
- }
-}
diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index 750cea4b16e..f893380efb0 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -2,33 +2,117 @@
# https://help.github.com/en/articles/about-github-actions
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
-name: Install Dependencies, Lint
+name: Validate Docs
on: [pull_request]
+# A new push supersedes the run before it.
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ NODE_VERSION: 24
+
jobs:
- test:
- name: Test on ${{ matrix.os }}
+ # Needs no dependencies, so it reports in seconds rather than queueing behind
+ # npm ci and lint.
+ admonitions:
+ name: Check Admonitions
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ # The check diffs against the pull request base, so it needs history.
+ fetch-depth: 0
+ - uses: ./.github/workflows/actions/check-admonitions
+
+ # These produce the same verdict on any operating system, so they run once.
+ checks:
+ name: Checks
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - name: ⚙️ Use Node.js
+ uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: npm
+ - name: 🕸️ Install Dependencies
+ run: npm ci
+ - name: Test
+ run: npm run test
+ - name: 🧩 Typecheck
+ run: npm run typecheck
+ - name: 🔤 Spell Check
+ run: npm run spellcheck
+ # Docusaurus derives a heading's anchor from its text, so renaming a
+ # heading moves the anchor and breaks every inbound link. An explicit id
+ # survives the rename, and lets a translation keep the English anchor
+ # after the heading text is translated.
+ #
+ # Nothing in Docusaurus enforces this: a page whose headings are all
+ # unpinned builds clean. So run its own generator and fail if it had
+ # anything to add.
+ - name: 🔗 Heading IDs
+ run: |
+ npm run heading-ids
+ if ! git diff --quiet -- docs; then
+ echo "::error::Headings are missing explicit ids. Run \`npm run heading-ids\` and commit the result."
+ git diff -- docs
+ exit 1
+ fi
+ - uses: ./.github/workflows/actions/check-translations
+ # Vercel builds on Linux, where imports are case-sensitive. No other check
+ # resolves the imports in doc pages, so an import with the wrong casing only
+ # fails when the site is built.
+ - name: 🏗️ Build
+ run: |
+ npm run generate-markdown
+ npm run build:preview
+ env:
+ # The release notes page reads releases from the GitHub API, and the
+ # script fails in CI without a token.
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ cross-platform:
+ name: Cross-platform on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
- node_version: [20]
+ # Prettier rewrites line endings, so Lint is the one check whose
+ # verdict depends on the operating system.
os: [windows-latest, macOS-latest]
steps:
- - uses: actions/checkout@v4
- - name: Use Node.js ${{ matrix.node_version }}
- uses: actions/setup-node@v4
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - name: ⚙️ Use Node.js
+ uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
- node-version: ${{ matrix.node_version }}
- - name: Install Dependencies
- run: npm ci --legacy-peer-deps
- - name: Lint
+ node-version: ${{ env.NODE_VERSION }}
+ cache: npm
+ - name: 🕸️ Install Dependencies
+ run: npm ci
+ - name: 🖌️ Lint
run: npm run lint
- - name: Spell Check
- run: npm run spellcheck
- # Lint and spell check changes should be pushed
- # to the branch before the branch is merge eligible.
- - name: Check Diff
+ # Lint changes should be pushed to the branch before the branch is merge
+ # eligible.
+ - name: 🔍 Check Diff
run: git diff --exit-code
shell: bash
+
+ verify:
+ # The one required check on main and the feature branches, so the jobs
+ # above can change without touching the protection rules. Renaming this
+ # blocks merges until those rules are updated to match.
+ name: Verify
+ if: ${{ always() }}
+ needs: [admonitions, checks, cross-platform]
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Check job status
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+ run: exit 1
diff --git a/.github/workflows/actions/check-admonitions/action.yml b/.github/workflows/actions/check-admonitions/action.yml
new file mode 100644
index 00000000000..8cd33474a5d
--- /dev/null
+++ b/.github/workflows/actions/check-admonitions/action.yml
@@ -0,0 +1,89 @@
+name: 'Check Admonitions'
+description: 'Fails on admonition titles using the MDX v1 syntax'
+runs:
+ using: 'composite'
+ steps:
+ # `:::note My Title` was MDX v1 syntax that Docusaurus rewrote for us.
+ # With `future.v4.mdx1CompatDisabledByDefault` that shim is off, and
+ # the block `:::note My Title` stops being a directive: it renders as
+ # literal `:::note` text on the page, with no warning and a successful
+ # build.
+ #
+ # The other MDX v1 forms, HTML comments and `{#heading-ids}`, fail the
+ # build on their own, so this only covers the one that fails silently.
+ #
+ # Only the files the pull request touches are checked, so an existing
+ # page is never anyone else's problem to fix.
+ #
+ # The caller has to check out with `fetch-depth: 0`, which a composite
+ # action cannot require for itself.
+ - name: 🔎 Check Admonitions
+ shell: bash
+ env:
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
+ CHANGED_FILES: ${{ runner.temp }}/changed-files.txt
+ run: |
+ git diff --name-only --diff-filter=ACMR "$BASE_SHA" HEAD > "$CHANGED_FILES"
+ node <<'JS'
+ const { readFileSync } = require('fs');
+
+ // Files Docusaurus compiles as MDX. Under `static/usage` that is
+ // only the `index` files; the rest are raw code samples.
+ const compiled = (f) =>
+ !f.endsWith('README.md') &&
+ ((/^(docs|versioned_docs|src\/pages)\//.test(f) && /\.mdx?$/.test(f)) ||
+ (f.startsWith('static/usage/') && f.endsWith('.mdx')));
+
+ // Defaults from `@docusaurus/mdx-loader/lib/remark/admonitions`.
+ const keywords =
+ 'secondary|info|success|danger|note|tip|warning|important|caution';
+ const legacyTitle = new RegExp(
+ `^[ \\t]*:::(?:${keywords})[ \\t]+(?!\\[)\\S[^\\n]*`,
+ 'gm'
+ );
+
+ // A `:::note` in a code sample is an example, not a directive.
+ // Blank out code samples with spaces, same length so line numbers
+ // still match.
+ const blank = (m) => m.replace(/[^\n]/g, ' ');
+ const mask = (t) =>
+ t
+ .replace(/^([ \t]*)(`{3,}|~{3,})[^\n]*\n[\s\S]*?^\1\2[ \t]*$/gm, blank)
+ .replace(/(`+)(?:(?!\1)[\s\S])+?\1/g, blank);
+
+ const files = readFileSync(process.env.CHANGED_FILES, 'utf8')
+ .split('\n')
+ .filter(compiled);
+
+ if (!files.length) {
+ console.log('No MDX files changed.');
+ process.exit(0);
+ }
+
+ const findings = [];
+ for (const file of files) {
+ const source = readFileSync(file, 'utf8');
+ for (const m of mask(source).matchAll(legacyTitle)) {
+ findings.push({
+ file,
+ line: source.slice(0, m.index).split('\n').length,
+ text: source.slice(m.index, m.index + m[0].length).trim(),
+ });
+ }
+ }
+
+ if (!findings.length) {
+ console.log(`No MDX v1 admonition titles in ${files.length} changed file(s).`);
+ process.exit(0);
+ }
+
+ // `::error` puts each one on the offending line in the Files changed
+ // tab and prints it in red in the log, so the failure is not something
+ // to go hunting for. The message leads with the fix because the found
+ // text starts with `:::`, which reads badly right after the delimiter.
+ for (const { file, line, text } of findings) {
+ const fix = 'Wrap the title in brackets, for example :::note[My Title]';
+ console.log(`::error file=${file},line=${line},title=MDX v1 admonition title::${fix}%0A%0AFound: ${text}`);
+ }
+ process.exit(1);
+ JS
diff --git a/.github/workflows/actions/check-translations/action.yml b/.github/workflows/actions/check-translations/action.yml
new file mode 100644
index 00000000000..3e53a643597
--- /dev/null
+++ b/.github/workflows/actions/check-translations/action.yml
@@ -0,0 +1,20 @@
+name: 'Check Translations'
+description: 'Validates the translated locales without building them'
+runs:
+ using: 'composite'
+ steps:
+ # Surfaces failures unique to a translated locale, such as duplicate
+ # translation keys, while the changes are still in review. Previews only
+ # build the default locale, so translated locale issues would not surface
+ # until after merging into main.
+ #
+ # The sidebars reference the native and CLI docs, which are generated rather
+ # than committed, so those have to exist before the translations can be
+ # extracted.
+ - name: 🇯🇵 Extract Translations
+ shell: bash
+ run: |
+ trap 'rm -rf i18n' EXIT
+ node scripts/native.mjs
+ node scripts/cli.mjs
+ npx docusaurus write-translations --locale ja
diff --git a/.gitignore b/.gitignore
index a1ae05b6ea1..37f55c23bec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,8 @@
# Generated files
.docusaurus
.cache-loader
+.eslintcache
+.cspellcache
src/components/page/reference/ReleaseNotes/release-notes.json
# Misc
diff --git a/.prettierignore b/.prettierignore
index e523352d6cd..90a6a6c2be7 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,13 +1,29 @@
-src/theme/DocItem
-src/theme/DocRoot
-legacy-stencil-components
-scripts/bak
+# Ejected components keep upstream's formatting so they stay diffable against
+# @docusaurus/theme-classic. Refer to `src/theme/README.md`.
+# Wrapped components are our own code, so they follow the repo's formatting.
+src/theme/DocItem/Layout/index.tsx
+src/theme/EditMetaRow/index.tsx
+src/theme/Icon/DarkMode/index.tsx
+src/theme/Icon/Edit/index.tsx
+src/theme/Icon/LightMode/index.tsx
+src/theme/Icon/Language/index.tsx
+src/theme/Layout/index.tsx
+src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx
+src/theme/prism-include-languages.ts
-docs/api
+
+# Auto-generated files
docs/native
versioned_docs/version-v*/native
docs/cli/commands
-docs/reference/glossary.md
+versioned_docs/version-v*/cli/commands
+
+# Archived versions
+versioned_docs/version-v5
+versioned_docs/version-v6
+versioned_docs/version-v7
+static/usage/v6
+static/usage/v7
static/code/stackblitz
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 00000000000..2b532afe4ce
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,11 @@
+/**
+ * Prettier configuration for the docs site.
+ */
+
+const ionicConfig = require('@ionic/prettier-config');
+
+module.exports = {
+ ...ionicConfig,
+ // Override the trailingComma setting to avoid trailing commas in function arguments and JSX props.
+ trailingComma: 'es5',
+};
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6f589964046..a009111539f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,17 +8,23 @@ Thanks for your interest in contributing to Ionic's documentation! :tada: Check
- [Development Workflow](#development-workflow)
- [Previewing Changes](#previewing-changes)
+ - [Checking Links](#checking-links)
- [Linting Documentation](#linting-documentation)
- [Spell Check](#spell-check)
+ - [Heading IDs](#heading-ids)
- [Using VS Code on Windows](#using-vs-code-on-windows)
- [Project Structure](#project-structure)
- [Directories](#directories)
- [Authoring Content](#authoring-content)
+ - [Admonitions](#admonitions)
+ - [Links and Headings](#links-and-headings)
+ - [Playgrounds](#playgrounds)
- [Reference Content](#reference-content)
- [Translation](#translation)
- [Reporting Issues](#reporting-issues)
- [Pull Request Guidelines](#pull-request-guidelines)
- [Deploying](#deploying)
+ - [Archiving a Version](#archiving-a-version)
- [License](#license)
---
@@ -27,16 +33,62 @@ Thanks for your interest in contributing to Ionic's documentation! :tada: Check
### Previewing Changes
-In order to run the documentation locally, install the dependencies and run the development server:
+In order to run the documentation locally, use Node.js 24 or later, install the dependencies and run the development server:
```sh
-npm install
+npm ci
npm start
```
+#### GitHub Token
+
+The documentation build requires a GitHub Personal Access Token to fetch Ionic Framework release notes. The build still works locally without it, with an empty release notes page, but Vercel preview and production builds fail without it.
+
+**Local Development:**
+
+1. Create a [fine-grained Personal Access Token](https://github.com/settings/personal-access-tokens/new) with:
+
+ - **Repository access**: Public repositories (read-only)
+ - **Expiration**: 366 days (update annually)
+
+2. Add the token to your shell profile (`~/.zshrc`, `~/.bashrc`, etc.):
+
+ ```sh
+ export GITHUB_TOKEN=github_pat_...
+ ```
+
+3. Reload your shell or run `source ~/.zshrc` (or equivalent)
+
+**Vercel:**
+
+1. Create a [fine-grained Personal Access Token](https://github.com/settings/personal-access-tokens/new) with the same settings as above, but with:
+
+ - **Owner**: ionic-team organization (not your personal account)
+
+2. Add the token to Vercel project settings:
+
+ - Go to your project on Vercel
+ - Navigate to **Settings → Environment Variables**
+ - Add `GITHUB_TOKEN` with the token value
+ - Select Production and Preview environments
+
+3. Redeploy the project for the token to take effect
+
+If the token is missing, Vercel builds fail with `GITHUB_TOKEN environment variable is required.`
+
+### Checking Links
+
+The development server does not check for broken links or anchors. Only a build does, and it fails on any it finds. Build the site before pushing a change that adds or moves links or headings:
+
+```sh
+npm run build:preview
+```
+
+This builds the English site only, the same build as a Vercel preview.
+
### Linting Documentation
-This repository uses [Prettier](https://prettier.io/), an opinionated code formatter, in order to keep consistent formatting throughout the documentation. Run the following command to automatically fix all formatting, and then push any changes:
+This repository uses [ESLint](https://eslint.org/) to catch markup the build cannot check, such as raw links and headings and misaligned JSDoc comments, and [Prettier](https://prettier.io/), an opinionated code formatter, to keep consistent formatting throughout the documentation. Run the following command to report ESLint errors and automatically fix all formatting, and then push any changes:
```
npm run lint
@@ -62,17 +114,17 @@ npm run spellcheck
- A **directory** or anything matching a **regular expression**, update the following file: `cspell.json`
- For example, we don't want to flag anything inside of code ticks (`) or code blocks (```), so there are regular expressions added to ignore anything inside of these.
- An **entire line**, add the following comment above it:
- ```markdown
-
+ ```mdx
+ {/* cspell:disable-next-line */}
```
- **Multiple lines**, add comments above and below the lines to be ignored:
- ```markdown
-
+ ```mdx
+ {/* cspell:disable */}
-
Everything inside of these comments will be ignored by the spell checkr. Proofread your own words carefully.
+Everything inside of these comments will be ignored by the spell checker. Proofread your own words carefully.
- + {/* cspell:enable */} ``` > [!IMPORTANT] @@ -87,11 +139,25 @@ Comments disabling the next line or entire sections of documentation are useful In general, we should try to avoid ignoring words unless they are technical terms that are used throughout the documentation and wouldn't necessarily make sense formatted as code. +### Heading IDs + +Every heading in `docs/` needs an explicit ID, so that renaming the heading doesn't change its anchor and break links to it: + +```mdx +## Basic Usage {/* #basic-usage */} +``` + +Run the following command to add IDs to any new headings, and then push the changes. CI fails if a heading is missing one. + +``` +npm run heading-ids +``` + --- ## Using VS Code on Windows -The Ionic docs were originally built in a Mac-based environment, so Mac-focused linting rules apply when committing changes. To contribute on Windows, do the following: +Prettier expects LF line endings, and CI fails if `npm run lint` changes any file. To contribute on Windows, do the following: - Configure VS Code to read/save files using line breaks (LF) instead of carriage returns (CRLF). Set it globally by navigating to: Settings -> Text Editor -> Files -> Eol. Set to `\n`. - Check that the Git setting `core.autocrlf` is set to `false`: run `git config -l | grep autocrlf`. Switch it to false using: `git config --global core.autocrlf false`. @@ -103,14 +169,19 @@ Ionic's documentation is built using [Docusaurus](https://docusaurus.io/). The c ### Directories +- `_templates/` - templates used by `npm run playground:new` +- `docs/` - content of the current version of the docs +- `plugins/` - local Docusaurus plugins, such as the one that generates the component API pages - `scripts/` - build scripts used to generate markdown or json files -- `src/` - source code and content of the docs +- `src/` - source code of the site - `components/` - components used across the site - `global/` - components used globally - `page/` - components used on a single page or in a limited scope - `styles/` - global styles and variables - `components/` - styles split out into the components they target + - `theme/` - Docusaurus theme components that have been swizzled - `static/` + - `code/` - StackBlitz project templates used by the playgrounds - `demos/` - self-contained demos, optionally presented by pages via `demoUrl` YAML frontmatter - `usage/` - playgrounds that can be created by running `npm run playground:new` [(docs)](_templates/README.md#new-playground-template) - `versioned_docs/` - versions of the docs created by the docusaurus versioning command @@ -121,22 +192,81 @@ Ionic's documentation is built using [Docusaurus](https://docusaurus.io/). The c The content of the Ionic docs is written as [Markdown](https://commonmark.org/) in `docs/`. Each Markdown file corresponds to a route unless explicitly changed in the frontmatter. ``` -/docs/ => src/pages/index.md -/docs/intro/cli => src/pages/intro/cli.md -/docs/theming/advanced => src/pages/theming/advanced.md -/docs/theming => src/pages/theming.md +/docs => docs/index.mdx +/docs/intro/cli => docs/intro/cli.mdx +/docs/theming/basics => docs/theming/basics.mdx +/docs/v8/intro/cli => versioned_docs/version-v8/intro/cli.mdx +``` + +`/docs` maps to `docs/index.mdx` through `slug: /` in its frontmatter. Older versions live in `versioned_docs/` and are served under their version, such as `/docs/v8/`. + +Versions listed in [`versions.json`](versions.json) are actively maintained. If your change also applies to one of them, make the same change in its `versioned_docs/version-Accordions provide collapsible sections in your content to reduce vertical space while providing a way of organizing and grouping information.
-Action Sheets display a set of options with the ability to confirm or cancel an action.
-Alerts are a great way to offer the user the ability to choose a specific action or list of actions.
-Badges are a small component that typically communicate a numerical value to the user.
-Breadcrumbs are navigation items that are used to indicate where a user is on an app.
-Buttons let your users take action. They're an essential way to interact with and navigate through an app.
-- Cards are a great way to display an important piece of content, and can contain images, buttons, text, and more. -
-Checkboxes can be used to let the user know they need to make a binary decision.
-Chips are a compact way to display data or actions.
-Content is the quintessential way to interact with and navigate through an app.
-Date & time pickers are used to present an interface that makes it easy for users to select dates and times.
-Floating action buttons are circular buttons that perform a primary action on a screen.
-The grid is a powerful mobile-first system for building custom layouts.
-Beautifully designed icons for use in web, iOS, and Android apps.
-Infinite scroll allows you to load new data as the user scrolls through your app.
-Inputs provides a way for users to enter data in your app.
-- Items are elements that can contain text, icons, avatars, images, inputs, and any other native or custom elements. - Items can be swiped, deleted, reordered, edited, and more. -
-Lists can display rows of information, such as a contact list, playlist, or menu.
-- A collection of media components, including avatars, icons, images, and thumbnails, designed to enhance visual - content. -
-Menus are a common navigation pattern. They can be permanently on-screen, or revealed when needed.
-Modals slide in and off screen to display a temporary UI and are often used for login or sign-up pages.
-Navigation is how users move between different pages in your app.
-Popover provides an easy way to present information or options without changing contexts.
-Progress indicators visualize the progression of an operation or activity.
-Radio inputs allow you to present a set of exclusive options.
-Range sliders let users select a value by dragging a knob along a track.
-Refresher provides pull-to-refresh functionality on a content component.
-Reorder lets users drag and drop to reorder a list of items.
-Routing allows navigation based on the current path.
-Searchbar is used to search or filter items, usually from a toolbar.
-Segments provide a set of exclusive buttons that can be used as a filter or view switcher.
-Select is similar to the native HTML select, with a few improvements to sorting and selecting.
-Tabs enable tabbed navigation, a standard navigation pattern in modern apps.
-Toasts are subtle notifications that appear over your app's content without interrupting user interaction.
-Toggles are an input for binary options, often used for options and switches.
-Toolbars are used to house information and actions relating to your app.
-Text is used to style or change the color of text within an application.
-Accordions provide collapsible sections in your content to reduce vertical space while providing a way of organizing and grouping information.
+Action Sheets display a set of options with the ability to confirm or cancel an action.
+Alerts are a great way to offer the user the ability to choose a specific action or list of actions.
+Badges are a small component that typically communicate a numerical value to the user.
+Breadcrumbs are navigation items that are used to indicate where a user is on an app.
+Buttons let your users take action. They're an essential way to interact with and navigate through an app.
+Checkboxes can be used to let the user know they need to make a binary decision.
+Chips are a compact way to display data or actions.
+Content is the quintessential way to interact with and navigate through an app.
+Date & time pickers are used to present an interface that makes it easy for users to select dates and times.
+Floating action buttons are circular buttons that perform a primary action on a screen.
+The grid is a powerful mobile-first system for building custom layouts.
+Beautifully designed icons for use in web, iOS, and Android apps.
+Infinite scroll allows you to load new data as the user scrolls through your app.
+Inputs provide a way for users to enter data in your app.
+Lists can display rows of information, such as a contact list, playlist, or menu.
+Menus are a common navigation pattern. They can be permanently on-screen, or revealed when needed.
+Modals slide in and off screen to display a temporary UI and are often used for login or sign-up pages.
+Navigation is how users move between different pages in your app.
+Popover provides an easy way to present information or options without changing contexts.
+Progress indicators visualize the progression of an operation or activity.
+Radio inputs allow you to present a set of exclusive options.
+Range sliders let users select a value by dragging a knob along a track.
+Refresher provides pull-to-refresh functionality on a content component.
+Reorder lets users drag and drop to reorder a list of items.
+Routing allows navigation based on the current path.
+Searchbar is used to search or filter items, usually from a toolbar.
+Segments provide a set of exclusive buttons that can be used as a filter or view switcher.
+Select is similar to the native HTML select, with a few improvements to sorting and selecting.
+Tabs enable tabbed navigation, a standard navigation pattern in modern apps.
+Toasts are subtle notifications that appear over your app's content without interrupting user interaction.
+Toggles are an input for binary options, often used for options and switches.
+Toolbars are used to house information and actions relating to your app.
+Text is used to style or change the color of text within an application.
+