# Technical Documentation: elastic/eui

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/elastic/eui)

### Overview (README.md)

<img src="https://repository-images.githubusercontent.com/107422373/b6180480-a1d7-11eb-8a3c-902086232aa7" alt="" />

# Elastic UI Framework

**The Elastic UI Framework is a collection of React UI components for quickly building user interfaces at Elastic.**

Check out our [full documentation site][docs] which contains many examples of components in the EUI framework aesthetic, and how to use them in your products. Our FAQ below covers common usage questions — for other general questions regarding EUI, check out the [Discussions tab](https://github.com/elastic/eui/discussions).

## Frequently Asked Questions

### What is the Elastic UI Framework?

The Elastic UI Framework (EUI) is a design library in use at Elastic to build React applications that need to share our branding and aesthetics. It distributes typed UI React components and static assets for use in building web layouts. Alongside the React components, we ship theme & style utilities that can be used independently on their own.

The primary goal of this library is to provide reusable UI components that can be used throughout Elastic's web products. As React components, they remove CSS from the process of building UIs. As a single source of truth, the framework allows our designers to make changes to our aesthetic directly in the code. And unit test coverage for the UI components allows us to deliver a stable "API for user interfaces".

### Can I use EUI?

Please see Elastic's licensing FAQ: [I’m using EUI or Elastic Charts in my application outside of Kibana, how does this affect me?][licensing-faq]

### Why is EUI open source?

Many of Elastic's products are open source and rely upon this library to function. The Elastic UI Framework began as a folder of code in Kibana and we decided it could be used beyond that codebase. It exists as an independent library so that patterns can be shared across teams and design standards can be scaled across our organization. Since most of our products are open source, we treat this one similarly as far as public publishing and conversation even if its usage tends to focus more inward towards Elastic itself.

### What is the versioning, release, and upgrade strategy?

We use [semver](https://semver.org/) for versioning and use that to denote breaking changes in EUI upgrades. Traditionally we consider API changes in our prop names or existing component functionality to be a reason for a breaking change, but do not track the renaming of CSS selectors, mixins or other style changes under this same rigor.

Traditionally releases are made weekly against whatever is in the `main` branch and you can upgrade from NPM as you see fit.

### Can I contribute to EUI?

External contributors may only open PRs for issues labeled [**help wanted**](https://github.com/elastic/eui/labels/help%20wanted). See [Contributing to EUI](wiki/contributing-to-eui/) for the full policy.

### What about reporting bugs and feature requests?

Bug reports and feature requests are most welcome, but our roadmap and prioritization are driven primarily by internal Elastic usage.

Please note that in order to keep our backlog manageable and focused on tasks we intend to complete, feature requests & tech debt issues that are inactive for a year will be auto-closed (bugs will remain open if determined to be reproducible and valid).

This activity counter can be soft reset by commenting on the issue directly, but please do so mindfully. We would ask that you proactively let the EUI team know why this request matters to you or how it impacts you or your users, in order to help us prioritize accordingly.

The EUI team, like everyone else, has a finite amount of time and resources, and it is not humanly possible for us to implement every task or feature requested of us. If you want to contribute a fix, see [Can I contribute to EUI?](#can-i-contribute-to-eui).

### I have more questions!

The EUI team has ongoing FAQs for more transient or component-specific questions. [Please see the FAQ section in our GitHub discussions here](https://github.com/elastic/eui/discussions/categories/faq).

## Wiki

Our wiki docs contain instructions and guidelines on multiple areas of EUI usage and development that are too detailed for an initial README. For more information, see:

- [Consuming EUI](wiki/consuming-eui)
- [Contributing to EUI](wiki/contributing-to-eui/)
- [Running EUI locally](wiki/contributing-to-eui/running-eui-locally.md)

## License

[Dual-licensed under Elastic v2 and Server Side Public License, v1][license]. See Elastic's [licensing FAQ][licensing-faq] for details.

[license]: LICENSE.txt
[licensing-faq]: https://www.elastic.co/pricing/faq/licensing#im-using-eui-or-elastic-charts-in-my-application-outside-of-kibana-how-does-this-affect-me
[docs]: https://elastic.github.io/eui/

---

### Consuming Eui README (`wiki/consuming-eui/README.md`)

# Consuming EUI

## Installation

To install the Elastic UI Framework into an existing project, use the `yarn` CLI (`npm` is not supported).

```bash
yarn add @elastic/eui
```

Note that EUI has [several `peerDependencies` requirements](../../packages/eui/package.json) that will also need to be installed if starting with a blank project.

```bash
yarn add @elastic/eui @elastic/eui-theme-borealis @elastic/datemath @emotion/react @emotion/css moment
```

## Requirements and dependencies

EUI also has `moment` and `@elastic/datemath` as dependencies itself. These are already loaded in most Elastic repos, but make sure to install them if you are starting from scratch.

## What's available

EUI publishes React UI components, JavaScript helpers called services, and utilities for writing Jest tests. Please refer to the [Elastic UI Framework website](https://eui.elastic.co) for comprehensive info on what's available.

EUI is published through [NPM](https://www.npmjs.com/package/@elastic/eui) as a dependency.

### Components

You can import React components from the top-level EUI module.

```js
import {
  EuiButton,
  EuiCallOut,
  EuiPanel,
} from '@elastic/eui';
```

### Test

Test utilities are published from the `lib/test` directory.

```js
import { findTestSubject } from '@elastic/eui/lib/test'; // Enzyme
import { findByTestSubject, render, screen } from '@elastic/eui/lib/test/rtl'; // React Testing Library
```

### Custom styles

EUI uses a CSS-in-JS approach for styling, specifically [Emotion](https://emotion.sh) library. We recommend using the `css` function (read more [here](https://emotion.sh/docs/css-prop#use-the-css-prop)) from `@emotion/react`, which automatically sets the generated `className` and combines all passed styles into a single ruleset. To enable `css` concatenation, you'll need the [Babel preset](https://www.npmjs.com/package/@emotion/babel-preset-css-prop).

You can find more information regarding Emotion usage with EUI [here](https://github.com/elastic/eui/discussions/6828).

### Theming

EUI leverages [Emotion](https://emotion.sh) for its theming as well. As such, we require an `<EuiProvider>` wrapper around your application in order for various theme-related UI & UX (such as dark/light mode switching) to work as expected.

```jsx
import React from 'react';

import { EuiProvider, EuiText } from '@elastic/eui';

const MyApp = () => (
  <EuiProvider>
    <EuiText><p>Hello World!</p></EuiText>
  </EuiProvider>
);

export default MyApp;
```

#### Consuming theme tokens

Using EUI's theme layer with Emotion is [documented in our docs](https://eui.elastic.co/docs/getting-started/theming/theme-provider) and should cover the majority of your theming needs.

```jsx
import { useEuiTheme } from '@elastic/eui';
import { css } from '@emotion/react';

export default () => {
  const { euiTheme } = useEuiTheme();
  const styles = css`
    color: ${euiTheme.colors.primary};
    border: ${euiTheme.border.thin};
    padding: ${euiTheme.size.s};
  `;
  return (
    <div css={styles} />
  );
};
```

### "Module build failed" or "Module parse failed: Unexpected token" error

If you get an error when importing a React component, you might need to configure Webpack's `resolve.mainFields` to `['webpack', 'browser', 'main']` to import the components from `lib` instead of `src`. See the [Webpack docs](https://webpack.js.org/configuration/resolve/#resolve-mainfields) for more info.

## Using the `test-env` build

EUI provides a separate babel-transformed and partially mocked commonjs build for testing environments in consuming projects. The output is identical to that of `lib/`, but has transformed async functions and dynamic import statements, and also applies some useful mocks. This build mainly targets Kibana's Jest environment, but may be helpful for testing environments in other projects.

### Mapping to the `test-env` directory

In Kibana's Jest configuration, the `moduleNameMapper` option is used to resolve standard EUI import statements with `test-env` aliases.

```js
moduleNameMapper: {
  '@elastic/eui$': '<rootDir>/node_modules/@elastic/eui/test-env'
}
```

This eliminates the need to polyfill or transform the EUI build for an environment that otherwise has no need for such processing.

### Mocked component files

Besides babel transforms, the test environment build consumes mocked component files of the type `src/**/[name].testenv.*`. During the build, files of the type `src/**/[name].*` will be replaced by those with the `testenv` namespace. The purpose of this mocking is to further mitigate the impacts of time- and import-dependent rendering, and simplify environment output such as test snapshots. Information on creating mock component files can be found with [testing documentation](../contributing-to-eui/testing/unit-testing.md#writing-mock-component-files).

## Using the `optimize` build (Beta)

The `optimize` output directory is an opt-in intermediate step as we work towards dedicated, formal build output for development and production environments.

When compiling with webpack, use the `resolve.alias` configuration to target the desired directory:

```json
resolve: {
  alias: {
    '@elastic/eui$': '@elastic/eui/optimize/lib'
  }
}
```

Designated "Beta" as included babel plugins may change and the output directory is likely to be renamed.

### Notable differences

* Absence of `propTypes`
  * Significant bundle size decrease
  * Likely not suitable for development environments
* Runtime transforms
  * Slight bundle size decrease
  * Requires `@babel/runtime` be a consumer dependency

---

### Contributing To Eui README (`wiki/contributing-to-eui/README.md`)

# Contributing to EUI

🙌 Thanks for your interest in contributing to EUI! 🙌

We welcome and encourage contributions.

However, because EUI has a large footprint in Elastic products, we must maintain a high standard of quality and due diligence for contributions. The guidance below outlines our expectations. **While we'd hate to turn away any contribution, PRs that deviate from this guidance will most likely be rejected.**

## Who can contribute

- **Elastic employees** — EUI is built primarily for Elastic products; maintainers prioritize internal roadmap work first. If your need isn't currently a priority, feel free to contribute the solution yourself.
- **Community** — Outside contributions are welcome and merged on a **best-effort** basis.

## What to contribute

External contributors may only open PRs for issues labelled [`help wanted`](https://github.com/elastic/eui/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22). We add that label when a task fits our roadmap and it has been prepared with clear instructions.

If you are having a problem with EUI, [file an issue](https://github.com/elastic/eui/issues/new).

If you want to contribute a fix for an issue that affects you, comment on that issue with a proposed solution. We can discuss it there. If we agree, we will add the `help wanted` label.

## What not to contribute

Unless agreed upon previously:

- **Large or core roadmap work** — Often handled internally so architecture, accessibility, and downstream coordination stay aligned.
- **Style or design changes** — These require alignment with design teams at Elastic.
- **High-impact changes** - Even small code changes can have a large impact on Kibana, requiring significant testing and review.

## How to contribute

We do not assign issues to community members. Comment on the `help wanted` issue before you start so others know you are working on it.

## Typical change flow

A typical contribution moves through these steps:

1. **Set up locally** — see [Running EUI locally](./running-eui-locally.md).
2. **Make your changes** — follow the [Developing](./developing/README.md) guidelines for component structure, props, refs, icons, and Emotion styles.
3. **Update docs** — add or update the corresponding page in `packages/website` per [Documenting](./documenting/README.md).
4. **Write tests** — at minimum unit tests; see [Testing](./testing/README.md) for the full stack.
5. **Add a changelog** — see [Changelogs](./documenting/changelogs.md) for when one is required.
6. **Verify locally** — run lint and the relevant test commands (see [Verifying your change](#verifying-your-change)).
7. **Open a PR** — fill in the [PR template](/.github/pull_request_template.md) and add any [labels](#pr-labels) that apply.

## Naming at a glance

EUI uses different naming conventions for different artifacts. Full details live in the linked docs:

| Artifact | Convention | Defined in |
| --- | --- | --- |
| Component source folders & files | `snake_case` | [Creating component files](./developing/creating-component-files.md) |
| Component class/function name | `EuiPascalCase` | [Creating component files](./developing/creating-component-files.md) |
| Doc page paths (Docusaurus URLs) | `kebab-case` | [Writing documentation](./documenting/writing-documentation.md) |
| Doc page & section titles | Sentence case | [Documenting](./documenting/README.md) |
| Component references in prose | `<strong>EuiFoo</strong>` (with `Eui` prefix) | [Documenting](./documenting/README.md) |
| Commit / PR title | `[Component] Short description` | [Commit messages](#commit-messages) |

## Pull requests

- **Use this wiki** — [Developing](./developing/README.md), [Documenting](./documenting/README.md), [Testing](./testing/README.md).
- **Keep PRs small** — Prefer **[atomic commits and focused PRs](https://learning-notes.mistermicheels.com/processes-techniques/small-commits-pull-requests/)** (one concern per commit and per PR when you can).
- **Review timing** — We aim to respond within **about a week**.
- **Concurrency** — Please limit open PRs so review stays focused.
- **Due diligence** — Follow the [PR template](/.github/pull_request_template.md) (summary, impact, screenshots, checklists, QA notes).
- **Reviewers** — Code ownership is defined in [`CODEOWNERS`](/CODEOWNERS); the right teams will be auto-requested based on the paths you touch.
- **Draft PRs** — We don’t review drafts by default. When you want feedback or help, **comment and ping `@eui-team`** (same idea as the note at the top of the PR template).

## Commit messages

We do not enforce a commit naming convention but it's customary to use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/).

PRs typically follow the pattern: `[ComponentName] Short description (#PR)`, e.g. `[EuiBanner] Adjust additional content spacing`. When merging, we squash all commits and the `main` commit message is the PR title. The `(#PR)` suffix is appended automatically.

## PR labels

A few labels carry behavior beyond categorization:

- `skip-changelog` — bypasses the CI changelog check for all packages. See [Changelogs](./documenting/changelogs.md) for when this is acceptable.
- `skip-changelog-<package-name>` — bypasses the check for a single package only (e.g. `skip-changelog-eslint-plugin-eui`).
- `breaking change` — required for PRs introducing breaking changes; triggers an automated comment with extra due-diligence steps for the Kibana upgrade.

## Verifying your change

From `packages/eui` (unless noted):

- `yarn lint` — ESLint + type checking
- `yarn test-unit` — Jest unit tests (add `--watch` while iterating)
- `yarn test-cypress` — Cypress component tests
- A changelog entry in `packages/eui/changelogs/upcoming/<PR>.md` for any user-facing change — see the [changelog guide](./documenting/changelogs.md)

## Stale PRs

Inactive PRs (~**3 months**) may be closed by GitHub’s **[stale workflow](https://github.com/actions/stale)**.

- If **we** owe review, ping us to get things moving again.
- If **you** owed changes and the PR auto-closed, we may push to your branch or close it and continue in a new PR based on your work.

---

### Contributing To Eui Designing README (`wiki/contributing-to-eui/designing/README.md`)

# Design System Synchronization Guidelines
When submitting code changes that affect the visual design, behavior, or properties of EUI components or tokens, it's critical to ensure the [Elastic UI Borealis](https://www.figma.com/design/FHys7gLzyvD1gc9DrJM6D8/Elastic-UI--Borealis-?m=auto) Figma library remains synchronized with the codebase. This maintains design-development consistency across the entire Elastic ecosystem.

## When Figma Updates Are Required
Code changes that impact design and require Figma library updates include:

- *Component visual changes:* Styling modifications, color updates, spacing adjustments, typography changes
- *New component creation:* Following the four-step component creation process
- *Props modifications:* Adding, removing, or changing component properties that affect visual output
- *Icon additions/changes:* New icons or modifications to existing ones per icon creation guidelines
- *Design token updates:* Changes to colors, spacing, typography, or other design tokens
- *Behavioral changes:* Interactions, states, or animations that alter user experience

## Design Review Process

1. Contact the design colleague in your team who can support you throughout the process, if needed.
2. Create a new Figma branch in the [Elastic UI Borealis](https://www.figma.com/design/FHys7gLzyvD1gc9DrJM6D8/Elastic-UI--Borealis-?m=auto) library that includes the proposed changes and links to the related PR.
3. Request a design review in Figma using the built-in workflow, or share the branch in the #eui-design Slack channel.

---

### Contributing To Eui Developing README (`wiki/contributing-to-eui/developing/README.md`)

# Component development & architecture

Before working with EUI components or creating new ones, you will want to [run a local development server](../running-eui-locally.md). EUI has two complementary local servers:

- **Storybook** at [http://localhost:6006/](http://localhost:6006/) — the recommended environment for component development.
- **Docusaurus website** at [http://localhost:3000/](http://localhost:3000/) — the consumer-facing documentation site.

Both servers watch for source changes and recompile automatically.

## Component creation

There are four steps to creating a new component:

1. Create the React portion of the component
    - See [Component file & folder architecture](./creating-component-files.md) for more detailed steps on how to spin up new files
2. Create the styles
    - See [Writing styles with Emotion](./writing-styles-with-emotion.md)
3. Write tests
    - All components should have at minimum [unit tests](../testing/unit-testing.md)
    - For more, see the dedicated [testing wiki docs](../testing/)
4. Document it with examples in `packages/website`
    - See the dedicated [documentation wiki guidelines](../documenting/)

## Component patterns

We use a number of patterns and conventions throughout our components for naming, [props](./props.md), [refs](./refs.md), and [icons](./creating-icons.md) that should be followed whenever possible.

---

### Contributing To Eui Documenting README (`wiki/contributing-to-eui/documenting/README.md`)

# Documentation guidelines

Always remember to update the [documentation site](https://eui.elastic.co/) in the `packages/website` folder and [add a changelog](./changelogs.md) in the same PR that contains functional changes. We do this in tandem to prevent our examples from going out of sync with the actual components. In this sense, treat documentation no differently than how you would treat tests.

The complexity of the component should determine how many examples you need to create, and how complex they should be. In general, your examples should demonstrate:

* The most common use-cases for the component.
* How the component handles edge cases, e.g. overflowing content, text-based vs. element-based content.
* The various states of the component, e.g. disabled, selected, empty of content, error state.

Refer to [Writing documentation](./writing-documentation.md) for information on the process of documenting components.

## Formatting & writing style

Here are our formatting guidelines for writing documentation:

- Use sentence case, always, for page and section titles. Example: `This component does something`
- Component names:
  - When referencing the component name, wrap it in `<strong>` tags. Example: `<strong>EuiComponent</strong>`
  - When referencing the component name, always include the `Eui` prefix unless you are referencing the generic term. Example: `EuiFlyout` vs `flyout`
- Code syntax:
  - Wrap references to prop names and elements in code blocks. Example: \`propName\`

---

### Contributing To Eui Testing README (`wiki/contributing-to-eui/testing/README.md`)

# Testing EUI components

All components should have, at minimum, unit tests for each prop.

## Test stack at a glance

- **[Jest unit tests](./unit-testing.md)** — required for every component. New tests should be written with [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/); legacy [Enzyme](https://enzymejs.github.io/enzyme/) tests still exist and are being migrated.
- **[Cypress component tests](./cypress-testing.md)** — optional, used for complex components or where real-browser DOM and interactions are needed.
- **Storybook** — the component development environment and the source of stories used by visual regression testing.
- **[Visual regression tests](./visual-regression-testing.md)** — Playwright + `jest-image-snapshot` against Storybook stories, run on every pull request.
- **[EUI test helpers](./eui-test-helpers.md)** — Playwright validation tests for `@elastic/eui-test-helpers`, run on every pull request with flake detection when a component changes.

## Code coverage

Code coverage is a tool intended to help devs quickly find lines/branches that still need to be covered and determine test cases to write. EUI does not enforce a code coverage threshold in CI; reports are generated on demand for local inspection.

### Jest coverage reports

Jest code coverage reports can be generated by running `yarn test-unit` with the `--coverage` flag. Generated HTML reports are output to the `reports/` folder.

To view the reports, you can either drag the `reports/jest-coverage/index.html` file into a browser window, or in a terminal, run `open reports/jest-coverage/index.html` from the EUI project root.

### Cypress coverage reports

Cypress has been configured to automatically output Cypress code coverage to the `reports/cypress-coverage` folder. If you would prefer to turn this off locally, you can add the `--env coverage=false` flag when running your your cypress commands.

To view the reports, you can either drag the `reports/cypress-coverage/index.html` file into a browser window, or in a terminal, run `open reports/cypress-coverage/index.html` from the EUI project root.

### Combined Jest & Cypress coverage reports

If you're working on a component that has both Cypress and Jest tests, we have a command that allows you to combine the results of both coverage reports.

1. Setup: On the component(s) you're looking for final coverage #s for,
  - Ensure you have already run `yarn test-unit --coverage` to generate a Jest report
  - Ensure you have already run `yarn test-cypress` to generate a Cypress report
2. Run `yarn combine-test-coverage`
  - This should automatically open a browser window with `reports/combined-coverage/index.html`

---

### Packages Website Docs Components Index (`packages/website/docs/components/index.mdx`)

---
sidebar_position: 1
---

# Overview

EUI offers a wide variety of components. This section is organized topically with individual pages containing live example, usage recommendations, guidelines, and props.

The adjacent [patterns](../patterns/index.mdx) section provides additional guidance for handling use cases that cross multiple components.

## Components by topic

- [Layout](./layout/flex/index.mdx)
- [Containers](./containers/accordion.mdx)
- [Navigation](./navigation/breadcrumbs.mdx)
- [Display](./display/badge/index.mdx)
- [Forms](./forms/layouts/usage.mdx)
- [Data grid](./data-grid/data-grid.mdx)
- [Tables](./tables/basic.mdx)
- [Templates](./templates/page-template/index.mdx)
- [Editors and syntax](./editors-and-syntax/markdown/format.mdx)

---

### Packages Website Docs Content Index (`packages/website/docs/content/index.mdx`)

---
sidebar_position: 1
---

# Overview

Our content guidelines cover the main principles we follow for crafting consistent, clear, and concise copy across Elastic products:

- [Voice and writing style](./style.mdx)
- [Tone](./adapt-tone.mdx)
- [Language](./language.mdx)
- [Accessibility](./accessibility.mdx)
- [Inclusivity](./inclusivity.mdx)
- [Word choice](./word-choice.mdx)

Some more specific guidelines and best practices apply in certain situations or for certain components:

- [Patterns](../patterns/index.mdx)
  - Find the right way to add help content to a UI: [Help content patterns](../patterns/help-content.mdx).
  - Write helpful [error messages](../patterns/error-messages/index.mdx).
- [Components](../components/index.mdx)

---

### Packages Website Docs Dataviz Index (`packages/website/docs/dataviz/index.mdx`)

---
sidebar_position: 1
---

import figmaDatavizConsistency from '!url-loader!./assets/dataviz_consistency.svg';
import figmaDatavizHierarchyOfInformation from '!url-loader!./assets/dataviz_hierarchy-of-information.svg';
import figmaDatavizSemantic from '!url-loader!./assets/dataviz_semantic.svg';
import figmaDatavizTitlesAndLabels from '!url-loader!./assets/dataviz_titles-and-labels.svg';
import figmaDatavizMultiPurposeCharts from '!url-loader!./assets/dataviz_multi-purpose-charts.svg';
import figmaDatavizTimeAxis from '!url-loader!./assets/dataviz_time-axis.svg';

# Overview

import VersionBadge from './version_badge';

<VersionBadge />

Elastic Charts ([github repository](https://github.com/elastic/elastic-charts), [storybook](https://elastic.github.io/elastic-charts/?path=/story/annotations-lines--x-continuous-domain&globals=theme:light)) is library of charts, a set of independent components that share a series of common rules in terms of style and behavior.
Moving past the concept of “library”, we consider this list of charts as a “system”, and with that we mean a series of elements that clearly belong to the same design environment, that are consistent with EUI and that are working in a much more cohesive and connected way, depending on each other instead of living on their own.

Please consider that the work described in this page is a long term goal that we are trying to achieve and therefore this material has to be considered a work-in-progress and might not reflect precisely the current state of the library.

---

## Consistency

It might sound simple, even trivial from some points of view, but the most important thing is that all charts should look like they belong to the same system. Charts should behave (link to interaction page) and look similar, there should be an overall shared aesthetic that is consistent among them and with EUI.
If charts, such as any other component, look different from the rest of elements they will be perceived as detached from the product and the whole user experience would be affected, this is why elements within charts follow the same set of rules of positioning, style and interaction.

<FigmaAsset
  url="https://www.figma.com/file/aOhpp2CK5tZTGxerdklavR/Elastic-Charts-as-a-Design-System-%5B220%5D?type=design&node-id=1713-24059&mode=design&t=k01qLYeiGwXgx47y-4"
  src={figmaDatavizConsistency}
  title="Library consistency."
/>

---

## Style

We consider the concept of style as not purely related to aesthetics. While we obviously know that appearance plays a crucial role in fruition of components, we prefer to approach this topic from the perspective of semantic and hierarchy of information. We focus on how we display information in order to convey meaning and data in a consistent way across the whole set of charts.

### Hierarchy of information

Labels on top of charts are a good example of this concept. Up until 8.11, charts such as pie charts and treemaps have been displaying information in a slightly confusing and conflicting way (left). Reading direction would suggest that the first information we display is the most important, while font-weight in communicating the opposite, giving the values a stronger visual role. The planned design update (right) reinforces these roles being redundant in both position and weight across these two elements.

<FigmaAsset
  url="https://www.figma.com/file/aOhpp2CK5tZTGxerdklavR/Elastic-Charts-as-a-Design-System-%5B220%5D?type=design&node-id=2301-2073&mode=design&t=k01qLYeiGwXgx47y-4"
  src={figmaDatavizHierarchyOfInformation}
  title="Hierarchy of information."
/>

### Semantic

When representing data, everything should have a meaning and every detail should be carefully considered in order to properly convey information. A good illustration of this approach is how axis labels are positioned next to gridlines consistently across charts.
Labels that describe passage of time (such as timestamps, dates or hours and minutes) are always positioned right next to the gridlines, suggesting that a specific portion of time starts from that specific point and proceeds from that.
Categorical labels (such as the name of a Country, or a specific data series), instead, are always centered on the element in order to directly associate the label with the referred element.

<FigmaAsset
  url="https://www.figma.com/file/aOhpp2CK5tZTGxerdklavR/Elastic-Charts-as-a-Design-System-%5B220%5D?type=design&node-id=1732-43337&mode=design&t=k01qLYeiGwXgx47y-4"
  src={figmaDatavizSemantic}
  title="Charts semantics."
/>

---

## Titles and labels

Titles and subtitles play a crucial role in describing what the user is supposed to see, they can guide and help our customers in understanding charts and their importance, both visually and semantically, is often underestimated. When too subtle they might disappear from the component failing in delivering information, when too strong they might visually interfere with the overall aesthetic balance being too prominent.

Few typologies of charts (e.g. Metric and Bullet) include, by design, their own title and subtitle while in other cases (e.g. line charts, barchart) that is not required. Both these cases should be consistent and should follow the same rules in order to have a cohesive visual appearance when placed next to each other.

<FigmaAsset
  url="https://www.figma.com/file/aOhpp2CK5tZTGxerdklavR/Elastic-Charts-as-a-Design-System-%5B220%5D?type=design&node-id=1732-45544&mode=design&t=k01qLYeiGwXgx47y-4"
  src={figmaDatavizTitlesAndLabels}
  title="titles and labels."
/>

---

## Dependencies among charts

In a system, differently from a library, charts should not live by themselves. The behavior that has been designed for bullet charts is a proof of that.

We are aware that our users might create very small charts and that our charts might be displayed on different monitors in a very wide variety of resolutions. In order to be sure that readability of data is always ensured, we designed a responsive behavior that not only takes in consideration how elements would be displayed within the chart (e.g. see truncation of titles) but also how that whole chart could switch to a simpler and more readable model in case of need.



---

## Multi-purpose charts

In data visualization you can often obtain the same representation with different approaches, or relying on different typologies of charts and the possibility to do that would be a good metric to define the flexibility of a system of charts. The following examples show how we can obtain the same exact representation coming from different starting points, especially when we don’t have a specific solution for a problem.

A good example would be a representation of the health status of a monitored environment, which we represent here with a heatmap and a barchart getting pretty similar results.

<FigmaAsset
  url="https://www.figma.com/file/aOhpp2CK5tZTGxerdklavR/Elastic-Charts-as-a-Design-System-%5B220%5D?type=design&node-id=1701-19998&mode=design&t=k01qLYeiGwXgx47y-4"
  src={figmaDatavizMultiPurposeCharts}
  title="Multi-purpose charts."
/>

---

## Time Axis

Most of the charts created within the Kibana environment are time-based and therefore we need an advanced way of displaying time so that we can accommodate most of the needs while at the same time providing all information about the context. Our axes are based on a two-levels organization that would provide information about time in a different degree of detail.

A first set of gridlines display the detailed set of time buckets while a higher one would help users understand the context, adding information about years, months or any measure upon that.

Timestamps are also automatically transformed into common ways of writing time such as hours and minutes instead of milliseconds.

<FigmaAsset
  url="https://www.figma.com/file/aOhpp2CK5tZTGxerdklavR/Elastic-Charts-as-a-Design-System-%5B220%5D?type=design&node-id=1732-43797&mode=design&t=k01qLYeiGwXgx47y-4"
  src={figmaDatavizTimeAxis}
  title="Time axis."
/>

---

### Packages Website Docs Patterns Index (`packages/website/docs/patterns/index.mdx`)

---
sidebar_position: 1
---

# Overview

Patterns are preferred solutions to specific user needs, ensuring consistency in design, behavior, and interaction.

## What are patterns?

Patterns offer practical solutions that can be applied repeatedly to address frequent design issues, ensuring alignment with our principles and guidelines. They serve as building blocks for creating consistent and cohesive user interfaces.

## How do patterns differ from guidelines?

**Guidelines** are best practices for EUI components that ensure consistency and quality.
They answer "how to use it correctly," providing usage instructions, do's and don'ts, accessibility guidelines, and best practices.

**Patterns** are reusable solutions combining components to solve design problems.
They answer "how to solve this problem," showing component combinations, layout, user flow, interaction, and code examples.


---


## Contributing

The content available here reflects collective insights and best practices. If you see opportunities for improvement or have new ideas, we encourage contributions. Your expertise helps ensure our design system remains relevant and user-focused.

Start by creating a discussion with the EUI team [here](https://github.com/elastic/eui/discussions).

---


## Additional patterns at elastic

We capture patterns specific to EUI here. For additional patterns and design guidelines specific to Kibana and Solutions, be sure to look for additional content on https://docs.elastic.dev/ (Elastic internal link).

---

### Packages Website Docs Components Tables Index (`packages/website/docs/components/tables/index.mdx`)

# Tables

Tables can get complicated very fast. EUI provides both opinionated and non-opinionated ways to build tables.

- **Opinionated high-level components:**
  - These high-level components remove the need to worry about constructing individual building blocks together. You simply arrange your data in the format it asks for.
  - [EuiBasicTable](./basic.mdx) handles mobile row selection, row actions, row expansion, and mobile UX out of the box with relatively simple-to-use APIs. It is best used with asynchronous data, or static datasets that do not need pagination/sorting.
  - [EuiInMemoryTable](./in-memory.mdx) has all the features that EuiBasicTable has, and additionally handles pagination, sorting, and searching the passed data out-of-the-box with relatively minimal APIs. It is best used with smaller synchronous datasets.
- **Non-opinionated building blocks:**
  - If your table requires completely custom behavior, you can use individual building block components like [EuiTable, EuiTableRow, EuiTableRowCell, and more](./custom.mdx) to do what you need.
  - Please note that if you go this route, you must han`dle your own data management as well as table accessibility and mobile UX.

---

### Packages Website Docs Patterns Error Messages Index (`packages/website/docs/patterns/error-messages/index.mdx`)

# Error messages

## What is an error?

An error happens when the system couldn’t do something it was trying to do.

There are lots of reasons why errors happen, but they’re not always obvious to the user. It could be because instructions were not clear, data is missing, or there are bugs in the application.

We should do everything we can to [help users to avoid errors](./help-users-avoid-errors.mdx). When an error occurs, we **must** tell the user. You should tell them exactly what went wrong, and any actions they can take to fix it.

Missing or badly written error messages can be frustrating, time consuming and difficult to recover from. They can also make the user believe the task is more complex than it is, and can give the impression that our product is low quality.

We have written guidance on [how to write good error messages](./how-to-write-good-error-messages.mdx).

### Primary errors

Primary errors are as bad as it gets. They block the user from completing the current task, and we can’t even show them the page they expected. For example, when a user does not have permission to view a page, error code 403. A primary error should redirect the user to an error page.

Read more about the [error page pattern](./error-page.mdx).

### Secondary errors

Secondary errors happen when there is an error which blocks the current task, but we can still show them the page they expected. For example, an API or cluster that is not responding, error code `504`. A secondary error should reload the page without the user losing any information, and display an error banner.

Read more about the [error banner pattern](./error-banners.mdx).

### Validation errors

Validation errors happen when the user enters information in a different format than expected, blocking the current task, error code `400`. Validation errors should reload the page without the user losing any information, display an error summary, and highlight any fields which caused errors.

Read more about the [validation errors pattern](./error-validation.mdx).

### Unrelated errors (Warnings)

Unrelated errors are warnings. They don’t impact the user right now, but they’re useful to know. For example, there may be an error in another part of the application, but it’s not blocking the current task.

Read more about the [error warning pattern](./error-warning.mdx).

## Error codes

When an error happens, there is usually an error code provided by the client (browser) or the server, which can help us to explain to the user what went wrong.

It can be tempting to just tell the user, ‘hey, error 504’. But, most users won’t know what that means. Rather than just quoting the error code, we should translate what it means to the user in plain language.

See examples for common error codes:
- [400: Bad request](./examples.mdx#400-bad-request)
- [401: Unauthorized](./examples.mdx#401-unauthorized)
- [403: Forbidden](./examples.mdx#403-forbidden)
- [404: Not found](./examples.mdx#404-not-found)
- [408: Request timeout](./examples.mdx#408-request-timeout)
- [410: Gone](./examples.mdx#410-gone)
- [429: Too many requests](./examples.mdx#429-too-many-requests)
- [500: Internal server error](./examples.mdx#500-internal-server-error)
- [502: Bad gateway](./examples.mdx#502-bad-gateway)
- [503: Service unavailable](./examples.mdx#503-service-unavailable)
- [504: Gateway timeout](./examples.mdx#504-gateway-timeout)
- [507: Insufficient storage](./examples.mdx#507-insufficient-storage)


You can read in-depth about all the different [client errors](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses) and [server errors](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses) on [MDN Web Docs](https://developer.mozilla.org/en-US/).

## Related patterns and documentation

- [Confirmation prompts](../../components/containers/modal/index.mdx#confirming-an-action)
- [Content patterns](../../content/index.mdx)

---

### Packages Website Docs Patterns Nested Drag And Drop Index (`packages/website/docs/patterns/nested-drag-and-drop/index.mdx`)

# Nested drag and drop

```mdx-code-block
import { EuiLink } from '@elastic/eui';
```

EUI exposes `EuiDraggable` and `EuiDroppable` components (see [documentation](../../components/display/drag-and-drop.mdx)), which are wrappers around <EuiLink href="https://github.com/hello-pangea/dnd" target="_blank">@hello-pangea/dnd</EuiLink>. While excellent for simple lists, `@hello-pangea/dnd` is heavy and has limitations such as not being able to move items between different levels of nesting.

For complex use cases like this, we recommend <EuiLink href="https://atlassian.design/components/pragmatic-drag-and-drop/about" target="_blank">Pragmatic drag and drop</EuiLink> by Atlassian. It is a performance-focused, flexible library that handles these scenarios efficiently.

The example below demonstrates a simplified version of Pragmatic's <EuiLink href="https://atlassian.design/components/pragmatic-drag-and-drop/examples/#tree" target="_blank">Tree pattern</EuiLink>, adapted to use EUI components and design tokens with enhanced keyboard navigation.

:::accessibility Accessibility

This example uses nested **EuiAccordion** components with roving tabindex to improve usability, similarly as in [Tree view pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/).

For complex trees, the recommended accessibility pattern is not to mimic mouse dragging with keys but provide a "Move" action. In this case, we use **EuiPopover** and **EuiContextMenu** composition inside the `extraAction` prop.
:::

:::warning Package versions

This pattern may work differently depending on which version of **@atlaskit/pragmatic-drag-and-drop** you use. Please check the versions used in our <EuiLink href="https://github.com/elastic/eui/blob/main/packages/website/package.json" target="_blank">package.json</EuiLink>.
:::

```bash
yarn add @atlaskit/pragmatic-drag-and-drop @atlaskit/pragmatic-drag-and-drop-hitbox
```

```mdx-code-block
import { css } from '@emotion/react';
import {
  EuiAccordion,
  EuiIcon,
  EuiPanel,
  EuiText,
  useEuiTheme,
} from '@elastic/eui';
import {
  draggable,
  dropTargetForElements,
  monitorForElements,
} from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
import {
  attachInstruction,
  extractInstruction,
} from '@atlaskit/pragmatic-drag-and-drop-hitbox/list-item';

import ExampleCode from '!!raw-loader!./example';
```

<Demo
  scope={{
    css,
    EuiAccordion,
    EuiIcon,
    EuiPanel,
    EuiText,
    useEuiTheme,
    draggable,
    dropTargetForElements,
    monitorForElements,
    combine,
    attachInstruction,
    extractInstruction,
  }}
>
  {ExampleCode}
</Demo>

---

### Packages Website Docs Patterns Severity Index (`packages/website/docs/patterns/severity/index.mdx`)

---
title: Health and Severity
sidebar_position: 6
---

```mdx-code-block
import { css } from '@emotion/react';
import { EuiButton, EuiButtonIcon, EuiIcon, EuiTable, EuiTableBody, EuiTableHeader, EuiTableHeaderCell, EuiTableRow, EuiTableRowCell } from '@elastic/eui';
```

Health describes the status of an element (eg. node, environment, host) that would be typically associated with positive or negative values, while in severity indicates an increasing level of risk.

## Levels

These levels, accordingly applied, serve both purposes of communicating Health statuses and Severity concerns among different contexts. They are willingly generic and descriptive only at a high level so that they can be applied and adapted to different contexts, while at the same time providing consistency across the product.

<EuiTable>
  <EuiTableHeader>
    <EuiTableHeaderCell width="10%">Level</EuiTableHeaderCell>
    <EuiTableHeaderCell>Name</EuiTableHeaderCell>
    <EuiTableHeaderCell width="65%">Description</EuiTableHeaderCell>
  </EuiTableHeader>

  <EuiTableBody>
    <EuiTableRow>
      <EuiTableRowCell>0</EuiTableRowCell>
      <EuiTableRowCell>Unknown</EuiTableRowCell>
      <EuiTableRowCell>Created for unknown or unassigned values that can’t be associated with a specific level. It does not imply any positive or negative meaning.</EuiTableRowCell>
    </EuiTableRow>

    <EuiTableRow>
      <EuiTableRowCell>1</EuiTableRowCell>
      <EuiTableRowCell>Good / Success</EuiTableRowCell>
      <EuiTableRowCell>Created for a direct association with positive meanings, used for healthy elements and positive outcomes.</EuiTableRowCell>
    </EuiTableRow>

    <EuiTableRow>
      <EuiTableRowCell>2</EuiTableRowCell>
      <EuiTableRowCell>Regular / Neutral</EuiTableRowCell>
      <EuiTableRowCell>Used for usual, acceptable states that need to be recognised but don't need to stand out.</EuiTableRowCell>
    </EuiTableRow>

    <EuiTableRow>
      <EuiTableRowCell>3</EuiTableRowCell>
      <EuiTableRowCell>Warning</EuiTableRowCell>
      <EuiTableRowCell>The starting level of concern, used for elements that would need attention.</EuiTableRowCell>
    </EuiTableRow>

    <EuiTableRow>
      <EuiTableRowCell>4</EuiTableRowCell>
      <EuiTableRowCell>Risk</EuiTableRowCell>
      <EuiTableRowCell>Middle level of risk, used for potential escalations and increasing level of severity.</EuiTableRowCell>
    </EuiTableRow>

    <EuiTableRow>
      <EuiTableRowCell>5</EuiTableRowCell>
      <EuiTableRowCell>Danger</EuiTableRowCell>
      <EuiTableRowCell>Highest level of danger, used for elements that need immediate support and attention.</EuiTableRowCell>
    </EuiTableRow>
  </EuiTableBody>
</EuiTable>

## Use cases

The following mapping is not exhaustive of all use cases but it serves as an example of how the Health & Severity levels might be applied. Different contexts and environments might need dedicated terminology, therefore these levels can be used with alternative, customised variations in terms of words and naming, serving the dedicated purpose while aligning the use of colors across the product.

<EuiTable>
  <EuiTableHeader>
    <EuiTableHeaderCell width="20%">Level</EuiTableHeaderCell>
    <EuiTableHeaderCell>Use case A (Alerting/Priority)</EuiTableHeaderCell>
    <EuiTableHeaderCell>Use case B (Health/Status)</EuiTableHeaderCell>
    <EuiTableHeaderCell>Use case C (Severity/Logs)</EuiTableHeaderCell>
  </EuiTableHeader>

  <EuiTableBody>
    <EuiTableRow>
      <EuiTableRowCell>Unknown</EuiTableRowCell>
      <EuiTableRowCell>-</EuiTableRowCell>
      <EuiTableRowCell>Unknown / No data</EuiTableRowCell>
      <EuiTableRowCell>Other</EuiTableRowCell>
    </EuiTableRow>

    <EuiTableRow>
      <EuiTableRowCell>Good / Success</EuiTableRowCell>
      <EuiTableRowCell>-</EuiTableRowCell>
      <EuiTableRowCell>Healthy</EuiTableRowCell>
      <EuiTableRowCell>-</EuiTableRowCell>
    </EuiTableRow>

    <EuiTableRow>
      <EuiTableRowCell>Regular / Neutral</EuiTableRowCell>
      <EuiTableRowCell>Low</EuiTableRowCell>
      <EuiTableRowCell>-</EuiTableRowCell>
      <EuiTableRowCell>Low</EuiTableRowCell>
    </EuiTableRow>

    <EuiTableRow>
      <EuiTableRowCell>Warning</EuiTableRowCell>
      <EuiTableRowCell>Medium</EuiTableRowCell>
      <EuiTableRowCell>Degrading</EuiTableRowCell>
      <EuiTableRowCell>Warn</EuiTableRowCell>
    </EuiTableRow>

    <EuiTableRow>
      <EuiTableRowCell>Risk</EuiTableRowCell>
      <EuiTableRowCell>High</EuiTableRowCell>
      <EuiTableRowCell>-</EuiTableRowCell>
      <EuiTableRowCell>Minor, Major</EuiTableRowCell>
    </EuiTableRow>

    <EuiTableRow>
      <EuiTableRowCell>Danger</EuiTableRowCell>
      <EuiTableRowCell>Critical</EuiTableRowCell>
      <EuiTableRowCell>Violated</EuiTableRowCell>
      <EuiTableRowCell>Critical</EuiTableRowCell>
    </EuiTableRow>
  </EuiTableBody>
</EuiTable>

## Colors

This association between levels and colors has been created to be recognised and immediately understood, avoiding conflicts with other EUI elements and tints.

```mdx-code-block
import { SeverityColorAssociationTable } from './color_association_table.tsx';
```

<SeverityColorAssociationTable />

### Tokens

import { SeverityColorsTable } from '../../getting-started/theming/tokens/colors/severity_colors_table.tsx';
import { DataVisBackgroundColor } from '../../getting-started/theming/tokens/colors/data_vis_colors_table.tsx';
import { DataVisColorsPreview } from '../../getting-started/theming/tokens/colors/data_vis_colors_preview.tsx'

<SeverityColorsTable />

## Text Tokens

import { TextColorPreview } from '../../getting-started/theming/tokens/colors/text_color_preview.tsx'; 
import { SeverityTextColorsTable } from '../../getting-started/theming/tokens/colors/severity_text_colors_table.tsx';
import { Example } from '@site/src/components';

<SeverityTextColorsTable />

## Background Tokens

import { BackgroundColorPreview } from '../../getting-started/theming/tokens/colors/background_color_preview.tsx';
import { SeverityBackgroundColorsTable } from '../../getting-started/theming/tokens/colors/severity_background_colors_table.tsx';

<SeverityBackgroundColorsTable />

## Edge cases

There might be cases in which these levels are not sufficient and don't fully fullfill the needs, in that case please reach out to EUI team.

---

### Packages Website Docs Utilities Accessibility Index (`packages/website/docs/utilities/accessibility/index.mdx`)

---
keywords: [EuiScreenReaderOnly, EuiScreenReaderLive, EuiSkipLink]
---

# Accessibility

import { Example } from '@site/src/components';

## Screen reader only

Using `EuiScreenReaderOnly` hides the wrapped element from the page, but keeps it accessible for screen readers to provide more context. It should be used primarily to mask **text** and requires the child to be a single React element for cloning.

:::warning WebAIM recommendation for screen reader-only content
"In most cases, if content (particularly content that provides functionality or interactivity) is important enough to provide to screen reader users, it should probably be made available to all users." [Learn more about invisible content](https://webaim.org/techniques/css/invisiblecontent/)
:::

*Using a screen reader, verify that there is a second paragraph.*

<Demo>
  ```tsx
  import React from 'react';
  import { EuiText, EuiScreenReaderOnly } from '@elastic/eui';

  export default () => (
    <EuiText>
      <p>This is the first paragraph. It is visible to all.</p>
      <EuiScreenReaderOnly>
        <p>
        This is the second paragraph. It is hidden for sighted users but visible
        to screen readers.
        </p>
      </EuiScreenReaderOnly>
      <p>This is the third paragraph. It is visible to all.</p>
    </EuiText>
  );
  ```
</Demo>

### Showing on focus

If the wrapped element is **focusable**, you must use the `showOnFocus` prop to visibly show the element to all users when focused.

*Tab through the following example with your keyboard to verify the element is visible on focus.*

<Demo>
  ```tsx
  import React from 'react';
  import { EuiText, EuiScreenReaderOnly, EuiLink, EuiToolTip, EuiButtonIcon } from '@elastic/eui';

  export default () => (
    <EuiText>
      <p>
        This link is visible to all on focus:{' '}
        <EuiScreenReaderOnly showOnFocus>
          <EuiLink href="./utilities/accessibility">Link text</EuiLink>
        </EuiScreenReaderOnly>
      </p>
      <p>
        This tooltip + button is visible on focus within:{' '}
        <EuiScreenReaderOnly showOnFocus>
          <span>
            <EuiToolTip content="Information">
              <EuiButtonIcon iconType="info" aria-label="Information" />
            </EuiToolTip>
          </span>
        </EuiScreenReaderOnly>
      </p>
    </EuiText>
  );
  ```
</Demo>

## Screen reader live region

Using `EuiScreenReaderLive` to announce dynamic content, such as status changes based on user interaction.

The configurable `role` and `aria-live` props default to `status` and `polite` respectively for non-intrusive but timely update announcements. When not using the default values, be sure to follow [ARIA guidelines](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions) for `role` to `aria-live` mapping.

Also consider other live region guidelines, such as that live regions must be present on initial page load, and should not be in a conditional JSX wrapper.

import ScreenReaderLiveRegion from './screen_reader_live_region';

<Demo>
  ```tsx
  import { useState, useCallback } from 'react';

  import {
    EuiButton,
    EuiCode,
    EuiScreenReaderLive,
    EuiSpacer,
    EuiText,
  } from '@elastic/eui';

  export default () => {
    const [screenReaderText, setScreenReaderText] = useState(
      'You have no notifications.'
    );

    const startAnnouncements = useCallback(() => {
      const randomNumber = Math.floor(Math.random() * 10) + 1;

      setScreenReaderText(
        `You have ${randomNumber} new notification${randomNumber > 1 ? 's' : ''}.`
      );
    }, []);

    return (
      <>
        <EuiButton onClick={startAnnouncements}>
          Create screen reader announcement
        </EuiButton>
        <EuiSpacer />
        <EuiText>
          <p>
            <em>Content announced by screen reader: </em>
            <EuiCode>{screenReaderText}</EuiCode>
          </p>
          <EuiScreenReaderLive>
            <p>{screenReaderText}</p>
          </EuiScreenReaderLive>
        </EuiText>
      </>
    );
  };
  ```
</Demo>

### Auto-focusing the live region on text change

The `focusRegionOnTextChange` prop will automatically focus the `EuiScreenReaderLive` region (causing screen readers to read out the text content) whenever `children` changes.

This is primarily useful for announcing navigation or page changes, when programmatically resetting focus location back to a certain part of the page (where the `EuiScreenReaderLive` is placed) is desired.

*Using a screen reader, click the following navigation links and notice that when the new page is announced, focus is also set to the top of the body content.*

<Demo previewPadding="s">
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

import { EuiBetaBadge } from '@elastic/eui';

## Live announcer region <EuiBetaBadge label="Beta" color="accent" />

:::warning `EuiLiveAnnouncer` is a new, experimental alternative to `EuiScreenReaderLive` for screen reader live region announcements. 
Its API and behavior may change based on feedback and testing.
:::

Both `EuiLiveAnnouncer` and `EuiScreenReaderLive` are designed for the **same use cases**: to announce dynamic content, such as nodifications or status changes based on user interaction.
The main drawback for live regions is that they must be present on initial page load before reading content updates. `EuiLiveAnnouncer` addresses this 
by updating the content after the initial render to ensure an announcement is made when mounting a component.

Same as for `EuiScreenReaderLive`, `EuiLiveAnnouncer` supports configurable `role` and `aria-live` props which default to `status` and `polite` respectively for non-intrusive but timely update announcements. 
If you're not using the default values, be sure to follow [ARIA guidelines](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions) for `role` to `aria-live` mapping.

### Main difference

- **`EuiLiveAnnouncer`** will announce the message **when the component mounts** (e.g., when it first appears in the DOM), as well as when the message changes.
- **`EuiScreenReaderLive`** will only announce when the message changes, and will not announce the initial message on mount.

This means `EuiLiveAnnouncer` is especially useful for scenarios where you want to ensure an announcement is made immediately when a component is mounted, e.g. showing a notification or alert based on user interaction.

An additional difference is that `EuiLiveAnnouncer` can clear its message after a configurable timeout via `clearAfterMs`, which prevents stale 
announcements and duplicated DOM content for screen reader users. Screen readers will continue reading the message even if it was already cleared.

<Demo>
  ```tsx
  import { useState } from 'react';
  import { EuiButton, EuiCodeBlock, EuiFlexGroup, EuiFlexItem, EuiLiveAnnouncer, EuiSpacer } from '@elastic/eui';

  export default () => {
    const [announcement, setAnnouncement] = useState('No notifications.');
    const [isShown, setIsShown] = useState(false);

    return (
      <EuiFlexGroup direction="column" gutterSize="m" css={{ maxWidth: 300 }}>
        <EuiFlexItem>
          <EuiButton onClick={() => setIsShown((shown) => !shown)}>
            Toggle announcement
          </EuiButton>
        </EuiFlexItem>

        <EuiFlexItem>
          {isShown && (
            <>
              <EuiButton onClick={() => setAnnouncement(`You have ${Math.floor(Math.random() * 1000)} new notifications.`)}>
                Update announcement
              </EuiButton>
              <EuiSpacer size="m" />
              <EuiCodeBlock>{announcement}</EuiCodeBlock>
              <EuiLiveAnnouncer>
                {announcement}
              </EuiLiveAnnouncer>
            </>
          )}
        </EuiFlexItem>
      </EuiFlexGroup>
    );
  };
  ```
</Demo>

### Key differences between `EuiLiveAnnouncer` and `EuiScreenReaderLive`

| Feature                        | `EuiLiveAnnouncer`       | `EuiScreenReaderLive`           |
|--------------------------------|:---------------------------------:|:-------------------------------:|
| **Auto-clear message**         | Yes, after configurable timeout (`clearAfterMs`) | No                    |
| **Announce on mount**          | Yes                                | No                    |
| **Announce on message change** | Yes                                | Yes                   |
| **Focus on message change**    | No                                 | Yes (`focusRegionOnTextChange` prop) |
| **Handles rapid updates**      | Yes                                | Yes                   |
| **Output consistency**         | High                               | Medium                   |
| **API stability**              | Beta/experimental                  | Stable                |


## Skip link

The `EuiSkipLink` component allows users to bypass navigation, or ornamental elements, and quickly reach the main content of the page. It requires a `destinationId` which should match the `id` of your main content. If your ID does not correspond to a valid element, the skip link will fall back to focusing the `<main>` tag on your page, if it exists.

*Tab through the following section to verify the Skip to content button is visible on focus.*

<Demo>
  ```tsx
  import React from 'react';

  import { EuiSkipLink, EuiText } from '@elastic/eui';

  export default () => {
    return (
      <EuiText id="skip-link-example">
        <p>The following skip links are only visible on focus:</p>
        <EuiSkipLink destinationId="skip-link-example" overrideLinkBehavior>
          Skips to this example container
        </EuiSkipLink>
        <EuiSkipLink destinationId="" overrideLinkBehavior>
          Falls back to main container
        </EuiSkipLink>
      </EuiText>
    );
  };
  ```
</Demo>

## Styles helpers

import { ClassNamePreview } from './class_name_preview';
import { FunctionPreview } from './function_preview';
import { HookPreview } from './hook_preview';

<Example>
  <Example.Description>
    ### `.euiScreenReaderOnly` <Badge color="hollow">className</Badge>

    This utility class allows you to apply the screen reader only CSS styles directly to your component.
  </Example.Description>
  <Example.Preview>
    <ClassNamePreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <p className="euiScreenReaderOnly" />
    ```
  </Example.Snippet>
</Example>

<Example>
  <Example.Description>
    ### `euiScreenReaderOnly()` <Badge color="hollow">function</Badge>

    This function allows you to apply the screen reader only CSS styles directly to your component.
  </Example.Description>
  <Example.Preview>
    <FunctionPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      ${euiScreenReaderOnly()}
    `
    ```
  </Example.Snippet>
</Example>

<Example>
  <Example.Description>
    ### `useEuiFocusRing(offset?, color?)` <Badge color="hollow">hook</Badge>

    By default, all interactive elements will inherit the `outline` property from the reset file. However, some instances require adjustment to the `offset` and `color` of this outline. This helper function allows that customization of the focus outline.

    `offset: 'inset' | 'outset' | 'center' | CSSProperties['outlineOffset'];`

    `color: CSSProperties['outlineColor'];`
  </Example.Description>
  <Example.Preview>
    <HookPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      &:focus {
        ${useEuiFocusRing('center', euiTheme.colors.accent)}
      }
    `
    ```
  </Example.Snippet>
</Example>

## Props

import docgen from '@elastic/eui-docgen/dist/components';

<PropTable definition={docgen.EuiScreenReaderOnly} />
<PropTable definition={docgen.EuiScreenReaderLive} />
<PropTable definition={docgen.EuiLiveAnnouncer} />
<PropTable definition={docgen.EuiSkipLink} />

---

### Packages Website Docs Utilities Color Palettes Index (`packages/website/docs/utilities/color-palettes/index.mdx`)

# Color palettes

import { ColorPaletteCopyCode, ColorPaletteFlexItem } from './color_palettes_components';
import colorPaletteComponentsSource from '!raw-loader!./color_palettes_components';

EUI provides a base set of color palettes that return an array of hexadecimal color for use in other EUI components or charts.

## Preset qualitative palettes

Qualitative palettes are best suited for communicating and comparing discrete data series. EUI recommends using the `euiPaletteColorBlind()` for qualitative and categorical data.

This palette is restricted to only 10 colors. However, you can add more groups of 10 which are alternates of the original. This is better than allowing the initial set to loop.

These colors are meant to be used as graphics and contrasted against the value of `euiColorEmptyShade` for the current theme. When placing text on top of these colors, use the `euiPaletteColorBlindBehindText()` variant. It is a brightened version of the base palette to create better contrast with text.

<Demo scope={{ ColorPaletteCopyCode, ColorPaletteFlexItem }} extraFiles={{ 'color_palettes_components.tsx': colorPaletteComponentsSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Recommended quantitative palettes

Quantitative palettes are best suited for displaying data on a continuum, as in the case of health statuses and large geographic or demographic-based data sets.

EUI provides the following common palettes for quantitative data and [charts](../../dataviz/index.mdx). Just pass in the number of steps needed and the function will interpolate between the colors.
For usages in React we recommend using the respective <a href="https://github.com/elastic/eui/blob/main/packages/eui/src/services/color/eui_palettes_hooks.ts" target="_blank" rel="noopener noreferrer">palette hooks</a>, e.g. `useEuiPaletteColorBlind`.

:::warning
The palette for status is the only palette that has proper contrast ratios. When using the other palettes, consider adding another form of the data for screen readers.
:::

<Demo scope={{ ColorPaletteCopyCode, ColorPaletteFlexItem }} extraFiles={{ 'color_palettes_components.tsx': colorPaletteComponentsSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Custom palettes

Use the `colorPalette` service to generate a custom, gradiated palette array of any length from one or more hexadecimal color codes. The third parameter `divergent`, will interpolate between the two halves of the spectrums separately. If a middle point is not provided, it will graduate to light gray.

<Demo scope={{ ColorPaletteCopyCode, ColorPaletteFlexItem }} extraFiles={{ 'color_palettes_components.tsx': colorPaletteComponentsSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/services/color';

<PropTable definition={docgen.euiPaletteColorBlind} />

---

### Packages Website Docs Utilities Focus Trap Index (`packages/website/docs/utilities/focus-trap/index.mdx`)

---
keywords: [EuiFocusTrap]
---

# Focus trap

Use **EuiFocusTrap** to prevent keyboard-initiated focus from leaving a defined area. Temporary flows and UX escapes that occur in components such as [EuiModal](../../components/containers/modal/index.mdx) and [EuiFlyout](../../components/containers/flyout/index.mdx) are prime examples.

For components that project content in a React portal, **EuiFocusTrap** will maintain the tab order expected by users.

* Use `clickOutsideDisables` to disable the focus trap when the user clicks outside the trap.
* Use `noIsolation={false}` when pointer events on outside elements should be disallowed.
* Use `crossFrame={true}` when focus should not be allowed on other iframes on the page.

import FormExample from './form_compressed';
import formCompressedSource from '!raw-loader!./form_compressed';

<Demo scope={{ FormExample }} extraFiles={{ 'form_compressed.tsx': formCompressedSource }}>
```tsx interactive
import React, { useState } from 'react';

import {
  EuiBadge,
  EuiButton,
  EuiFocusTrap,
  EuiPanel,
  EuiSpacer,
  EuiText,
} from '@elastic/eui';
import FormExample from './form_compressed';

export default () => {
  const [isDisabled, changeDisabled] = useState(true);

  const toggleDisabled = () => changeDisabled(!isDisabled);

  return (
    <div>
      <EuiBadge>Trap is {isDisabled ? 'disabled' : 'enabled'}</EuiBadge>
      <EuiSpacer size="s" />
      <EuiFocusTrap disabled={isDisabled}>
        <EuiPanel>
          <FormExample />
          <EuiSpacer size="m" />
          <EuiButton onClick={toggleDisabled}>
            {`${!isDisabled ? 'Disable' : 'Enable'} Focus Trap`}
          </EuiButton>
        </EuiPanel>
      </EuiFocusTrap>
      <EuiSpacer size="l" />
      <EuiText>
        The button below is not focusable by keyboard as long as the focus trap
        is enabled.
      </EuiText>
      <EuiButton onClick={() => {}}>External Focusable Element</EuiButton>
    </div>
  );
};
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/focus_trap';

<PropTable definition={docgen.EuiFocusTrap} />

---

### Packages Website Docs Utilities Scroll Index (`packages/website/docs/utilities/scroll/index.mdx`)

# Scroll

import { css } from '@emotion/react';
import { Example } from '@site/src/components';
import {
  EuiFlexGroup,
  EuiFlexItem,
  EuiPanel,
  EuiProvider,
  EuiText,
  logicalCSS,
  logicalCSSWithFallback,
  useEuiOverflowScroll,
  useEuiScrollBar
} from '@elastic/eui';

import { ScrollContent } from './scroll_content';
import {
  HorizontalScrollClassNamePreview,
  HorizontalScrollHookPreview,
  ScrollBarClassNamePreview,
  ScrollBarHookPreview,
  VerticalScrollClassNamePreview,
  VerticalScrollHookPreview
} from './previews';

:::warning Scrollable regions must be focusable, promoted to region and with the right aria-label

To ensure keyboard-only users have access to the scrollable regions, the optimal solution is to apply `tabIndex="0"` to the region. <a href="https://dequeuniversity.com/rules/axe/4.1/scrollable-region-focusable" target="_blank" rel="noopener noreferrer">**Learn more about the `scrollable-region-focusable` rule at Deque**</a>.
:::

## Scroll bar style

<Example>
  <Example.Description>
    ### `.eui-scrollBar` <Badge color="hollow">className</Badge>

    Use this utility class to style the browser's scrollbar in a minimal aesthetic. This is best used on small, inner-page contents like panels wherever you have `overflow: auto`.
  </Example.Description>
  <Example.Preview>
    <ScrollBarClassNamePreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <div tabIndex={0} className="eui-scrollBar">
      <EuiPanel />
      <EuiPanel />
      <EuiPanel />
    </div>
    ```
  </Example.Snippet>
</Example>
<Example>
  <Example.Description>
    ### `useEuiScrollBar()` <Badge color="hollow">hook</Badge>

    Use this style function to style the browser's scrollbar in a minimal aesthetic. This is best used on small, inner-page contents like panels.

    All parameters are optional and default to specific global settings.
  </Example.Description>
  <Example.Preview>
    <ScrollBarHookPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      ${useEuiScrollBar()}
    `
    ```
  </Example.Snippet>
</Example>

## Vertical (scroll-y)

These utilities allow for quickly applying vertical scrolling to a container. They also automatically apply the minimal scroll bar styles as well. If you do not want your content to stretch to `100%` height, you will need to manually add a `height` (or `max-height`) to the container.

The `WithShadows` variants are primarily used in modals and flyouts and masks the edges to indicate there is more content. When using these variants, you may want to add a small amount padding to the top and bottom of your content so the mask doesn't overlay it.

<Example>
  <Example.Description>
    ### `.eui-yScroll` <Badge color="hollow">className</Badge>

    Quick utility class for adding vertical scrolling to a container.
  </Example.Description>
  <Example.Preview>
    <VerticalScrollClassNamePreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <div tabIndex={0} className="eui-yScrollWithShadows">
      <EuiPanel />
      <EuiPanel />
      <EuiPanel />
    </div>
    ```
  </Example.Snippet>
</Example>
<Example>
  <Example.Description>
    ### `useEuiOverflowScroll('y')` <Badge color="hollow">hook</Badge>

    Styles hook for adding vertical scrolling to a container.

    To mask the top and bottom of the scrolled content, indicating visually that there is more content below, pass in true to the second parameter `mask`.

    `useEuiOverflowScroll('y', true);`
  </Example.Description>
  <Example.Preview>
    <VerticalScrollHookPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      ${useEuiOverflowScroll('y', true)}
    `
    ```
  </Example.Snippet>
</Example>

## Horizontal (scroll-x)

The horizontal equivalent should be used sparingly and usually only in full-height layouts or a grid of items.

When using the `WithShadows` variant, you may want to add a small amount padding to the sides of your content so the mask doesn't overlay it.

<Example>
  <Example.Description>
    ### `.eui-xScroll` <Badge color="hollow">className</Badge>

    Quick utility class for adding horizontal scrolling to a container.
  </Example.Description>
  <Example.Preview>
    <HorizontalScrollClassNamePreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <div tabIndex={0} className="eui-xScrollWithShadows">
      <EuiPanel />
      <EuiPanel />
      <EuiPanel />
    </div>
    ```
  </Example.Snippet>
</Example>
<Example>
  <Example.Description>
    ### `useEuiOverflowScroll('x')` <Badge color="hollow">hook</Badge>

    Styles hook for adding horizontal scrolling to a container.

    To mask the top and bottom of the scrolled content, indicating visually that there is more content below, pass in true to the second parameter `mask`.

    `useEuiOverflowScroll('x', true);`
  </Example.Description>
  <Example.Preview>
    <HorizontalScrollHookPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      ${useEuiOverflowScroll('x', true)}
    `
    ```
  </Example.Snippet>
</Example>

## Full height layout

<Example>
  <Example.Description>
    ### `.eui-fullHeight` <Badge color="hollow">className</Badge>

    Quick utility for expanding the height of the element to its parents dimensions. Use it to stretch each nested element until the one that applies scroll.

    Works on both flex and non-flex elements.
  </Example.Description>
  <Example.Preview>
    <div style={{ height: 180 }}>
      <EuiFlexGroup className="eui-fullHeight" gutterSize="s" responsive={false}>
        <EuiFlexItem>
          <EuiPanel className="eui-yScroll" color="warning" tabIndex={0}>
            <EuiText size="s">
              <p>
                Orbiting this at a distance of roughly ninety-two million miles is
                an utterly insignificant little blue green planet whose
                ape-descended life forms are so amazingly primitive that they
                still think digital watches are a pretty neat idea.
              </p>
            </EuiText>
          </EuiPanel>
        </EuiFlexItem>
        <EuiFlexItem>
          <EuiPanel className="eui-yScroll" color="warning" tabIndex={0}>
            <EuiText size="s">
              <p>
                Orbiting this at a distance of roughly ninety-two million miles is
                an utterly insignificant little blue green planet whose
                ape-descended life forms are so amazingly primitive that they
                still think digital watches are a pretty neat idea.
              </p>
            </EuiText>
          </EuiPanel>
        </EuiFlexItem>
      </EuiFlexGroup>
    </div>
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <BodyContent style={{ height: 180 }}>
      <EuiFlexGroup className="eui-fullHeight" responsive={false}>
        <EuiFlexItem>
          <BodyScroll className="eui-yScroll" tabIndex={0} />
        </EuiFlexItem>
        <EuiFlexItem>
          <BodyScroll className="eui-yScroll" tabIndex={0} />
        </EuiFlexItem>
      </EuiFlexGroup>
    </BodyContent>
    ```
  </Example.Snippet>
</Example>
<Example>
  <Example.Description>
    ### `euiFullHeight()` <Badge color="hollow">function</Badge>

    Emotion mixin for adding full height scrolling to a container or flex child.

    It applies `height: 100%; overflow: hidden;` but also adds `flex: 1 1 auto;` for use within `flex` containers.
  </Example.Description>
  <Example.Snippet>
    ```tsx
    css`
      ${euiFullHeight()}
    `
    ```
  </Example.Snippet>
</Example>

---

### Packages Website Docs Utilities Window Events Index (`packages/website/docs/utilities/window-events/index.mdx`)

# Window events

import { ModalExample } from './modal_example';
import modalExampleSource from '!raw-loader!./modal_example';

## Basic example: closing a modal on escape

Use an **EuiWindowEvent** to safely and declaratively manage adding and auto-removing event listeners to the `window`. This is preferable to setting up your own window event listeners because it will remove old listeners when your component unmounts, preventing you from accidentally leaving them around forever.

This modal example registers a listener on the `keydown` event and listens for ESC key presses, which closes the open modal.

<Demo scope={{ ModalExample }} extraFiles={{ 'modal_example.tsx': modalExampleSource }}>
```tsx interactive
import React from 'react';

import {
  EuiModal,
  EuiModalBody,
  EuiModalHeader,
  EuiModalHeaderTitle,
} from '@elastic/eui';
import { ModalExample } from './modal_example';

const BasicModal = ({ onClose }) => (
  <EuiModal onClose={onClose} style={{ width: '800px' }}>
    <EuiModalHeader>
      <EuiModalHeaderTitle>Example modal</EuiModalHeaderTitle>
    </EuiModalHeader>
    <EuiModalBody>
      <p>
        This modal closes when you press ESC, using a window event listener.
      </p>
    </EuiModalBody>
  </EuiModal>
);

export default () => <ModalExample modal={BasicModal} />;
```
</Demo>

## Avoiding event conflicts

:::warning Be careful with global listeners

Since window event listeners are global, they can conflict with other event listeners if you aren't careful.
:::

The safest and best way to avoid these conflicts is to use `event.stopPropagation()` at the lowest, most specific level where you are responding to a DOM event. This will prevent the event from bubbling up to the window, and the **EuiWindowEvent** listener will never be triggered, avoiding the conflict.

<Demo scope={{ ModalExample }} extraFiles={{ 'modal_example.tsx': modalExampleSource }}>
```tsx interactive
import React, { useState } from 'react';

import {
  EuiModal,
  EuiModalBody,
  EuiModalHeader,
  EuiModalHeaderTitle,
  EuiFieldText,
  EuiSpacer,
  keys,
} from '@elastic/eui';
import { ModalExample } from './modal_example';

const ConflictModal = (props) => {
  const [inputValue, setInputValue] = useState('');

  const updateInputValue = (e) => {
    setInputValue(e.target.value);
  };

  const clearInputValueOnEscape = (event) => {
    if (event.key === keys.ESCAPE) {
      setInputValue('');
      event.stopPropagation();
    }
  };

  return (
    <EuiModal onClose={props.onClose} style={{ width: '800px' }}>
      <EuiModalHeader>
        <EuiModalHeaderTitle>Example modal</EuiModalHeaderTitle>
      </EuiModalHeader>
      <EuiModalBody>
        <EuiFieldText
          value={inputValue}
          onChange={updateInputValue}
          onKeyDown={clearInputValueOnEscape}
        />
        <EuiSpacer size="s" />
        <p>While typing in this field, ESC will clear the field.</p>
        <EuiSpacer size="l" />
        <p>
          Otherwise, the event bubbles up to the window and ESC closes the
          modal.
        </p>
      </EuiModalBody>
    </EuiModal>
  );
};

export default () => (
  <ModalExample
    modal={ConflictModal}
    buttonText="Open Modal with Conflicting Listener"
  />
);
```
</Demo>

## Tracking mouse position

For some DOM events, you have to listen on the window. One example of this is tracking mouse position. Below, when you click the toggle switch, your mouse position is tracked. When you toggle off, tracking stops.

If you were manually attaching window listeners, you might forget to remove the listener and be silently responding to mouse events in the background for the life of your app. The **EuiWindowEvent** component manages that unmount/unregister process for you.

<Demo>
```tsx interactive
import React, { useState } from 'react';

import {
  EuiSwitch,
  EuiDescriptionList,
  EuiSpacer,
  EuiWindowEvent,
} from '@elastic/eui';

export default () => {
  const [tracking, setTracking] = useState(false);
  const [coordinates, setCoordinates] = useState({});

  const onSwitchChange = () => {
    setTracking(!tracking);
  };

  const onMouseMove = ({ clientX, clientY }) => {
    setCoordinates({ clientX, clientY });
  };

  const listItems = [
    {
      title: 'Position X',
      description: coordinates.clientX || '??',
    },
    {
      title: 'Position Y',
      description: coordinates.clientY || '??',
    },
  ];

  return (
    <div>
      <EuiSwitch
        label="Track mouse position"
        checked={tracking}
        onChange={onSwitchChange}
      />
      {tracking ? (
        <EuiWindowEvent event="mousemove" handler={onMouseMove} />
      ) : null}
      <EuiSpacer size="l" />
      <EuiDescriptionList listItems={listItems} />
      <EuiSpacer size="xxl" />
    </div>
  );
};
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/services/window_event';

<PropTable definition={docgen.EuiWindowEvent} />

---

### Packages Website Docs Components Containers Flyout Index (`packages/website/docs/components/containers/flyout/index.mdx`)

---
keywords: [EuiFlyout, EuiFlyoutBody, EuiFlyoutHeader, EuiFlyoutFooter, EuiFlyoutMenu]
---

# Flyout

**EuiFlyout** is a fixed position panel that pops in from the side of the window. It should be used to reveal more detailed contextual information or to provide complex forms without losing the user's current state. It is a good alternative to [modals](../modal/index.mdx) when the action is not transient.

Like modals, you control the visibility of the flyout using your own state management, but **EuiFlyout** requires an `onClose` handler for it's internal dismiss buttons.

## Component

:::accessibility Accessibility requirement
Use `aria-labelledby={headingId}` to ensure the flyout is announced to screen readers.
:::

```tsx interactive
import React, { useState } from 'react';
import {
  EuiFlyout,
  EuiFlyoutBody,
  EuiFlyoutHeader,
  EuiButton,
  EuiText,
  EuiTitle,
  EuiCodeBlock,
  useGeneratedHtmlId,
} from '@elastic/eui';

export default () => {
  const [isFlyoutVisible, setIsFlyoutVisible] = useState(false);
  const simpleFlyoutTitleId = useGeneratedHtmlId({
    prefix: 'simpleFlyoutTitle',
  });

  let flyout;

  const htmlCode = `<EuiFlyout ...>
  <EuiFlyoutHeader hasBorder>
    <EuiTitle size="m">
      <h2></h2>
    </EuiTitle>
  </EuiFlyoutHeader>
  <EuiFlyoutBody>
    ...
  </EuiFlyoutBody>
</EuiFlyout>
`;

  if (isFlyoutVisible) {
    flyout = (
      <EuiFlyout
        ownFocus
        onClose={() => setIsFlyoutVisible(false)}
        aria-labelledby={simpleFlyoutTitleId}
      >
        <EuiFlyoutHeader hasBorder>
          <EuiTitle size="m">
            <h2 id={simpleFlyoutTitleId}>A typical flyout</h2>
          </EuiTitle>
        </EuiFlyoutHeader>
        <EuiFlyoutBody>
          <EuiText>
            <p>
              For consistency across the many flyouts, please utilize the
              following code for implementing the flyout with a header.
            </p>
          </EuiText>
          <EuiCodeBlock language="html">{htmlCode}</EuiCodeBlock>
        </EuiFlyoutBody>
      </EuiFlyout>
    );
  }

  return (
    <div>
      <EuiButton onClick={() => setIsFlyoutVisible(true)}>
        Show flyout
      </EuiButton>
      {flyout}
    </div>
  );
};

```

## Usage

### Accessing flyout elements

Pass a React `ref` to **EuiFlyoutHeader** or **EuiFlyoutFooter** to access its root `div`. On **EuiFlyout**, `ref` points to the flyout panel and `scrollContainerRef` points to the outer `.euiFlyout__content` container wrapping the header, body, and footer. **EuiFlyoutBody** has a separate `scrollContainerRef` pointing to its inner overflow container.

Normally, the body's container is what scrolls. The outer container scrolls only when using **EuiFlyoutBody** and the header, body, and footer exceed the viewport height (usually on short screens). To respond to every scroll, attach to both containers.

### More complicated flyout

This component also comes with related child components for ease of creating headers, footers and scrolling body content. **EuiFlyoutHeader** and **EuiFlyoutFooter** are pinned to the top and bottom of the flyout, respectively, to allow for always visible navigation and actions. The **EuiFlyoutBody** component will then automatically overflow.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Sizing

Flyouts come in three predefined `size`s of `'s' | 'm' | 'l'`, which define the width **relative to the window size** with a minimum width defined in pixels. You can otherwise supply your own fixed width in number or string format.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Padding

All the inner flyout components inherit their padding from the wrapping **EuiFlyout** component. This ensures that all the horizontal edges line up no matter the `paddingSize`. When using the `"none"` size, you will need to accommodate your content with some other way of creating distance to the edges of the flyout.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Banners

To highlight some information at the top of a flyout, you can pass an [EuiCallOut](../../display/callout.mdx) to the `banner` prop available in **EuiFlyoutBody** and its layout will adjust appropriately.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Without ownFocus

Like modals, you will usually want to obscure the page content beneath with `ownFocus` which wraps the flyout with an [EuiOverlayMask](../../../utilities/overlay-mask.mdx) . However, there are use-cases where flyouts present more information or controls, but need to maintain the interactions of the page content. By setting `ownFocus={false}`, the underlying page content will be visible and clickable.

```tsx interactive
import React, { useState } from 'react';
import {
  EuiFlyout,
  EuiFlyoutHeader,
  EuiFlyoutBody,
  EuiButton,
  EuiText,
  EuiTitle,
  useGeneratedHtmlId,
} from '@elastic/eui';

export default () => {
  const [isFlyoutVisible, setIsFlyoutVisible] = useState(false);

  const closeFlyout = () => setIsFlyoutVisible(false);

  const toggleFlyout = () => setIsFlyoutVisible((isVisible) => !isVisible);

  const withoutFocusFlyoutTitleId = useGeneratedHtmlId({
    prefix: 'withoutFocusFlyoutTitle',
  });

  let flyout;
  if (isFlyoutVisible) {
    flyout = (
      <EuiFlyout
        ownFocus={false}
        onClose={closeFlyout}
        aria-labelledby={withoutFocusFlyoutTitleId}
      >
        <EuiFlyoutHeader hasBorder>
          <EuiTitle size="s">
            <h2 id={withoutFocusFlyoutTitleId}>A flyout without ownFocus</h2>
          </EuiTitle>
        </EuiFlyoutHeader>
        <EuiFlyoutBody>
          <EuiText>
            <p>
              The page contents is still interactive though screen reader users
              will find themselves still within the bounds of the flyout.
            </p>
          </EuiText>
        </EuiFlyoutBody>
      </EuiFlyout>
    );
  }
  return (
    <div>
      <EuiButton onClick={toggleFlyout}>Toggle flyout</EuiButton>

      {flyout}
    </div>
  );
};
```

### Understanding max-width

By default, flyouts will continue to grow with the width of the window. To stop this growth at an ideal width, set `maxWidth` to `true`, or pass your own custom size.

:::warning
Note that there are some caveats to providing a maxWidth that is smaller than the minWidth.
:::

```
/* Detailed source-code truncated for AI context efficiency. */
```

import { Example } from '@site/src/components';

### Focus management

`EuiFlyout` used with `type="overlay"` manages focus for keyboard navigation and accessibility. This ensures users can navigate modal content effectively,
especially those using screen readers or keyboard-only navigation.

When a `EuiFlyout` is used, it will automatically:

1. Move focus to the flyout when opened
2. Trap focus inside the flyout while open
3. Return focus to the trigger element when closed

#### Manual return focus control

Use `focusTrapProps` to customize the focus behavior:

```tsx
<EuiFlyout
  focusTrapProps={{
    returnFocus: (triggerElement) => {
      // Return true to use default behavior (focus triggerElement)
      // Return false to prevent default behavior
      if (customElement.current) {
        customElement.current.focus();
        return false;
      }
      return true;
    },
  }}
/>
```

:::warning Manually return focus when the trigger element is removed
If the trigger element is removed from the DOM before the flyout closes, focus will be "lost" to the document body.
In this case, manually return focus to an appropriate element using `focusTrapProps.returnFocus`.
:::

### Push flyout

import PushFlyout from './_flyout_push.mdx';

<PushFlyout />

### Resizable flyout

import ResizableFlyout from './_flyout_resizable.mdx';

<ResizableFlyout />

### Container-relative positioning

By default, flyouts use `position: fixed` and are positioned relative to the viewport. The optional `container` prop allows you to scope a flyout to a specific region of the page instead. When a `container` element is provided, the flyout's bounding rect is used to compute inline positioning styles that visually constrain the flyout within the container's bounds. The flyout remains in `document.body` with `position: fixed` — no DOM mutations are applied to the container (except push-mode padding).

This is useful when flyouts should not overlap application chrome such as side navigation or toolbars. For example, in Kibana the default container is the application content area so that flyouts stay within the app region.

```tsx
const [containerEl, setContainerEl] = useState<HTMLElement | null>(null);

<main ref={setContainerEl}>
  {isFlyoutVisible && (
    <EuiFlyout container={containerEl} onClose={closeFlyout}>
      {/* ... */}
    </EuiFlyout>
  )}
</main>
```

Resize clamping and responsive breakpoints use the container's width as the reference instead of the viewport width. The container element is treated as read-only — it is not modified by the flyout except for push-mode padding (`paddingInlineEnd` or `paddingInlineStart`) when a push flyout is open.

#### Child flyout inheritance

Child flyouts automatically inherit the `container` from the parent flyout's context. There is no need to pass the prop explicitly to child flyouts. To use the document body as the reference container for a child (overriding an inherited container), pass `container={null}`.

```mdx-code-block
import { EuiBetaBadge } from '@elastic/eui';
```

### Flyout menu <EuiBetaBadge size="s" label="Beta" color="accent" /> {#flyout-menu}

import FlyoutMenu from './_flyout_menu.mdx';

<FlyoutMenu />

## Guidelines

import SessionManagement from './_session_management.mdx';

<SessionManagement />

## Props

import docgen from '@elastic/eui-docgen/dist/components/flyout';
import docgenFlyoutMenuTypes from '@elastic/eui-docgen/dist/components/flyout/flyout_menu/types.docgen.json';

<PropTable definition={docgen.EuiFlyout} />

<PropTable definition={docgen.EuiFlyoutBody} />

<PropTable definition={docgen.EuiFlyoutFooter} />

<PropTable definition={docgen.EuiFlyoutHeader} />

<PropTable definition={docgen.EuiFlyoutMenu} />

<PropTable definition={docgenFlyoutMenuTypes.EuiFlyoutMenuAction} />

---

### Packages Website Docs Components Containers Modal Index (`packages/website/docs/components/containers/modal/index.mdx`)

---
slug: /containers/modal
id: containers_modal
keywords: [EuiModal, EuiModalBody, EuiModalFooter, EuiModalHeader, EuiModalHeaderTitle, EuiConfirmModal]
---

# Modal

A modal is best for focusing the user's attention on a **small** amount of content and prompting a decision, such as a [confirmation](#confirm-modal). Use it to temporarily interrupt the current task and block interaction with the content below.

Each **EuiModal** needs a specific set of nested child components. You can omit some if needed, but do not change their order.

:::tip Modal vs flyout

If your modal content is complex or takes a long time to complete, consider using an [EuiFlyout](../flyout/index.mdx) instead.
:::


## Components

:::accessibility Accessibility requirement
Use `aria-labelledby={modalTitleId}` to ensure the modal is announced to screen readers.
:::

### Default

Modals use an **EuiOverlayMask** to obscure content beneath.

```
/* Detailed source-code truncated for AI context efficiency. */
```

import { Example } from '@site/src/components';

### Focus management

`EuiModal` manages focus for keyboard navigation and accessibility. This ensures users can navigate modal content effectively, 
especially those using screen readers or keyboard-only navigation.

When a `EuiModal` is used, it will automatically:

1. Move focus to the modal when opened
2. Trap focus inside the modal while open
3. Return focus to the trigger element when closed

#### Manual return focus control

Use `focusTrapProps` to customize the focus behavior:

```tsx
<EuiModal
  focusTrapProps={{
    returnFocus: (triggerElement) => {
      // Return true to use default behavior (focus triggerElement)
      // Return false to prevent default behavior
      if (customElement.current) {
        customElement.current.focus();
        return false;
      }
      return true;
    },
  }}
/>
```

:::warning Manually return focus when the trigger element is removed
If the trigger element is removed from the DOM before the modal closes, focus will be "lost" to the document body.
In this case, manually return focus to an appropriate element using `focusTrapProps.returnFocus`.
:::

### Confirm modal

import ConfirmModal from './_confirm_modal.mdx';

<ConfirmModal />

## Usage

import Patterns from './_patterns.mdx';

<Patterns />

## Guidelines

import Guidelines from './_guidelines.mdx';

<Guidelines />

## Props

import docgen from '@elastic/eui-docgen/dist/components/modal';

<PropTable definition={docgen.EuiModal} />

<PropTable definition={docgen.EuiModalHeader} />

<PropTable definition={docgen.EuiModalHeaderTitle} />

<PropTable definition={docgen.EuiModalBody} />

<PropTable definition={docgen.EuiModalFooter} />

<PropTable definition={docgen.EuiConfirmModal} />

---

### Packages Website Docs Components Containers Panel Index (`packages/website/docs/components/containers/panel/index.mdx`)

---
keywords: [EuiPanel, EuiSplitPanel]
---

# Panel

**EuiPanel** is a building block component. Use it as a layout helper for containing content. It is also commonly used as a base for other larger components like [EuiPage](../../templates/page-template/index.mdx), [EuiPopover](../popover.mdx) and [EuiCard](../card.mdx).

## Component

### Default

Panels default to a flat bordered look (`hasBorder=true`, `hasShadow=false`). Use shadow only when you need elevation.

```tsx interactive
import React from 'react';
import { EuiPanel } from '@elastic/eui';

export default () => (
  <EuiPanel>
    Default panel
  </EuiPanel>
);
```

### Split

import SplitPanel from './_split_panel.mdx';

<SplitPanel />

## Usage

### Padding

The most basic use is to simply add padding around your content. The preferred padding options are `none`, `s`, `m` (default) and `l`.

```tsx interactive
import React from 'react';
import { EuiPanel, EuiCode, EuiSpacer } from '@elastic/eui';

export default () => (
  <div>
    <EuiPanel paddingSize="none">
      <EuiCode>paddingSize=&quot;none&quot;</EuiCode>
    </EuiPanel>

    <EuiSpacer size="l" />

    <EuiPanel paddingSize="s">
      <EuiCode>paddingSize=&quot;s&quot;</EuiCode>
    </EuiPanel>

    <EuiSpacer size="l" />

    <EuiPanel paddingSize="m">
      <EuiCode>paddingSize=&quot;m&quot; (default)</EuiCode>
    </EuiPanel>

    <EuiSpacer size="l" />

    <EuiPanel paddingSize="l">
      <EuiCode>paddingSize=&quot;l&quot;</EuiCode>
    </EuiPanel>
  </div>
);
```

### Shadow and border

By default, **EuiPanel** is flat with `hasBorder=true` on and `hasShadow=false`. Use `hasShadow` when you need elevation. Be mindful of not using too many [nested panels](#guidelines) with these settings.

:::warning Certain allowed combinations of shadow, border, and color depend on the current theme.

For instance, only plain or transparent panels can have a border and/or shadow. The default theme doesn't allow combining the `hasBorder` option with `hasShadow`.

:::

```tsx interactive
import React from 'react';
import { EuiPanel, EuiCode, EuiSpacer } from '@elastic/eui';

export default () => {
  return (
    <div>
      <EuiPanel>
        <EuiCode>Default (hasBorder, no shadow)</EuiCode>
      </EuiPanel>

      <EuiSpacer />

      <EuiPanel hasBorder={false} hasShadow>
        <EuiCode>{'hasBorder={false} hasShadow'}</EuiCode>
      </EuiPanel>
    </div>
  );
};
```

### Colors and corners

Use `color` to add background shading to your panel and provide an additional helpful aesthetic to your container in context. Be mindful to use color sparingly. You can also remove the rounded corners depending on the placement of your panel with `borderRadius="none"`

Passing `color="transparent"` can give you a quick empty box simply for adding padding to all sides.

```tsx interactive
import React from 'react';
import { EuiPanel, EuiSpacer } from '@elastic/eui';

export default () => (
  <div>
    <EuiPanel color="subdued" borderRadius="none" hasShadow={false}>
      <p>I am a simple shaded box</p>
    </EuiPanel>

    <EuiSpacer />

    <EuiPanel color="transparent" hasBorder={false}>
      <p>I am a transparent box simply for padding</p>
    </EuiPanel>
  </div>
);
```

### Growing height

Using **EuiPanel** in an [EuiFlexItem](../../layout/flex/item.mdx#panels-grow-vertically-to-fill-flex-items) will always grow its height to match. This is great for rows of panels. However, you can also turn this feature off by setting `grow={false}`.

```tsx interactive
import React from 'react';
import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';

export default () => (
  <EuiFlexGroup gutterSize="l">
    <EuiFlexItem>
      <EuiPanel>
        <EuiText>
          <p>
            I am some panel content...
            <br /> ... <br /> ... <br />
            whose content is tall
          </p>
        </EuiText>
      </EuiPanel>
    </EuiFlexItem>
    <EuiFlexItem>
      <EuiPanel grow={true}>
        <EuiText>
          <p>I am some panel content... whose content will grow</p>
        </EuiText>
      </EuiPanel>
    </EuiFlexItem>
    <EuiFlexItem>
      <EuiPanel grow={false}>
        <EuiText>
          <p>I am some panel content... whose content did not grow</p>
        </EuiText>
      </EuiPanel>
    </EuiFlexItem>
  </EuiFlexGroup>
);
```

## Guidelines

import Guidelines from './_guidelines.mdx';

<Guidelines />

## Props

import docgen from '@elastic/eui-docgen/dist/components/panel';

<PropTable definition={docgen.EuiPanel} />

import PropTableSplitPanel from './_split_panel_props';

<PropTableSplitPanel />

---

### Packages Website Docs Components Containers Tabs Index (`packages/website/docs/components/containers/tabs/index.mdx`)

---
keywords: [EuiTabs, EuiTab]
---

# Tabs

Use tabs to organize related but unique content for a single idea or subject. Tabs show and hide content using **in-page** navigation UI.

**EuiTabs** is a wrapping component that requires **EuiTab** components as direct children. You control the displayed contents and current state through props on EuiTab like `isSelected` and `onClick`.

Use the `prepend` and `append` tab props to add content before and after the tab label respectively.

## Component

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Usage

### Tab sizes

**EuiTabs** allow a `size` prop. In general you should always use the default (medium) size. The small size is best for when placing inside popovers or other small containers. Reserve using the large size for when using as primary page navigation, like inside of [EuiPageHeader](../../layout/page-header.mdx).

You can also use the `expand` prop to evenly stretch each tab horizontally.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Bottom border

The `bottomBorder` helps to separate the tab group from the content below and is on by default. However, some components like [flyouts](../../containers/flyout/index.mdx) already provide borders which can act as the divider. In this case you can turn the border off with `bottomBorder={false}`.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Tabbed content

**EuiTabbedContent** makes it easier to associate tabs with content based on the selected tab. Use the `initialSelectedTab` prop to specify which tab to initially select.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Controlled tabbed content

You can also use the `selectedTab` and `onTabClick` props to take complete control over tab selection. This can be useful if you want to change tabs based on user interaction with another part of the UI.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Guidelines

import Guidelines from './_guidelines.mdx';

<Guidelines />

## Props

import docgen from '@elastic/eui-docgen/dist/components/tabs';

<PropTable definition={docgen.EuiTabs} />

<PropTable definition={docgen.EuiTab} />

<PropTable definition={docgen.EuiTabbedContent} />

---

### Packages Website Docs Components Display Badge Index (`packages/website/docs/components/display/badge/index.mdx`)

---
keywords: [EuiBadge, EuiBetaBadge, EuiNotificationBadge]
---

# Badge

**EuiBadge** highlights key pieces of information. While badges will space themselves automatically when used repeatedly, it's best practice to wrap them in an **EuiBadgeGroup**. This ensures they wrap properly when space is limited (as shown below).

## Components

### Default

```tsx interactive
import React, { useState } from 'react';
import {
  EuiBadge,
} from '@elastic/eui';

export default () => <EuiBadge>Default badge</EuiBadge>;
```

### Notification badge

import NotificationBadge from './_notification_badge.mdx';

<NotificationBadge />

### Beta badge

import BetaBadge from './_beta_badge.mdx';

<BetaBadge />

## Usage

### Color options

Badge colors can be configured with the [`color` prop](#EuiBadge-prop-color)
and the related [`fill` prop](#EuiBadge-prop-fill).
When a named color like `primary` is passed to the `color` prop, the `fill` prop
determines whether the badge will use filled (more intense) or non-filled
(less intense) colors. By default, all badges use non-filled colors.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Badge with Icon

Badges can use icons on the left and right (default) sides.

```tsx interactive
import React from 'react';
import { EuiBadge } from '@elastic/eui';

export default () => (
  <div>
    <EuiBadge color="hollow" iconType="cross" iconSide="right">
      Hollow
    </EuiBadge>

    <EuiBadge iconType="check">Default</EuiBadge>

    <EuiBadge iconType="lensApp" color="primary">
      Primary with an app icon
    </EuiBadge>

    <EuiBadge iconType="return" />
  </div>
);
```

### Badge with onClick events

Badges can have `onClick` events applied to the badge itself or the icon within the badge. The latter option is useful for when you might use badges in other components (like a tag system with autocomplete where you need close events).

:::note `onClick` with `iconOnClick`

When providing both these click handlers, **EuiBadge** must alter the contents so that it does not contain nested button tags. Please make note that if you provide props other than those explicit to **EuiBadge**, they will always be applied to the main `button` tag which may be inside of the outer most tag.

:::

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Badge for health status

Badges can work as health status indicators in places where there are a lot of repeated statuses, e.g. in tables.

```tsx interactive
import React from 'react';
import { EuiBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';

export default () => (
  <EuiFlexGroup wrap responsive={false} gutterSize="xs">
    <EuiFlexItem grow={false}>
      <EuiBadge color="success">Healthy</EuiBadge>
    </EuiFlexItem>
    <EuiFlexItem grow={false}>
      <EuiBadge color="warning">Warning</EuiBadge>
    </EuiFlexItem>
    <EuiFlexItem grow={false}>
      <EuiBadge color="danger">Critical</EuiBadge>
    </EuiFlexItem>
    <EuiFlexItem grow={false}>
      <EuiBadge color="default">Unknown</EuiBadge>
    </EuiFlexItem>
  </EuiFlexGroup>
);
```

### Badge with href

Badges can also be made to render anchor tags by passing an `href`.

```tsx interactive
import React from 'react';
import { EuiBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';

export default () => (
  <EuiFlexGroup wrap responsive={false} gutterSize="xs">
    <EuiFlexItem grow={false}>
      <EuiBadge color="#BADA55" href="#/display/badge">
        badge as an anchor
      </EuiBadge>
    </EuiFlexItem>
    <EuiFlexItem grow={false}>
      <EuiBadge color="hollow" href="#/display/badge" target="blank">
        anchor with target specified
      </EuiBadge>
    </EuiFlexItem>
    <EuiFlexItem grow={false}>
      <EuiBadge
        color="accent"
        href="#/display/badge"
        iconType="bolt"
        iconSide="right"
        iconOnClick={() => {}}
        iconOnClickAriaLabel="Example of onClick event for icon within the anchor"
      >
        anchor with an icon and iconOnClick
      </EuiBadge>
    </EuiFlexItem>
    <EuiFlexItem grow={false}>
      <EuiBadge color="success" href="#/display/badge" isDisabled={true}>
        disabled anchor badge
      </EuiBadge>
    </EuiFlexItem>
  </EuiFlexGroup>
);
```

### Badge groups and truncation

Badges, like buttons, will only every be a single line of text. This means text will not wrap, but be truncated if the badge's width reaches that of its parent's.

For this reason, badges also auto-apply the inner text of the badge to the `title` attribute of the element to provide default browser tooltips with the full badge text.

To ensure proper wrapping, truncation and spacing of multiple badges, it is advisable to wrap them in a **EuiBadgeGroup**.

```tsx interactive
import React from 'react';
import { EuiBadge, EuiPanel, EuiBadgeGroup } from '@elastic/eui';

export default () => (
  <EuiPanel style={{ maxWidth: 200 }}>
    <EuiBadgeGroup gutterSize="s">
      <EuiBadge>Badge with simple text being truncated</EuiBadge>

      <EuiBadge iconType="clock">Badge with icon being truncated</EuiBadge>

      <EuiBadge onClick={() => {}} onClickAriaLabel="Click this badge to...">
        Badge with onClick being truncated
      </EuiBadge>

      <EuiBadge
        iconType="cross"
        iconSide="right"
        iconOnClick={() => {}}
        iconOnClickAriaLabel="Click this icon to..."
      >
        Badge with iconOnClick being truncated
      </EuiBadge>

      <EuiBadge
        iconType="cross"
        iconSide="right"
        onClick={() => {}}
        onClickAriaLabel="Click this badge to..."
        iconOnClick={() => {}}
        iconOnClickAriaLabel="Click this icon to..."
      >
        Badge with both onClicks being truncated
      </EuiBadge>
    </EuiBadgeGroup>
  </EuiPanel>
);
```

## Guidelines

import Guidelines from './_guidelines.mdx';

<Guidelines />

## Props

import docgen from '@elastic/eui-docgen/dist/components/badge';

<PropTable definition={docgen.EuiBadge} />

<PropTable definition={docgen.EuiBadgeGroup} />

<PropTable definition={docgen.EuiNotificationBadge} />

<PropTable definition={docgen.EuiBetaBadge} />

---

### Packages Website Docs Components Display Comment List Index (`packages/website/docs/components/display/comment-list/index.mdx`)

---
keywords: [EuiCommentList, EuiComment]
---

# Comment list

The **EuiCommentList** is a timeline component built on top of [EuiTimeline](../timeline.mdx). It allows you to display comments or logged actions that either a user or a system has performed.

:::accessibility Accessibility recommendation
Provide a descriptive `aria-label` or the ID of an external label to the `aria-labelledby` prop of the **EuiCommentList**. A `timelineAvatarAriaLabel` should be provided for every **EuiComment** with or without a `timelineAvatar` as `IconType`.
:::

## Basic comment list

Use **EuiCommentList** to display a list of **EuiComments**. Pass an array of **EuiComment** objects and **EuiCommentList** will generate a comment thread.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Comment

The **EuiComment** is flexible and adapts the design according to the props passed.

import { CommentListProps, CommentListStyle } from './comment_list_props.tsx';

<CommentListProps
  snippet={`<EuiCommentList aria-label="Comment example">
    <EuiComment
      eventIcon="pencil"
      username="janed"
      event={event}
      timestamp={timestamp}
      actions={customActions}
    >
      {children}
    </EuiComment>
  </EuiCommentList>`}
/>
<CommentListStyle>

1.  `timelineAvatar`: Shows an avatar that should indicate who is the author of the comment. To customize, pass a `string` as an `EuiIcon['type']` or an [EuiAvatar](../avatar.mdx). Use in conjunction with `timelineAvatarAriaLabel` to pass an aria label to the avatar. If no avatar is provided, it will default to an avatar with a `user` icon.
2.  `eventIcon`: Icon that shows before the username. Use in conjunction with `eventIconAriaLabel` to pass an aria label to the event icon.
3.  `username`: Author of the comment.
4.  `event`: Describes the event that took place.
5.  `timestamp`: Time of occurrence of the event.
6.  `actions`: Custom actions that the user can perform from the comment's header. When having multiple actions, consider grouping them in a nested menu system using a [EuiPopover](../../containers/popover.mdx) with a [EuiContextMenu](../../navigation/context-menu.mdx).
7.  `children`: A user message or any custom component.

</CommentListStyle>

The following demo shows how you can combine different props to create different types of comments events like a regular, update, update with a danger background and a custom one.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Timeline avatar

The timeline icon is a very important part of the comment:

*   By default, each **EuiComment** shows an avatar with the `user` icon. A `timelineAvatarAriaLabel`should be provided when using this default option.
*   You can customize your avatar by passing to the `timelineAvatar` any of the icon types that [EuiIcon](../icons/index.mdx) supports. The icon will show inside a `subdued` avatar. Consider this option when showing a system update. Providing a `timelineAvatarAriaLabel` is recommended.
*   You can further customize the timeline icon by passing to the `timelineAvatar` a [EuiAvatar](../avatar.mdx).

```tsx interactive
import React from 'react';
import {
  EuiCommentList,
  EuiComment,
  EuiCode,
  EuiText,
  EuiAvatar,
} from '@elastic/eui';

export default () => (
  <EuiCommentList aria-label="An example with different timeline icons">
    <EuiComment
      username="andred"
      timelineAvatarAriaLabel="Andre Diaz"
      event="is using a default avatar"
    >
      <EuiText size="s">
        <p>
          The avatar initials is generated from the <EuiCode>username</EuiCode>{' '}
          prop.
        </p>
      </EuiText>
    </EuiComment>

    <EuiComment
      username="system"
      timelineAvatarAriaLabel="System"
      timelineAvatar="dot"
      event={
        <>
          The <EuiCode>timelineAvatar</EuiCode> is using a{' '}
          <EuiCode>dot</EuiCode> icon.
        </>
      }
    />

    <EuiComment
      username="cat"
      timelineAvatarAriaLabel="Beautiful cat"
      event="is using a custom avatar"
      timelineAvatar={
        <EuiAvatar name="Cat" imageUrl="https://picsum.photos/id/40/64" />
      }
    >
      <EuiText size="s">
        <p>
          The <EuiCode>timelineAvatar</EuiCode> is using a custom{' '}
          <strong>EuiAvatar</strong>.
        </p>
      </EuiText>
    </EuiComment>
  </EuiCommentList>
);
```

## Comment event actions

There are scenarios where you might want to allow the user to perform `actions` related to each comment. Some common `actions` include: editing, deleting, sharing and copying. To add custom `actions` to a comment, use the `actions`prop. These will be placed to the right of the metadata in the comment's header. We recommend using a [EuiButtonIcon](../../navigation/buttons/button.mdx#icon) to trigger an action. When having multiple actions, consider grouping them in a nested menu system using a [EuiPopover](../../containers/popover.mdx) with a [EuiContextMenu](../../navigation/context-menu.mdx).

```
/* Detailed source-code truncated for AI context efficiency. */
```

## A comment system

The below example uses a list of **EuiComments**, a [EuiMarkdownEditor](../../editors-and-syntax/markdown/editor.mdx), and a [**EuiMarkdownFormat**](../../editors-and-syntax/markdown/format.mdx) to create a simple comment system.

*   Each comment renders in a **EuiComment**.
*   We use the **EuiMarkdownEditor** to post the `EuiComment.children`. This means the content uses Markdown.
*   When the new **EuiComment** is posted, we use the **EuiMarkdownFormat** to wrap the `EuiComment.children` and render the Markdown correctly.

When dealing with asynchronous events like posting a message we recommend setting the **EuiMarkdownEditor** to a `readOnly` state and the "Add comment" **EuiButton** to a `isLoading` state. This will ensure users understand that the content cannot be changed while the comment is being submitted.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Props

import docgen from '@elastic/eui-docgen/dist/components/comment_list';

<PropTable definition={docgen.EuiCommentList} />
<PropTable definition={docgen.EuiComment} />
<PropTable definition={docgen.EuiCommentEvent} />

---

### Packages Website Docs Components Display Empty Prompt Index (`packages/website/docs/components/display/empty-prompt/index.mdx`)

---
keywords: [EuiEmptyPrompt]
---

# Empty prompt

import illustrationUrl from '!url-loader!../../../../static/images/empty_prompt/illustration.svg';
import illustrationSource from '!raw-loader!../../../../static/images/empty_prompt/illustration.svg';

The **EuiEmptyPrompt** is the building block to create an empty state. You can use it as a placeholder for any type of empty content. They are especially helpful for replacing entire pages or parts of a product that contain no content.

## Component

While no one piece of content is required, each **EuiEmptyPrompt** should contain at least a `title` (wrapped in an HTML heading element) and/or a `description`. They usually contain one or more `actions` that promotes the primary call-to-actions. You can also provide a `footer` to direct users towards making informed decisions.

```tsx interactive
import React from 'react';
import { EuiEmptyPrompt, EuiButton, EuiTitle, EuiLink } from '@elastic/eui';

export default () => (
  <EuiEmptyPrompt
    iconType="logoSecurity"
    title={<h2>Start adding cases</h2>}
    body={<p>Add a new case or change your filter settings.</p>}
    actions={
      <EuiButton color="primary" fill>
        Add a case
      </EuiButton>
    }
    footer={
      <>
        <EuiTitle size="xxs">
          <h3>Want to learn more?</h3>
        </EuiTitle>
        <EuiLink href="#" target="_blank">
          Read the docs
        </EuiLink>
      </>
    }
  />
);
```
## Usage

### Less content, more actions

You can remove parts of the prompt to simplify it. You can also provide an array of multiple actions. Be sure to list primary actions first and secondary actions as empty buttons.

```tsx interactive
import React from 'react';
import { EuiEmptyPrompt, EuiButton, EuiButtonEmpty } from '@elastic/eui';

export default () => (
  <EuiEmptyPrompt
    title={<h2>Upgrade your license to use Machine Learning</h2>}
    actions={[
      <EuiButton color="primary" fill>
        Upgrade
      </EuiButton>,
      <EuiButtonEmpty color="primary">Start a trial</EuiButtonEmpty>,
    ]}
  />
);
```
### Panel options

The **EuiEmptyPrompt** is wrapped by [EuiPanel](../../containers/panel/index.mdx). By default, the panel is set to `transparent` but you can customize other panel options like `color`, `hasBorder` and `paddingSize`. Changing the `color` prop will also attempt to adjust the `iconColor` and `footer` color.

Read the [usage guidelines](#guidelines) to better understand when to use certain panel props.

```tsx interactive
import React, { FunctionComponent } from 'react';
import {
  EuiEmptyPrompt,
  EuiButton,
  EuiTitle,
  EuiLink,
  EuiEmptyPromptProps,
} from '@elastic/eui';

export default ({ color }: { color: EuiEmptyPromptProps['color'] }) => {
  return (
    <EuiEmptyPrompt
      iconType="securityAnalyticsApp"
      title={<h2>Start adding cases</h2>}
      color={color}
      body={<p>Add a new case or change your filter settings.</p>}
      actions={
        <EuiButton color="primary" fill>
          Add a case
        </EuiButton>
      }
      footer={
        <>
          <EuiTitle size="xxs">
            <h3>Want to learn more?</h3>
          </EuiTitle>
          <EuiLink href="#" target="_blank">
            Read the docs
          </EuiLink>
        </>
      }
    />
  );
};
```

### Title sizes and icon colors

Other customization options include changing the`titleSize` to any of the [EuiTitle sizes](../title.mdx) and `iconColor`. When using an application or solution logo as the `iconType`, you can reset to the multi-tone colors with `iconColor="default"`

```tsx interactive
import React from 'react';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';

export default () => (
  <EuiEmptyPrompt
    iconType="securityAnalyticsApp"
    iconColor="default"
    title={<h2>Start adding cases</h2>}
    titleSize="xs"
    body={<p>Add a new case or change your filter settings.</p>}
    actions={
      <EuiButton size="s" color="primary" fill>
        Add a case
      </EuiButton>
    }
  />
);
```

### Loading and error prompts

Empty prompts can also be used to emulate loading and error states, by utilizing the same patterns.

For **loading** states, instead of passing a `iconType`, you can provide a custom `icon` and pass in one of our [loading components](../loading.mdx).

```tsx interactive
import React from 'react';
import { EuiEmptyPrompt, EuiLoadingLogo } from '@elastic/eui';

export default () => (
  <EuiEmptyPrompt
    icon={<EuiLoadingLogo logo="logoKibana" size="xl" />}
    title={<h2>Loading Dashboards</h2>}
  />
);
```

For **error** states, you can simply set the `color` to `danger`.

```tsx interactive
import React from 'react';
import { EuiEmptyPrompt } from '@elastic/eui';

export default () => (
  <EuiEmptyPrompt
    iconType="error"
    color="danger"
    title={<h2>Unable to load your dashboards</h2>}
    body={
      <p>
        There was an error loading the Dashboard application. Contact your
        administrator for help.
      </p>
    }
  />
);
```

### Layout

You can supply a `layout` of either `"horizontal"` or `"vertical"` with the default being `vertical`. When creating empty states we want the content to be short and straight to the point. So most of the time, the `vertical` layout is enough. All the content will be center aligned and this type of text alignment only works with small content.

When you have longer body text with multiple calls to action, you can use the `horizontal` layout. This layout works best when you can provide a larger graphic like an illustration as the `icon`. For consistency, we recommend providing the illustration using a [EuiImage](../image.mdx) with `size="fullWidth"`.

<Demo scope={{ illustration: illustrationUrl }} extraFiles={{ 'illustration.svg': illustrationSource }}>
  ```tsx
  import React from 'react';
  import {
    EuiEmptyPrompt,
    EuiButton,
    EuiTitle,
    EuiLink,
    EuiImage,
  } from '@elastic/eui';
  import illustration from './illustration.svg';

  export default () => {
    return (
      <>
        <EuiEmptyPrompt
          icon={<EuiImage size="fullWidth" src={illustration} alt="" />}
          title={<h2>Create your first visualization</h2>}
          layout="horizontal"
          color="plain"
          body={
            <>
              <p>
                There are no visualizations to display. This tool allows you to
                create a wide range of charts, graphs, maps, and other graphics.
              </p>
              <p>
                The visualizations you create can be easily shared with your
                peers.
              </p>
            </>
          }
          actions={
            <EuiButton color="primary" fill>
              Create visualization
            </EuiButton>
          }
          footer={
            <>
              <EuiTitle size="xxs">
                <span>Want to learn more?</span>
              </EuiTitle>{' '}
              <EuiLink href="#" target="_blank">
                Read the docs
              </EuiLink>
            </>
          }
        />
      </>
    );
  };
  ```
</Demo>

### More types of empty states

**EuiEmptyPrompt** can be used for more than just **empty** pages. The following example showcases different types of empty states that you can create with the **EuiEmptyPrompt**. For a full list see the [usage guidelines](#guidelines).

import MultipleTypes from './_multiple_types';

<MultipleTypes />

### Using in a page template

When using a **EuiEmptyPrompt** in a [EuiPageTemplate](../../templates/page-template/index.mdx), we recommend using the namespaced component so the template can determine which how to display the empty prompt based on the rest of the template configuration.

The following example shows the usage of the [EuiPageTemplate.EmptyPrompt](../../templates/page-template/index.mdx#empty-pages-or-content) namespaced component.

<Demo scope={{ illustration: illustrationUrl }} extraFiles={{ 'illustration.svg': illustrationSource }}>
  ```tsx
  import React from 'react';
  import {
    EuiPageTemplate,
    EuiButton,
    EuiTitle,
    EuiLink,
    EuiImage,
  } from '@elastic/eui';
  import illustration from './illustration.svg';

  export default () => (
    <EuiPageTemplate minHeight="0">
      <EuiPageTemplate.EmptyPrompt
        title={<h2>Create your first visualization</h2>}
        icon={<EuiImage size="fullWidth" src={illustration} alt="" />}
        color="plain"
        layout="horizontal"
        body={
          <>
            <p>
              There are no visualizations to display. This tool allows you to
              create a wide range of charts, graphs, maps, and other graphics.
            </p>
            <p>
              The visualizations you create can be easily shared with your peers.
            </p>
          </>
        }
        actions={
          <EuiButton color="primary" fill>
            Create visualization
          </EuiButton>
        }
        footer={
          <>
            <EuiTitle size="xxs">
              <span>Want to learn more?</span>
            </EuiTitle>{' '}
            <EuiLink href="#" target="_blank">
              Read the docs
            </EuiLink>
          </>
        }
      />
    </EuiPageTemplate>
  );
  ```
</Demo>

You can then tie multiple types of empty states together to create a seamless loading to empty or loading to error experience. The following example shows how to incorporate these states with [EuiPageTemplate.EmptyPrompt](../../templates/page-template/index.mdx#empty-pages-or-content).

{/* setting a fixed `height` to avoid jumps on the page as the state changes */}
<Demo previewWrapper={({ children }) => (
  <div style={{ height: 460 }}>{children}</div>
)}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Guidelines

import Guidelines from './_guidelines.mdx';

<Guidelines />

## Props

import docgen from '@elastic/eui-docgen/dist/components/empty_prompt';

<PropTable definition={docgen.EuiEmptyPrompt} />

---

### Packages Website Docs Components Display Icons Index (`packages/website/docs/components/display/icons/index.mdx`)

---
keywords: [EuiIcon]
---

# Icons

import { EuiCodeBlock, EuiSpacer, EuiSplitPanel, EuiToken } from '@elastic/eui';

**EuiIcon** is a handy component for using our custom glyphs and logos. The `type` prop accepts either an enumerated name from one of the sets below, a location to a custom SVG asset, or a React Element.

## Component

```tsx interactive
import React from 'react';
import { EuiIcon } from '@elastic/eui';

export default () => <EuiIcon type="grid" />;
```

:::accessibility Accessibility recommendation
If possible, provide a descriptive title based on the icon use. If no title is provided, the icon is considered purely decorative, and it will default to `aria-hidden=true`.
:::

## All icons

### Glyphs

Glyphs are small, monochromatic icons that typically should always use the default size of `size="m"`. They are named according to their appearance or the action they represent. For example, `star`, `play`, etc.

If you would like to contribute to our growing list of glyphs, you can follow [these guidelines](https://github.com/elastic/eui/blob/main/wiki/contributing-to-eui/developing/creating-icons.md).

import { IconSearch } from '@site/src/components/display/icons';
import {
  typeToPathMapDocsGlyphIconTypes as iconTypes,
  typeToPathMapSynonyms as iconSynonyms,
} from '../../../../../eui/src/components/icon/icon_map';

<Demo
  scope={{
    iconTypes,
    iconSynonyms,
    IconSearch,
  }}
>
  ```tsx
  import React from 'react';
  import { css } from '@emotion/react';
  import { EuiCodeBlock, EuiSpacer } from '@elastic/eui';
  import { IconSearch } from '@site/src/components/display/icons';
  import {
    typeToPathMapDocsGlyphIconTypes as iconTypes,
    typeToPathMapSynonyms as iconSynonyms,
  } from '../../../../../eui/src/components/icon/icon_map';

  export default () => (
    <div css={css`height: fit-content;`}>
      <EuiCodeBlock language="tsx" isCopyable paddingSize="m">
        {'<EuiIcon type="warning" />'}
      </EuiCodeBlock>
      <EuiSpacer />
      <IconSearch iconTypes={iconTypes} iconSynonyms={iconSynonyms} />
    </div>
  );
  ```
</Demo>

### Elastic logos

These logos are restricted in use to Elastic products or when referencing Elastic products. They are multi-color with some internal paths having a class of `.euiIcon__fillNegative` to handle flipping colors for dark mode. The only other colors most of them support are ghost and text which turn them into a solid shape.

import { typeToPathMapDocsLogoIconTypes as iconTypesLogos } from '../../../../../eui/src/components/icon/icon_map';

<Demo scope={{ iconTypes: iconTypesLogos, IconSearch }} previewPadding="none">
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

### Apps

App logos are logos for Elastic Apps, and can contain multiple colors. Normally the Elastic Design team creates those icons. They are not meant to be used outside of Elastic, because they represent our apps. App logos are usually displayed at `32x32` or above and can contain multiple colors.

Our set of App Icons are a subset of what the [Elastic Design team provides](https://brand.elastic.co/302f66895/p/031452-icons). If you require an icon from that set which EUI does not currently provide, please open a [Feature Request](https://github.com/elastic/eui/issues) for the EUI team to add it.

import { typeToPathMapDocsAppIconTypes as iconTypesApps } from '../../../../../eui/src/components/icon/icon_map';

<Demo scope={{ iconTypes: iconTypesApps, IconSearch }}>
  ```tsx
  import React from 'react';
  import { css } from '@emotion/react';
  import { EuiCodeBlock, EuiSpacer } from '@elastic/eui';
  import { IconSearch } from '@site/src/components/display/icons';
  import { typeToPathMapDocsAppIconTypes as iconTypes } from '../../../../../eui/src/components/icon/icon_map';

  export default () => (
    <div css={css`height: fit-content;`}>
      <EuiCodeBlock language="tsx" isCopyable paddingSize="m">
        {'<EuiIcon type="addDataApp" size="xl" />'}
      </EuiCodeBlock>
      <EuiSpacer />
      <IconSearch iconTypes={iconTypes} placeholder="Search app logos" iconSize="xl" />
    </div>
  );
  ```
</Demo>

### Machine learning icons

Machine learning has some specific icons for job creation. Again, these are made for `32x32`.

import { typeToPathMapDocsMlIconTypes as iconTypesML } from '../../../../../eui/src/components/icon/icon_map';

<Demo scope={{ iconTypes: iconTypesML, IconSearch }}>
  ```tsx
  import React from 'react';
  import { css } from '@emotion/react';
  import { EuiCodeBlock, EuiSpacer } from '@elastic/eui';
  import { IconSearch } from '@site/src/components/display/icons';
  import { typeToPathMapDocsMlIconTypes as iconTypes } from '../../../../../eui/src/components/icon/icon_map';

  export default () => (
    <div css={css`height: fit-content;`}>
      <EuiCodeBlock language="tsx" isCopyable paddingSize="m">
        {'<EuiIcon type="addDataApp" size="xl" />'}
      </EuiCodeBlock>
      <EuiSpacer />
      <IconSearch
        iconTypes={iconTypes}
        placeholder="Search machine learning app logos"
        iconSize="xl"
      />
    </div>
  );
  ```
</Demo>


## Usage

### Sizes

Use the `size` prop to automatically size your icons. Medium is the default, and will output a `16x16` icon.

import { iconSizes, iconSizesText } from './icon_sizes';
import iconSizeSource from '!raw-loader!./icon_sizes';

<Demo scope={{ iconSizes, iconSizesText }} extraFiles={{ 'icon_sizes.ts': iconSizeSource }}>
  ```tsx
  import React from 'react';
  import { css } from '@emotion/react';
  import { EuiCodeBlock, EuiSpacer, EuiFlexGrid, EuiFlexItem, EuiCopy, EuiPanel, EuiIcon } from '@elastic/eui';
  import { iconSizes, iconSizesText } from './icon_sizes';

  export default () => (
    <div css={css`height: fit-content;`}>
      <EuiCodeBlock language="tsx" isCopyable paddingSize="m">
        {'<EuiIcon type="logoElasticsearch" size="xl" />'}
      </EuiCodeBlock>
      <EuiSpacer />
      <EuiFlexGrid direction="row" columns={3}>
        {iconSizes.map((size, index) => (
          <EuiFlexItem key={size}>
            <EuiCopy textToCopy={size} afterMessage={`${size} copied`} tooltipProps={{ display: 'block' }}>
              {(copy) => (
                <EuiPanel hasShadow={false} hasBorder={false} onClick={copy} paddingSize="s">
                  <EuiIcon className="eui-alignMiddle" type="logoElasticsearch" size={size} /> &emsp;{' '}
                  <small>{iconSizesText[index]}</small>
                </EuiPanel>
              )}
            </EuiCopy>
          </EuiFlexItem>
        ))}
      </EuiFlexGrid>
    </div>
  );
  ```
</Demo>

### Colors

The default behavior of icons is to inherit from the text color. You can use the `color` prop to assign a custom color which accepts a named color from our palette or a valid [CSS color data type](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) which will be passed down through the inline-style `fill`  property. **We recommend relying on the EUI named color palette** unless the custom color is initiated by the user (like as a graph color).

Two-tone icons, like our app style icons, will behave similarly to normal glyphs when provided a specific color by applying the color to **all** the shapes within. You can force the icon to match the parent's text color by passing `color="inherit"` to the icon.

import { iconColors } from './icon_colors.ts'
import iconColorsSource from '!raw-loader!./icon_colors';

<Demo scope={{ iconColors }} extraFiles={{ 'icon_colors.ts': iconColorsSource }}>
  ```tsx
  import React from 'react';
  import { css } from '@emotion/react';
  import { EuiCodeBlock, EuiSpacer, EuiFlexGrid, EuiFlexItem, EuiCopy, EuiPanel, EuiIcon, EuiThemeProvider } from '@elastic/eui';
  import { iconColors } from './icon_colors';

  export default () => (
    <div css={css`height: fit-content;`}>
      <EuiCodeBlock language="tsx" isCopyable paddingSize="m">
        {'<EuiIcon type="brush" color="primary" />'}
      </EuiCodeBlock>
      <EuiSpacer />
      <EuiFlexGrid direction="row" columns={3}>
        {iconColors.map((color) => (
          <EuiFlexItem key={color}>
            <EuiCopy textToCopy={color} afterMessage={`${color} copied`} tooltipProps={{ display: 'block' }}>
              {(copy) => {
                const panel = (
                  <EuiPanel hasShadow={false} hasBorder={false} onClick={copy} paddingSize="s">
                    <EuiIcon className="eui-alignMiddle" type="brush" color={color} /> &emsp;{' '}
                    <small>{color}</small>
                  </EuiPanel>
                );
                return color === 'ghost'
                  ? <EuiThemeProvider colorMode="DARK">{panel}</EuiThemeProvider>
                  : panel;
              }}
            </EuiCopy>
          </EuiFlexItem>
        ))}
      </EuiFlexGrid>
    </div>
  );
  ```
</Demo>


### Custom SVGs

The `type` prop can accept a valid enum, string or React SVG Element. When using a custom SVG, please make sure it sits on a square canvas and preferably utilizes one of EUI's sizes (`16x16` or `32x32`).

When using custom SVGs for simple glyphs, **remove all fill attributes** on the SVG and utilize the CSS helpers if you have complex logos that need to work with theming.

:::warning Important considerations when importing SVGs as components

When importing an SVG as a component like `import { ReactComponent as ReactLogo } from './logo.svg';`, keep in mind that the component will not support the `title` prop. The `title` prop is designed to only work with our icons or SVGs imported as images or passed as a Data URL. So, if you're importing your SVG as a component, be sure to use an`aria-label` instead of a `title` prop to enhance accessibility and avoid potential issues.

:::

import customSvg from '!url-loader!./custom.svg';
import customSvgSource from '!raw-loader!./custom.svg';

<Demo scope={{ customSvg }} extraFiles={{ 'custom.svg': customSvgSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

### Using icons outside of React

EUI publishes raw SVG files and a JSON manifest for consumers who need to use icons outside of the React component layer - for example, to generate canvas images, produce CSS background images at build time, or render icons in non-React environments.

**Individual SVG files** are available under `@elastic/eui/dist/svgs/`. For example:

```
@elastic/eui/dist/svgs/accessibility.svg
@elastic/eui/dist/svgs/tokens/tokenAlias.svg
```

**JSON manifest** (`@elastic/eui/dist/eui-icons.json`) maps icon filename stems to their raw SVG content strings:

```js
import icons from ‘@elastic/eui/dist/eui-icons.json’;
const svg = icons[‘accessibility’];         // plain glyph
const tokenSvg = icons[‘tokens/tokenAlias’]; // token icon
```

:::warning Server-side and build-time use only
`eui-icons.json` is intended for **server-side or build-time use** (e.g. Node.js scripts, SSR, canvas rasterization). Importing it in client-side code will inline all SVG strings into your JavaScript bundle.
:::


## Tokens

Tokens are most commonly used to visually signify field or code types. An **EuiToken** accepts any valid **EuiIcon** as its `iconType` property. However, icons designed specifically for use in the **EuiToken** are prefixed with "token" in their name and have pre-defined styles.

import { typeToPathMapDocsTokenIconTypes as iconTypesTokens } from '../../../../../eui/src/components/icon/icon_map';

<Demo scope={{ iconTypes: iconTypesTokens, IconSearch }}>
  ```tsx
  import React from 'react';
  import { css } from '@emotion/react';
  import { EuiCodeBlock, EuiSpacer, EuiToken } from '@elastic/eui';
  import { IconSearch } from '@site/src/components/display/icons';
  import { typeToPathMapDocsTokenIconTypes as iconTypes } from '../../../../../eui/src/components/icon/icon_map';

  export default () => (
    <div css={css`height: fit-content;`}>
      <EuiCodeBlock language="tsx" isCopyable paddingSize="m">
        {'<EuiToken iconType="tokenAlias" />'}
      </EuiCodeBlock>
      <EuiSpacer />
      <IconSearch
        iconTypes={iconTypes}
        placeholder="Search token icons"
        renderIcon={(iconType) => (
          <EuiToken className="eui-alignMiddle" iconType={iconType} />
        )}
      />
    </div>
  );
  ```
</Demo>


### Custom tokens

By default, an `iconType` with the token prefix (i.e. those listed above) will have predefined styles. However, any valid `iconType` can be passed and, in either case, the `shape`, `size`, `color`, and `fill` can be customized.

<EuiSplitPanel.Outer hasShadow={false} hasBorder direction="row">
  <EuiSplitPanel.Inner grow={false} style={{ minWidth: 96 }} className="eui-textCenter">
    <EuiToken iconType="tokenStruct" size="xs" color="gray" />
  </EuiSplitPanel.Inner>
  <EuiSplitPanel.Inner paddingSize="none" color="subdued">
    <EuiCodeBlock language="tsx" isCopyable transparentBackground paddingSize="m">
      {'<EuiToken iconType="tokenStruct" size="xs" color="gray" />'}
    </EuiCodeBlock>
  </EuiSplitPanel.Inner>
</EuiSplitPanel.Outer>

<EuiSpacer />
<EuiSplitPanel.Outer hasShadow={false} hasBorder direction="row">
  <EuiSplitPanel.Inner grow={false} style={{ minWidth: 96 }} className="eui-textCenter">
    <EuiToken iconType="tokenStruct" fill="none" />
  </EuiSplitPanel.Inner>
  <EuiSplitPanel.Inner paddingSize="none" color="subdued">
    <EuiCodeBlock language="tsx" isCopyable transparentBackground paddingSize="m">
      {'<EuiToken iconType="tokenStruct" fill="none" />'}
    </EuiCodeBlock>
  </EuiSplitPanel.Inner>
</EuiSplitPanel.Outer>

<EuiSpacer />
<EuiSplitPanel.Outer hasShadow={false} hasBorder direction="row">
  <EuiSplitPanel.Inner grow={false} style={{ minWidth: 96 }} className="eui-textCenter">
    <EuiToken iconType="tokenStruct" size="m" shape="circle" color="#b9f6c8" />
  </EuiSplitPanel.Inner>
  <EuiSplitPanel.Inner paddingSize="none" color="subdued">
    <EuiCodeBlock language="tsx" isCopyable transparentBackground paddingSize="m">
      {'<EuiToken iconType="tokenStruct" size="m" shape="circle" color="#b9f6c8" />'}
    </EuiCodeBlock>
  </EuiSplitPanel.Inner>
</EuiSplitPanel.Outer>

<EuiSpacer />
<EuiSplitPanel.Outer hasShadow={false} hasBorder direction="row">
  <EuiSplitPanel.Inner grow={false} style={{ minWidth: 96 }} className="eui-textCenter">
    <EuiToken iconType="faceHappy"  />
  </EuiSplitPanel.Inner>
  <EuiSplitPanel.Inner paddingSize="none" color="subdued">
    <EuiCodeBlock language="tsx" isCopyable transparentBackground paddingSize="m">
      {'<EuiToken iconType="faceHappy"  />'}
    </EuiCodeBlock>
  </EuiSplitPanel.Inner>
</EuiSplitPanel.Outer>

<EuiSpacer />
<EuiSplitPanel.Outer hasShadow={false} hasBorder direction="row">
  <EuiSplitPanel.Inner grow={false} style={{ minWidth: 96 }} className="eui-textCenter">
    <EuiToken iconType="faceHappy" size="l" color="euiColorVis7" shape="rectangle" fill="dark" />
  </EuiSplitPanel.Inner>
  <EuiSplitPanel.Inner paddingSize="none" color="subdued">
    <EuiCodeBlock language="tsx" isCopyable transparentBackground paddingSize="m">
      {'<EuiToken iconType="faceHappy" size="l" color="euiColorVis7" shape="rectangle" fill="dark" />'}
    </EuiCodeBlock>
  </EuiSplitPanel.Inner>
</EuiSplitPanel.Outer>


## Props

import docgen from '@elastic/eui-docgen/dist/components/icon';

<PropTable definition={docgen.EuiIcon} />

---

### Packages Website Docs Components Display Illustrations Index (`packages/website/docs/components/display/illustrations/index.mdx`)

---
keywords: [EuiIllustration, illustrations, svg]
---

# Illustrations

**EuiIllustration** renders theme-adaptive SVGs. Each illustration ships a `light` and a `dark` variant
and the component inlines the one that matches the current theme.

SVGs are sourced from [`@elastic/eui-illustrations`](https://github.com/elastic/eui/tree/main/packages/illustrations),
a standalone package that is **independently versioned and published** from `@elastic/eui`. This means the catalog
can grow and change without an `@elastic/eui` release.

## Component

Pass an illustration asset to the `type` prop. The component picks the correct color-mode variant automatically,
so try toggling the theme in the top toolbar.

import { illustrations } from '@elastic/eui-illustrations';

<Demo scope={illustrations}>
  ```tsx
  import React from 'react';
  import { EuiIllustration } from '@elastic/eui';
  import { dashboard } from '@elastic/eui-illustrations';
  import { css } from '@emotion/react';

  export default () => (
    <div css={css({ maxWidth: 360 })}>
      <EuiIllustration type={dashboard} />
    </div>
  );
  ```
</Demo>

:::accessibility Accessibility recommendation
The accessible label defaults to the illustration's `title`. Provide a more specific `alt` when the illustration conveys meaning
or pass `alt=""` to mark it as purely decorative (it will be hidden from assistive technology).
:::

## All illustrations

Search the full catalog exported from `@elastic/eui-illustrations`. Select an illustration to reveal the code.

import { IllustrationGallery } from './illustration_gallery';

<IllustrationGallery />

## Props

import docgen from '@elastic/eui-docgen/dist/components/illustration';

<PropTable definition={docgen.EuiIllustration} />

---

### Packages Website Docs Components Display Toast Index (`packages/website/docs/components/display/toast/index.mdx`)

---
keywords: [EuiToast, EuiGlobalToastList]
---

# Toast

import previewWrapper from './_preview_wrapper';

**EuiToast** allows for small notes that appear in the bottom right of the screen. They should be used for ephemeral, live actions (think **save complete** or **something just finished right now**).

They should not be used for historical actions (**your report built 30 minutes ago**). This means that a user should never be greeted with toasts when starting a session. Toasts should be brief and avoid long paragraphs of text or titling.

## Component

<Demo previewWrapper={previewWrapper}>
  ```tsx interactive
  import React from 'react';
  import { EuiToast } from '@elastic/eui';

  export default () => (
    <EuiToast
      title="Example of a good toast"
      text="A good toast message is short and to the point. It should very rarely span multiple lines."
      onClose={() => {}}
    />
  );
  ```
</Demo>

## Usage

### Toast list

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Colors

Each `color` variant displays a specific visual type toast and renders by default a corresponding icon. 

* Use `primary` for general information.
* Use `success` to let the user know that something completed successfully. Show a success message when the program detects that **something completed successfully**. 
* Use `warning` to warn the user against decisions they might regret. Show a warning message when the program detects that **something is not behaving right, but it didn't cause any termination.** 
* Use `danger` to let the user know that something went wrong. For example if you want to communicate an error. You should show an error message when the issue is **terminal, this doesn't always mean that the operation stops completely, but the task is not complete**. 

If you need to use a custom icon, use the `iconType` prop to override it.

<Demo previewWrapper={previewWrapper}>
  ```tsx interactive
  import React from 'react';
  import { EuiToast, EuiSpacer } from '@elastic/eui';

  export default () => (
    <>
      <EuiToast
        title="3 new messages"
        color="primary"
      />
      <EuiSpacer size="s" />
      <EuiToast
        title="Your report is complete"
        color="success"
      />
      <EuiSpacer size="s" />
      <EuiToast
        title="Node 726 is having trouble"
        color="warning"
      />
      <EuiSpacer size="s" />
      <EuiToast
        title="Couldn't complete the search"
        color="danger"
      />
      
    </>
  );
  ```
</Demo>

### Actions

Use `actionProps` to add a primary and an optional secondary action. A standalone secondary action without a primary is not supported.

<Demo previewWrapper={previewWrapper}>
  ```tsx interactive
  import React from 'react';
  import { EuiToast } from '@elastic/eui';

  export default () => (
    <EuiToast
      title="Created report for dashboard 'Tuba Sales by Region'"
      color="success"
      text="Your export has finished processing."
      actionProps={{
        primary: { children: 'Download' },
        secondary: { children: 'Dismiss' },
      }}
    />
  );
  ```
</Demo>

### Countdown animation

To show a countdown animation on top of the toast to indicate the remaining time until it dismisses, use `animationMs`.

<Demo previewWrapper={previewWrapper}>
  ```tsx interactive
  import React, { useEffect, useState } from 'react';
  import { EuiToast, EuiButton, EuiFlexGroup } from '@elastic/eui';

  const ANIMATION_MS = 6000;

  export default () => {
    const [animationMs, setAnimationMs] = useState<number | undefined>(undefined);

    useEffect(() => {
      setAnimationMs(ANIMATION_MS);
    }, []);

    return (
      <EuiFlexGroup direction="column" gutterSize="m">
        <EuiButton
          style={{ maxInlineSize: 'max-content' }}
          onClick={() => setAnimationMs(animationMs != null ? undefined : ANIMATION_MS)}
        >
          {animationMs != null ? 'Reset animation' : 'Start animation'}
        </EuiButton>
        <EuiToast
          title="Your report is complete"
          color="success"
          text="A short toast text"
          animationMs={animationMs}
          onClose={() => {}}
        />
      </EuiFlexGroup>
    );
  };
  ```
</Demo>

## Guidelines

import Guidelines from './_guidelines.mdx';

 <Guidelines />

## Props

import docgen from '@elastic/eui-docgen/dist/components/toast';

<PropTable definition={docgen.EuiToast} />

<PropTable definition={docgen.EuiGlobalToastList} />

<PropTable definition={docgen.EuiGlobalToastListItem} />

---

### Packages Website Docs Components Display Tour Index (`packages/website/docs/components/display/tour/index.mdx`)

---
keywords: [EuiTour, EuiTourStep, useEuiTour]
---

# Tour

The tour components provided by EUI allow for a flexible and customizable way to showcase items on a page in an ordered manner by augmenting existing elements on the page without altering functionality.

:::note
Examples on this page use `localStorage` to persist state.
:::

## Usage

### Wrap target element

The **EuiTourStep** component is the base for building a feature tour or an individual popover for onboarding.

All content and actions including titles, headings, and buttons are customizable via props.

```tsx interactive
import React, { useState } from 'react';
import { EuiButtonEmpty, EuiFieldText, EuiText, EuiSpacer, EuiTourStep } from '@elastic/eui';

export default () => {
  const [isOpen, setIsOpen] = useState(false);

  const beginTour = () => {
    setIsOpen(true);
  };

  return (
    <div>
      <EuiButtonEmpty size="s" flush="left" iconType="refresh" onClick={beginTour}>
        Begin tour
      </EuiButtonEmpty>
      <EuiSpacer size="m" />
      <EuiTourStep
        content={
          <EuiText size="s">
            <p>The tour step content.</p>
          </EuiText>
        }
        isStepOpen={isOpen}
        minWidth={300}
        onFinish={() => setIsOpen(false)}
        step={1}
        stepsTotal={1}
        title="Title of the current step"
        subtitle="Title of the full tour (optional)"
        anchorPosition="rightCenter"
        zIndex={1}
      >
        <EuiFieldText
          placeholder="Placeholder text"
        />
      </EuiTourStep>
    </div>
  );
};
```

### Anchor to DOM element

Instead of wrapping the target element, use the `anchor` prop to specify a DOM node. Accepted values include an HTML element reference, a function returning an HTML element, or a CSS selector string such as `anchor="#anchorTarget"`.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Guided tour

Users proceed through tour steps without needing to complete actions on the underlying page. In this scenario, consider showing both **Close tour** and **Next** buttons.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Standalone steps

Each **EuiTourStep** can be configured independently via props. In this case, each component is stateless and needs to be paired with some form of state management for navigation. The later examples showcase other ways to handle state management via **useEuiTour** and **EuiTour**.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### useEuiTour hook

The **useEuiTour** hook provides minimal state management using a predefined React reducer. Pass an array of steps consisting of accepted props, and an object of global configuration. The result is a full configuration object for each step, a set of reducer actions to perform state changes, and an up-to-date state object derived from the internal reducer.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### EuiTour render prop component

The **EuiTour** render prop component provides minimal state management. An alternative to the **useEuiTour** hook, **EuiTour** can be used for React class components and use cases with a single wrapping component.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Tour demo

A complete tour set in a more realistic application UI. Unlike other examples on this page, the demo does not use `localStorage` to persist state.

```
/* Detailed source-code truncated for AI context efficiency. */
```
## Guidelines

import Guidelines from './_guidelines.mdx';

<Guidelines />

## Props

import docgen from '@elastic/eui-docgen/dist/components/tour';

<PropTable definition={docgen.EuiTourStep} />
<PropTable definition={docgen.EuiTourStepIndicator} />
<PropTable definition={docgen.EuiTour} />

---

### Packages Website Docs Components Forms Selection Overview (`packages/website/docs/components/forms/selection/overview.mdx`)

---
sidebar_position: 1
---

# Component comparison

```mdx-code-block
import { EuiIconTip, EuiTable, EuiTableRow, EuiTableHeader, EuiTableBody, EuiTableRowCell, EuiTableHeaderCell } from '@elastic/eui';
```

EUI currently offers over 4 ways to select an option from a list (6 including checkboxes and radios).

Choosing the right selection component may seem tricky at first - with so many similar options, it can feel overwhelming figuring out which component to use. This comprehensive guide will help you decide which component to use and when, including detailed explanations and comparisons for each component.

## Summary

When choosing a selection component, consider these key factors:

- **Number of options**: small sets (\<7) work well with radio/checkbox groups, medium sets (\<12) with [EuiSelect](./basic-select.mdx), and larger sets need search functionality.
- **Selection type**: single vs. multiple selection requirements.
- **Display needs**: whether you need custom option rendering or simple text options.
- **User input**: whether users should be able to add custom values.
- **Accessibility**: native components ([EuiSelect](./basic-select.mdx), radio/checkbox groups) are generally more accessible.
- **Visual layout**: horizontal pills ([EuiComboBox](./combo-box.mdx)) vs. vertical lists ([EuiSelectable](./selectable.mdx)).

For most use cases, start with the simpler native components ([EuiSelect](./basic-select.mdx), [EuiRadioGroup](./radio-and-radio-group.mdx#radio-group), [EuiCheckboxGroup](./checkbox-and-checkbox-group.mdx#checkbox-group)) and only move to more complex components when you need their specific features.

## Which selection component should I use?

The following decision tree will help you choose the right component based on your specific needs.

### Single selection

- When you have a small set of options (\<7) and all options are equally important in terms of visibility, use [EuiRadioGroup](./radio-and-radio-group.mdx#radio-group).
- When you have a small set of options (\<12) and only the current selected option has UI importance, reach for [EuiSelect](./basic-select.mdx) first when possible, over other more complex selection components.
    - **EuiSelect** renders a basic HTML `<select>` element, providing the best cross-browser and cross-device affordances (particularly for mobile devices).
    - Native form controls are more familiar to end users due to their ubiquity across the internet.
- When you have a small set of options (\<12) _and_ if you need to customize how the options are rendered and selected, use [EuiSuperSelect](./super-select.mdx).
    - **EuiSuperSelect** gives you control over option display through the `dropdownDisplay` prop, allowing for multi-line option text or descriptions.
    - We recommend reaching for **EuiSuperSelect** only if custom option display is absolutely necessary, as **EuiSelect** is natively more accessible.
- Large sets of options (\>12) should use a selection component that supports searching/filtering options. This requires the use of one of the more advanced multiselect components with `singleSelection` set.

### Multiple selections

- When you have a small set of options (\<7), and all options are equally important in terms of visibility, use [EuiCheckboxGroup](./checkbox-and-checkbox-group.mdx#checkbox-group).
- In general, we recommend using [EuiSelectable](./selectable.mdx) for most multi-selection purposes. It renders a searchable, vertically-oriented list with icons next to the option representing selection state.
    - **EuiSelectable** can optionally be rendered with a search box for filtering through many options, or as just a list for fewer options.
    - **EuiSelectable** is by far our most accessible and flexible selection component (although customization may require extra development). It can be used within popovers and flyouts, or as a standalone list.
    - If you need the ability to exclude options, **EuiSelectable** is the only component that offers that functionality.
- In general, for multi-select scenarios, we recommend using [EuiComboBox](./combo-box.mdx) over [EuiSelectable](./selectable.mdx) primarily when selections should be immediately visible and unselected options should not. Selections are rendered as a horizontally-oriented list of pills.
    - **EuiComboBox** allows users to search through a list of dropdown options. This functionality is core to the component and cannot be removed, unlike **EuiSelectable**.
    - If you need the ability to dynamically add custom user-generated input outside of the available options, **EuiComboBox** is the only component that offers that functionality.

## Feature comparison chart

Below is a handy reference for comparing the selection components.

```mdx-code-block
export const tooltipProps = {
  anchorProps: { css: { position: 'absolute', marginBlockStart: -1 } },
  color: 'subdued',
};
```

<EuiTable>
  <EuiTableHeader>
    <EuiTableHeaderCell>Feature</EuiTableHeaderCell>
    <EuiTableHeaderCell align="center">[EuiSelect](./basic-select.mdx)</EuiTableHeaderCell>
    <EuiTableHeaderCell align="center">[EuiSuperSelect](./super-select.mdx)</EuiTableHeaderCell>
    <EuiTableHeaderCell align="center">[EuiSelectable](./selectable.mdx)</EuiTableHeaderCell>
    <EuiTableHeaderCell align="center">[EuiComboBox](./combo-box.mdx)</EuiTableHeaderCell>
  </EuiTableHeader>
  <EuiTableBody>
    <EuiTableRow>
      <EuiTableRowCell>Select a single option</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Select multiple options</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Accepts custom values from user input</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Option exclusion</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Customizable option display</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Customizable loading/error messages</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Searchable</EuiTableRowCell>
      <EuiTableRowCell align="center">
        ❌&nbsp;<EuiIconTip type="info" content="Native select behavior will jump to options based on user typing" {...tooltipProps} />
      </EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>`disabled` state</EuiTableRowCell>
      <EuiTableRowCell align="center">
        ✅&nbsp;<EuiIconTip type="info" content="Disables whole component" {...tooltipProps} />
      </EuiTableRowCell>
      <EuiTableRowCell align="center">
        ✅&nbsp;<EuiIconTip type="info" content="Disables individual option" {...tooltipProps} />
      </EuiTableRowCell>
      <EuiTableRowCell align="center">
        ✅&nbsp;<EuiIconTip type="info" content="Disables individual option" {...tooltipProps} />
      </EuiTableRowCell>
      <EuiTableRowCell align="center">
        ✅&nbsp;<EuiIconTip type="info" content="Disables whole component" {...tooltipProps} />
      </EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>`readOnly` state</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Built in utility function for clearing user input</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">
        ✅&nbsp;<EuiIconTip type="info" content="Clears search input" {...tooltipProps} />
      </EuiTableRowCell>
      <EuiTableRowCell align="center">
        ✅&nbsp;<EuiIconTip type="info" content="Clears all selections" {...tooltipProps} />
      </EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Supports virtualization</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
    </EuiTableRow>
  </EuiTableBody>
</EuiTable>

---

### Packages Website Docs Components Layout Flex Index (`packages/website/docs/components/layout/flex/index.mdx`)

# Flex

```mdx-code-block
import { createDemo } from '@elastic/eui-docusaurus-theme/components';
import FlexPreviewWrapper from './flex_preview_wrapper';
import flexPreviewWrapperSource from '!raw-loader!./flex_preview_wrapper';
import DemoNote from './_flex_preview_note.mdx';
```

## Use cases

- [EuiFlexGroup](./group.mdx) is useful for single row layouts and for quick alignment of items.
- [EuiFlexGrid](./grid.mdx) should be used for repeated wrapping rows of same-width items.
- [EuiFlexItem](./item.mdx) should be used as a direct child of both groups or grids. It can also, depending on the layout, be omitted if its automatic flex or grow behavior is not desired.

## Shared behavior

```mdx-code-block
export const FlexDemo = createDemo({ previewWrapper: FlexPreviewWrapper, previewWrapperSource: flexPreviewWrapperSource });

<DemoNote />
```

### Nesting flex layouts

**EuiFlexGroup** and **EuiFlexGrid** can nest within themselves indefinitely. For example, here we turn off the growth on a **EuiFlexGroup**, then nest a grid inside of it.

:::warning Flex items are also a flexbox

To support nested stretching of items, **EuiFlexItem** also has `display: flex` on it. If your children are not behaving correctly, consider using one of these [flex item workarounds](./item.mdx#flex-items-are-also-flex).

:::

<FlexDemo>
  ```tsx
  import React from 'react';
  import { EuiFlexGrid, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';

  export default () => (
    <>
      <EuiFlexGroup>
        <EuiFlexItem grow={false}>
          <div>Flex Group</div>
          <EuiSpacer />
          <EuiFlexGroup>
            <EuiFlexItem>Nested Group One</EuiFlexItem>
            <EuiFlexItem>Nested Group Two</EuiFlexItem>
          </EuiFlexGroup>
        </EuiFlexItem>
        <EuiFlexItem grow={false}>
          <div>Flex Grid</div>
          <EuiSpacer />
          <EuiFlexGrid columns={3}>
            <EuiFlexItem>Nested Grid One</EuiFlexItem>
            <EuiFlexItem>Nested Grid Two</EuiFlexItem>
            <EuiFlexItem>Nested Grid Three</EuiFlexItem>
            <EuiFlexItem>Nested Grid Four</EuiFlexItem>
          </EuiFlexGrid>
        </EuiFlexItem>
      </EuiFlexGroup>
    </>
  );
  ```
</FlexDemo>

### Overriding output component type

The `component` prop can be passed to either the parent **EuiFlexGroup** or **EuiFlexGrid**, or the child **EuiFlexItem**, to change the rendered component type from the default `div`. It can be any valid React component type like a tag name string such as `div`or `span` or a React component.

This allows you to use semantic tags such as `<form>` with flex layouts, or obey rules around nesting block elements within inline elements.

<FlexDemo>
  ```tsx
  import React from 'react';
  import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';

  export default () => (
    <EuiFlexGroup component="p">
      <EuiFlexItem component="span">
        These items are nested within a paragraph tag
      </EuiFlexItem>

      <EuiFlexItem component="span">
        So they use inline span tags to avoid HTML validation issues
      </EuiFlexItem>
    </EuiFlexGroup>
  );
  ```
</FlexDemo>

---

### Packages Website Docs Components Layout Page Components Index (`packages/website/docs/components/layout/page_components/index.mdx`)

---
slug: /layout/page-components
id: layout_page_components_overview
keywords: [EuiPageBody, EuiPageSection, EuiPageSidebar, EuiPageHeader, EuiPageTitle]
---

# Page components

```mdx-code-block
import fakeSidebar from '!url-loader!./fake_sidebar.svg';
import fakeParagraph from '!url-loader!./fake_paragraph.svg';

import { PageComponentsPreviewWrapper, FixedHeightPreviewWrapper } from './_preview_wrapper';
```

import fakeSidebarSource from '!raw-loader!./fake_sidebar.svg';
import fakeParagraphSource from '!raw-loader!./fake_paragraph.svg';

Page layouts are modular and fit together in a precise manner, though certain parts can also be added or removed as needed. EUI provides both the **individual page components** and an [over-arching template](../../templates/page-template/index.mdx) for easily creating some pre-defined layouts.

## Components

:::note The following examples showcase the individual components only.

If you're looking for full page layout examples, we recommend using the [EuiPageTemplate](../../templates/page-template/index.mdx) and use this page to modify the props of each part of the template.

:::

### Page, body, and sidebar

**EuiPage** is simply a flex wrapper that will automatically `grow` to fill the height of a flex container. You can also control the flex `direction` and the maximum width using`restrictWidth` which centers the page when it reaches the provided value (or `1200px` if set to `true`).

**EuiPageSidebar** doesn't contain many configurations itself, but it does dictate how the rest of the page contents should be displayed. Typically you'll want to wrap all your page contents in **EuiPageBody** and set `panelled={true}` when you have a side bar.

<Demo scope={{ fakeParagraph, fakeSidebar }} previewPadding="none" previewWrapper={FixedHeightPreviewWrapper} extraFiles={{ 'fake_sidebar.svg': fakeSidebarSource, 'fake_paragraph.svg': fakeParagraphSource }}>

  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

### Page sections

**EuiPageSection** is a stackable component that is essentially an [EuiPanel](../../containers/panel/index.mdx) with props for quickly creating common usages. It is meant to be a direct descendent of **EuiPageBody** You'll need to set `grow={false}` to any content that you don't want to stretch within the page.

To create dividers between contents, use the `bottomBorder` prop. The `'extended'` version ensures the border touches the sides of the parent. It also supports `restrictWidth` and `alignment` to align with common usages.

<Demo scope={{ fakeParagraph }} previewPadding="none" previewWrapper={PageComponentsPreviewWrapper} extraFiles={{ 'fake_paragraph.svg': fakeParagraphSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Usage

### Page configurations

When piecing all of the different page components together, the state of your application will dictate how best to configure each component. Ideally, your main content should always live within a `'plain'` colored body or section.

When using [EuiEmptyPrompt](../../display/empty-prompt/index.mdx) to replace the main contents of your page you will want to use a panel color opposite that of the section color. For example:

```mdx-code-block
import { ConfigurationsTable } from './configurations_table';
```

<ConfigurationsTable />

### Configuration example

:::tip
Reminder: [EuiPageTemplate](../../templates/page-template/index.mdx) can handle all these configurations for you.
:::

<Demo scope={{ fakeParagraph, fakeSidebar }} previewPadding="none" previewWrapper={PageComponentsPreviewWrapper} extraFiles={{ 'fake_sidebar.svg': fakeSidebarSource, 'fake_paragraph.svg': fakeParagraphSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/page';

<PropTable definition={docgen.EuiPage} />

<PropTable definition={docgen.EuiPageBody} />

<PropTable definition={docgen.EuiPageSidebar} />

---

### Packages Website Docs Components Layout Spacer Index (`packages/website/docs/components/layout/spacer/index.mdx`)

---
keywords: [EuiSpacer]
---

# Spacer

The **EuiSpacer** component is for adding vertical space between items and should be used in place of the `<br />` tag. There are many different heights you can specify via the `size` prop which align to the EUI vertical grid sizing.

import { SpacerPreviewWrapper } from './spacer_preview_wrapper';

<Demo previewWrapper={SpacerPreviewWrapper}>
  ```tsx
  import React from 'react';
  import { EuiSpacer, EuiCode, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';

  export default () => (
    <EuiFlexGroup>
      <EuiFlexItem>
        <EuiCode>xs</EuiCode>
        <EuiSpacer size="xs" />
      </EuiFlexItem>

      <EuiFlexItem>
        <EuiCode>s</EuiCode>
        <EuiSpacer size="s" />
      </EuiFlexItem>

      <EuiFlexItem>
        <EuiCode>m (default)</EuiCode>
        <EuiSpacer />
      </EuiFlexItem>

      <EuiFlexItem>
        <EuiCode>l</EuiCode>
        <EuiSpacer size="l" />
      </EuiFlexItem>

      <EuiFlexItem>
        <EuiCode>xl</EuiCode>
        <EuiSpacer size="xl" />
      </EuiFlexItem>

      <EuiFlexItem>
        <EuiCode>xxl</EuiCode>
        <EuiSpacer size="xxl" />
      </EuiFlexItem>
    </EuiFlexGroup>
  );
  ```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/spacer';

<PropTable definition={docgen.EuiSpacer} />

---

### Packages Website Docs Components Navigation Pagination Index (`packages/website/docs/components/navigation/pagination/index.mdx`)

---
keywords: [EuiPagination]
---

# Pagination

Some EUI components have pagination built-in, like [EuiBasicTable](../../tables/basic.mdx), but for custom built paginated interfaces you can use **EuiPagination** manually.

## Component

**EuiPagination** accepts a total `pageCount` and only shows up to 5 consecutive pages, with shortcuts to the first and/or last page. It also requires the parent component to maintain the current `activePage` and handle the `onPageClick`.

:::accessibility Accessibility recommendation
Provide a descriptive `aria-label` for each pagination set.
:::

```tsx interactive
import React, { useState } from 'react';
import { EuiPagination } from '@elastic/eui';

export default function () {
  const [activePage, setActivePage] = useState(0);
  const PAGE_COUNT = 22;

  return (
    <EuiPagination
      aria-label="Many pages example"
      pageCount={PAGE_COUNT}
      activePage={activePage}
      onPageClick={(activePage) => setActivePage(activePage)}
    />
  );
}
```

## Usage

### Few pages

The UI simplifies when we have fewer than the maximum number of visible pages.

```tsx interactive
import React, { useState } from 'react';
import { EuiPagination } from '@elastic/eui';

export default function () {
  const [activePage, setActivePage] = useState(0);
  const PAGE_COUNT = 4;

  return (
    <EuiPagination
      aria-label="Few pages example"
      pageCount={PAGE_COUNT}
      activePage={activePage}
      onPageClick={(activePage) => setActivePage(activePage)}
    />
  );
}
```

### Centered pagination

You can use [EuiFlexGroup](../../layout/flex/group.mdx) to center the pagination in a layout.

```tsx interactive
import React, { useState } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiPagination } from '@elastic/eui';

export default function () {
  const [activePage, setActivePage] = useState(0);
  const PAGE_COUNT = 15;

  return (
    <EuiFlexGroup justifyContent="spaceAround">
      <EuiFlexItem grow={false}>
        <EuiPagination
          aria-label="Centered pagination example"
          pageCount={PAGE_COUNT}
          activePage={activePage}
          onPageClick={(activePage) => setActivePage(activePage)}
        />
      </EuiFlexItem>
    </EuiFlexGroup>
  );
}
```

### Compressed and responsive

Use the `compressed` prop to minimize the horizontal footprint. This will replace the numbered buttons with static numbers and rely on the first, last, next and previous icon buttons to navigate.

This is also the same display that will occur when `responsive` is **not** `false`. You can adjust the responsiveness by supplying an array of [named breakpoints](../../../getting-started/theming/tokens/breakpoints/index.mdx) to `responsive`. The default is `['xs', 's']`.

```tsx interactive
import React, { useState } from 'react';
import { EuiPagination } from '@elastic/eui';

export default function () {
  const [activePage, setActivePage] = useState(0);
  const PAGE_COUNT = 24;

  return (
    <EuiPagination
      aria-label="Compressed example"
      pageCount={PAGE_COUNT}
      activePage={activePage}
      onPageClick={(activePage) => setActivePage(activePage)}
      compressed
    />
  );
}
```

### Indeterminate page count

If the total number of pages cannot be accurately determined, you can pass `0` as the `pageCount`. This will remove the button numbers and rely solely on the arrow icon buttons for navigation. Without a total page count, the last page button will pass back `-1` for the `activePage`.

```tsx interactive
import React, { useState } from 'react';
import { EuiPagination } from '@elastic/eui';

export default function () {
  const [activePage, setActivePage] = useState(0);

  return (
    <EuiPagination
      aria-label="Indeterminate example"
      pageCount={0}
      activePage={activePage}
      onPageClick={(activePage) => setActivePage(activePage)}
    />
  );
}
```

### Table pagination

You can use **EuiTablePagination** to create a combination "Rows per page" and pagination set, commonly used with [tables](../../tables/basic.mdx#pagination). If you pass `0` in as one of the `itemsPerPageOptions`, it will create a "Show all" option and hide the pagination.

```tsx interactive
import React, { useState } from 'react';
import { EuiTablePagination } from '@elastic/eui';

export default () => {
  const totalEntries = 1250;
  const [activePage, setActivePage] = useState(0);
  const [rowSize, setRowSize] = useState(50);
  const [pageCount, setPageCount] = useState(Math.ceil(totalEntries / 50));

  const goToPage = (pageNumber: number) => setActivePage(pageNumber);
  const changeItemsPerPage = (pageSize: number) => {
    setPageCount(Math.ceil(totalEntries / pageSize));
    setRowSize(pageSize);
    setActivePage(0);
  };

  return (
    <EuiTablePagination
      aria-label="Table pagination example"
      pageCount={pageCount}
      activePage={activePage}
      onChangePage={goToPage}
      itemsPerPage={rowSize}
      onChangeItemsPerPage={changeItemsPerPage}
      itemsPerPageOptions={[10, 20, 0]}
    />
  );
};
```

### Custom pagination

Or you can use [EuiFlexGroup](../../layout/flex/group.mdx) and [EuiContextMenu](../context-menu.mdx#with-single-panel) to set up your own custom pagination layout.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Guidelines

import Guidelines from './_guidelines.mdx';

<Guidelines />

## Props

import paginationDocgen from '@elastic/eui-docgen/dist/components/pagination';
import tableDocgen from '@elastic/eui-docgen/dist/components/table';

<PropTable definition={paginationDocgen.EuiPagination} />
<PropTable definition={paginationDocgen.EuiPaginationButton} />
<PropTable definition={tableDocgen.EuiTablePagination} />

---

### Packages Website Docs Components Navigation Steps Index (`packages/website/docs/components/navigation/steps/index.mdx`)

---
keywords: [EuiSteps, EuiStepsHorizontal]
---

# Steps

**EuiSteps** presents procedural content in a numbered outline format. It is best used when presenting instructional content that must be conducted in a particular order. It requires a `title` and `children` to be present and will automatically increment the step number based on the initial `firstStepNumber`.

## Component

### Default

```tsx interactive
import React from 'react';
import { EuiCode, EuiSpacer, EuiSteps, EuiText } from '@elastic/eui';

const firstSetOfSteps = [
  {
    title: 'Step 1',
    children: (
      <EuiText>
        <p>Do this first</p>
      </EuiText>
    ),
  },
  {
    title: 'Step 2',
    children: (
      <EuiText>
        <p>Then this</p>
      </EuiText>
    ),
  },
];

const nextSetOfSteps = [
  {
    title: 'Good step',
    children: (
      <EuiText>
        <p>Do this first</p>
      </EuiText>
    ),
  },
  {
    title: 'Better step',
    children: (
      <EuiText>
        <p>Then this</p>
      </EuiText>
    ),
  },
];

export default () => (
  <>
    <EuiSteps steps={firstSetOfSteps} />

    <EuiSpacer size="m" />
    <EuiText>
      <p>
        Set <EuiCode>firstStepNumber</EuiCode> to continue step numbering after
        any type of break in the content
      </p>
    </EuiText>
    <EuiSpacer size="m" />

    <EuiSteps
      firstStepNumber={firstSetOfSteps.length + 1}
      steps={nextSetOfSteps}
    />
  </>
);
```

### Horizontal Steps

import HorizontalSteps from './_horizontal_steps.mdx';

<HorizontalSteps />

## Usage

### Complex steps

If you need to call out a set of substeps that are not lines of code, most likely a `<ol/>`, wrap the block in a `<EuiSubSteps/>`.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Heading elements

To aid with accessibility and hierarchical headings, you can and should pass in a heading element to use for each step title. The example below shows that the logical heading element should be an `h2`and therefore adds `headingElement="h2"` to the EuiSteps component.

The style of the title will **not** be affected.

```tsx interactive
import React from 'react';
import { EuiSteps, EuiTitle, EuiSpacer } from '@elastic/eui';

const steps = [
  {
    title: 'Inspect me',
    children: (
      <EuiTitle size="xs">
        <h3>Did you notice the step title is inside a Heading 2 element?</h3>
      </EuiTitle>
    ),
  },
];

export default () => (
  <>
    <EuiTitle size="l">
      <h1>Heading 1</h1>
    </EuiTitle>

    <EuiSpacer size="xl" />

    <EuiSteps steps={steps} headingElement="h2" />
  </>
);
```

### Conveying status

Steps can optionally include `status` prop that will alter the look of the number prefix. The options are `incomplete`, `complete`, `warning`, `danger`, `disabled` and `loading`. This is used mostly as a final step when you need to make some sort of final check.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Custom title sizes

You can set a different title size using `titleSize`. If `titleSize` is set in both **EuiSteps** and **EuiStep**, the latter value will override the former. Additionally, the title size `xs` will automatically generate smaller steps circles.

The title size `xxs` affects only the size of the accompanying **unnumbered** step indicator, but not the title itself.

```tsx interactive
import React, { useState } from 'react';
import {
  EuiButtonGroup,
  EuiCode,
  EuiSpacer,
  EuiSteps,
  EuiTitle,
  EuiStepInterface,
} from '@elastic/eui';

const firstSetOfSteps: EuiStepInterface[] = [
  {
    title: 'Step 1',
    children: (
      <p>
        Both step title and circle indicators will adjust in size based on the{' '}
        <EuiCode>titleSize</EuiCode> prop
      </p>
    ),
  },
  {
    title: 'Step 2',
    children: (
      <p>
        Both step title and circle indicators will adjust in size based on the{' '}
        <EuiCode>titleSize</EuiCode> prop
      </p>
    ),
  },
];

const sizeButtons = [
  {
    id: 'xxs',
    label: 'XXSmall',
  },
  {
    id: 'xs',
    label: 'XSmall',
  },
  {
    id: 's',
    label: 'Small',
  },
  {
    id: 'm',
    label: 'Medium',
  },
];

type StepSizes = NonNullable<EuiStepInterface['titleSize']>;

export default () => {
  const [titleSize, setTitleSize] = useState<StepSizes>('m');

  const sizeOnChange = (optionId: StepSizes) => {
    setTitleSize(optionId);
  };

  return (
    <>
      <EuiTitle size="xxs">
        <h3>Step Size</h3>
      </EuiTitle>
      <EuiSpacer size="s" />
      <EuiButtonGroup
        legend="Horizontal step size toggle"
        options={sizeButtons}
        idSelected={titleSize}
        onChange={(id) => sizeOnChange(id as StepSizes)}
      />
      <EuiSpacer size="m" />
      <EuiSteps titleSize={titleSize} steps={firstSetOfSteps} />
    </>
  );
};
```

## Props

import docgen from '@elastic/eui-docgen/dist/components/steps';

<PropTable definition={docgen.EuiSteps} />

<PropTable definition={docgen.EuiStep} />

<PropTable definition={docgen.EuiStepNumber} />

<PropTable definition={docgen.EuiSubSteps} />

<PropTable definition={docgen.EuiStepsHorizontal} />

<PropTable definition={docgen.EuiStepHorizontal} />

---

### Packages Website Docs Components Templates Page Template Index (`packages/website/docs/components/templates/page-template/index.mdx`)

---
keywords: [EuiPageTemplate]
---

# Page template

**EuiPageTemplate** is a namespaced component for creating the different types of page layout patterns described in these docs. It is somewhat opinionated, but still has the ability to customize most of the inner components directly on their instance.

## Simple page with header and sections

All templates should start with a wrapping `EuiPageTemplate` to control some shared settings like `paddingSize`, `bottomBorder`, `restrictWidth`, and `panelled`. Then each direct child will be evaluated for if it is one of the other namespaced components. If so, it will place it in the appropriate spot and apply the appropriate props based on the full configuration of child elements. These namespaced components include:

- **EuiPageTemplate.Sidebar** extends [EuiPageSidebar](#providing-a-sidebar)
- **EuiPageTemplate.Header** extends [EuiPageHeader](../../layout/page-header.mdx)
- **EuiPageTemplate.Section** extends [EuiPageSection](../../layout/page_components/index.mdx#page-sections)
- **EuiPageTemplate.BottomBar** extends [EuiBottomBar](../../containers/bottom-bar.mdx)
- **EuiPageTemplate.EmptyPrompt** extends [EuiEmptyPrompt](../../display/empty-prompt/index.mdx)

With the exception of `.Sidebar` and `.BottomBar`, the stacking order of the page contents is determined by the order they are passed in. You can also override the outer props by simply applying them directly to the child element.

:::tip
If you have a fixed position [headers](../../layout/header.mdx#fixed-header), the template will automatically account for the padding `offset` based on the total number of page headers. If you do not want the template to calculate this, you can pass `0` in as the manual `offset`.
:::

```mdx-code-block
import contentSvg from '!url-loader!./content_paragraph.svg';
import sideNavSvg from '!url-loader!./content_side_nav.svg';
import centerSvg from '!url-loader!./content_center.svg';

import contentSvgSource from '!raw-loader!./content_paragraph.svg';
import sideNavSvgSource from '!raw-loader!./content_side_nav.svg';
import centerSvgSource from '!raw-loader!./content_center.svg';
```

<Demo scope={{ contentSvg }} extraFiles={{ 'content_paragraph.svg': contentSvgSource }}>
  ```tsx
  import React from 'react';
  import {
    EuiText,
    EuiButton,
    EuiImage,
    EuiPageTemplate,
    EuiPageTemplateProps,
  } from '@elastic/eui';

  import contentSvg from './content_paragraph.svg';

  const panelled: EuiPageTemplateProps['panelled'] = undefined;
  const restrictWidth: EuiPageTemplateProps['restrictWidth'] = false;
  const bottomBorder: EuiPageTemplateProps['bottomBorder'] = "extended";

  export default () => {
    return (
      <EuiPageTemplate
        panelled={panelled}
        restrictWidth={restrictWidth}
        bottomBorder={bottomBorder}
        offset={0}
        grow={false}
      >
        <EuiPageTemplate.Section grow={false} color="subdued" bottomBorder={bottomBorder}>
          <EuiText textAlign="center">
            <strong>
              Stack EuiPageTemplate sections and headers to create your custom content order.
            </strong>
          </EuiText>
        </EuiPageTemplate.Section>
        <EuiPageTemplate.Header
          iconType="logoElastic"
          pageTitle="Page title"
          rightSideItems={[<EuiButton>Right side item</EuiButton>]}
          description="Header description."
          tabs={[{ label: "Tab 1", isSelected: true }, { label: "Tab 2" }]}
        />
        <EuiPageTemplate.Section>
          <EuiImage size={"fullWidth"} alt="Fake paragraph" url={contentSvg} />
        </EuiPageTemplate.Section>
      </EuiPageTemplate>
    );
  };
  ```
</Demo>

## Providing a sidebar

If your application requires the use of side navigation or other sidebar content, you can pass and **EuiPageTemplate.Sidebar** component containing your sidebar content. The template will automatically adjust the layout when this content is provided.

This component will set its content to stick to the top of the browser window and scroll independently of the rest of the layout. If you have any fixed [**EuiHeaders**](../../layout/page-header.mdx), these will be accounted for as well. You can turn this behavior off with `sticky={false}`.

Typically when a sidebar is included and `restrictedWidth` is defined, we recommend keeping the `borderBottom={true}` though you can also expand particular sections with `borderBottom="extended"`.

:::warning Sidebars must be direct children declared in the same component.
In order for the template configurations to properly account for the existence of a sidebar, it needs to clone the element which can only be performed on direct children.
:::

<Demo
  scope={{ contentSvg, sideNavSvg }}
  extraFiles={{
    'content_paragraph.svg': contentSvgSource,
    'content_side_nav.svg': sideNavSvgSource
  }}
>
```tsx
import React from 'react';
import {
  EuiText,
  EuiButton,
  EuiImage,
  EuiPageTemplate,
  EuiPageTemplateProps,
} from '@elastic/eui';

import contentSvg from './content_paragraph.svg';
import sideNavSvg from './content_side_nav.svg';

const panelled: EuiPageTemplateProps['panelled'] = true;
const restrictWidth: EuiPageTemplateProps['restrictWidth'] = false;
const bottomBorder: EuiPageTemplateProps['bottomBorder'] = true;

export default () => {
  return (
    <EuiPageTemplate
      panelled={panelled}
      restrictWidth={restrictWidth}
      bottomBorder={bottomBorder}
      offset={0}
      grow={false}
    >
      <EuiPageTemplate.Sidebar>
        <EuiImage size={'fullWidth'} alt="Fake navigation" url={sideNavSvg} />
      </EuiPageTemplate.Sidebar>
      <EuiPageTemplate.Header
        iconType="logoElastic"
        pageTitle="Page title"
        rightSideItems={[<EuiButton>Right side item</EuiButton>]}
      />
      <EuiPageTemplate.Section
        grow={false}
        bottomBorder={bottomBorder}
      >
        <EuiText textAlign="center">
          <strong>
            Stack EuiPageTemplate sections and headers to create your custom
            content order.
          </strong>
        </EuiText>
      </EuiPageTemplate.Section>
      <EuiPageTemplate.Section>
        <EuiImage size={'fullWidth'} alt="Fake paragraph" url={contentSvg} />
      </EuiPageTemplate.Section>
    </EuiPageTemplate>
  );
};
````

</Demo>

## Showing a bottom bar

Adding an [**EuiBottomBar**](../../containers/bottom-bar.mdx) can be tricky to use and account for any sidebars. **EuiPageTemplate** handles this nicely by supplying a **EuiPageTemplate.BottomBar** component for passing the contents of your bottom bar that extends **EuiBottomBar**.

It uses the `sticky` position so that it sticks to the bottom of and remains within the bounds of page body. This way it will never overlap the sidebar, no matter the screen size. It also means not needing to accommodate for the height of the bar in the body element.

It will also keep its content constrained to the `restrictedWidth` value so the contents are always horizontally aligned.

:::warning
For proper alignment in case of short content, at least one **EuiPageTemplate.Section** must have `grow={true}`.
:::

<Demo
  scope={{ contentSvg, sideNavSvg }}
  extraFiles={{
    'content_paragraph.svg': contentSvgSource,
    'content_side_nav.svg': sideNavSvgSource
  }}
>
  ```
/* Detailed source-code truncated for AI context efficiency. */
````
</Demo>

## Empty pages or content

When the content is in an empty/pre-setup state, we recommend then using an [**EuiEmptyPrompt**](../../display/empty-prompt/index.mdx) to direct users on next steps. Using **EuiPageTemplate.EmptyPrompt** will automatically center the prompt vertically and horizontally.

The prompt's panel color depends on the other configurations but can be manually passed in via the `color` prop.

<Demo
  scope={{ centerSvg, sideNavSvg }}
  extraFiles={{
    'content_center.svg': centerSvgSource,
    'content_side_nav.svg': sideNavSvgSource
  }}
>
```tsx
import React from 'react';
import {
  EuiText,
  EuiButton,
  EuiImage,
  EuiPageTemplate,
  EuiPageTemplateProps,
} from '@elastic/eui';

import centerSvg from './content_center.svg';
import sideNavSvg from './content_side_nav.svg';

const panelled: EuiPageTemplateProps['panelled'] = true;
const restrictWidth: EuiPageTemplateProps['restrictWidth'] = false;
const bottomBorder: EuiPageTemplateProps['bottomBorder'] = true;

export default () => {
  return (
    <EuiPageTemplate
      panelled={panelled}
      restrictWidth={restrictWidth}
      bottomBorder={bottomBorder}
      offset={0}
      grow={false}
    >
      <EuiPageTemplate.Sidebar>
        <EuiImage size={'fullWidth'} alt="Fake navigation" url={sideNavSvg} />
      </EuiPageTemplate.Sidebar>
      <EuiPageTemplate.Header
        iconType="logoElastic"
        pageTitle="Page title"
        rightSideItems={[<EuiButton>Right side item</EuiButton>]}
      />
      <EuiPageTemplate.EmptyPrompt
        title={<span>No spice</span>}
        footer={<EuiButton>Footer action</EuiButton>}
      >
        <EuiImage size={'fullWidth'} alt="Fake paragraph" url={centerSvg} />
      </EuiPageTemplate.EmptyPrompt>
    </EuiPageTemplate>
  );
};
````

</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/page_template';

<PropTable definition={docgen.EuiPageTemplate} />

---

### Packages Website Docs Components Templates Sitewide Search Index (`packages/website/docs/components/templates/sitewide-search/index.mdx`)

---
keywords: [EuiSelectableTemplateSitewide]
---

# Sitewide search

**EuiSelectableTemplateSitewide** is an opinionated wrapper around [EuiSelectable](../../forms/selection/selectable.mdx) to provide a reusable template across the Elastic products that will share the same global search capabilities. It creates the search input that triggers a popover containing the list of options.

## Basic setup

### Search input

The search ability of [EuiSelectable](../../forms/selection/selectable.mdx) is still hooked up to the options provided. It will highlight the portion of the label that matches the search string.

:::note

The demo showcases the possibility to allow a keyboard shortcut (command + K) to trigger the search input focus, but the template does not come with this ability.

:::

### Popover

The popover itself allows you to display a `popoverTitle` node, `popoverFooter` node, or pass any of the `popoverProps` to the [EuiPopover](../../containers/popover.mdx) component.

### Selection

The options themselves are simply rendered as list items with no interactive behavior like buttons or links. You must handle the interaction when the component passes back the altered array of options with the selected option having `checked: 'on'`.

### Popover toggle and responsiveness

The default display is to render the search input inline which triggers a popover with the results. Or you can decide to trigger the whole selectable component from a single button. By passing your own button to `popoverButton`, the component will use this to trigger the popover, putting the search inside.

This is a great way to handle reducing the size of the component for smaller screens. The component offers a helper prop called `popoverButtonBreakpoints` which will only render the `popoverButton` if the window size matches named breakpoint(s).

```
/* Detailed source-code truncated for AI context efficiency. */
```

### ColorModes

**EuiSelectableTemplateSitewide** by default has the `colorMode` of the nearest **EuiThemeProvider** applied.
If you want to override the this manually, you can pass a `colorModes` prop to the component. This allows you 
to apply different color modes to the search and popover components.

import { Example } from '@site/src/components';

<Example.Snippet>
  ```tsx
  <EuiSelectableTemplateSitewide colorModes={{ search: 'default', popover: 'inverse' }} />
  ```
</Example.Snippet>

```tsx interactive
import React from 'react';
import { EuiSelectableTemplateSitewide } from '@elastic/eui';

export default () => {
  return (
    <EuiSelectableTemplateSitewide
      options={[
        {
          label: 'Welcome dashboards',
          meta: [
            {
              text: 'Dashboard',
              type: 'application',
              highlightSearchString: true,
            },
          ],
          url: 'welcome-dashboards',
        },
      ]}
      colorModes={{ search: 'default', popover: 'inverse' }}
    />
  );
};
```


## Options

The `options` are the most opinionated portion of the template. Their display is determined by the props passed in and extends the normal `EuiSelectable.option` type. All parts are optional with the exception of the label (A).

import { SitewideOption } from './sitewide_option';

<SitewideOption />

<br />
<details>
  <summary>
    Code snippet
  </summary>

  ```tsx
  const options: EuiSelectableTemplateSitewideOption[] = [
    {
      label: 'Label',
      icon: {
        type: 'logoKibana'
      }
      avatar: {
        name: 'Default',
      },
      meta: [
        {
          text: 'Meta',
          type: 'application',
        },
        {
          text: 'Deployment',
          type: 'deployment',
        },
        {
          text: 'Default display',
        },
      ],
    },
  ]
  ```
</details>

- `label` (required): The name of the item itself. By default, the search box will only use this to match the search term against, but you can supply a separate `searchableLabel` that combines the label and meta data to search on.
- `icon`: Only display the solution or application's logo when the option links to the application itself (Dashboard app) and not lower-level items such as individual dashboards. Size and color are predetermined but can be overridden.
- `avatar`: Represents the Kibana Space that the item is located in, **if** multiple spaces are present. Type and size are predetermined but can be overridden.
- `meta`: This bottom line should only contain items if the option is a lower-level item (individual dashboard). The display of which defaults to simple text, but if you pass one of the predetermined `types`, they will be styled according to the design pattern.

:::note
The demo shows how you can temporarily replace the icon for a subset of options to display a short list of recently viewed options.
:::

## Props

import docgen from '@elastic/eui-docgen/dist/components/selectable';

<PropTable definition={docgen.EuiSelectableTemplateSitewide} />

---

### Packages Eui Src Components Date Picker React Datepicker Docs Index (`packages/eui/src/components/date_picker/react-datepicker/docs/index.md`)

# `index` (component)

| name                         | type                           | default value      | description |
| ---------------------------- | ------------------------------ | ------------------ | ----------- |
| `adjustDateOnChange`         | `bool`                         |                    |             |
| `allowSameDay`               | `bool`                         | `false`            |             |
| `autoComplete`               | `string`                       |                    |             |
| `autoFocus`                  | `bool`                         |                    |             |
| `calendarClassName`          | `string`                       |                    |             |
| `calendarContainer`          | `func`                         |                    |             |
| `children`                   | `node`                         |                    |             |
| `className`                  | `string`                       |                    |             |
| `clearButtonTitle`           | `string`                       |                    |             |
| `customInput`                | `element`                      |                    |             |
| `customInputRef`             | `string`                       |                    |             |
| `dateFormat`                 | `union(string\|array)`         | `"L"`              |             |
| `dateFormatCalendar`         | `string`                       | `"MMMM YYYY"`      |             |
| `dayClassName`               | `func`                         |                    |             |
| `disabled`                   | `bool`                         | `false`            |             |
| `disabledKeyboardNavigation` | `bool`                         | `false`            |             |
| `dropdownMode`               | `enum("scroll"\|"select")`     | `"scroll"`         |             |
| `endDate`                    | `object`                       |                    |             |
| `excludeDates`               | `array`                        |                    |             |
| `excludeTimes`               | `array`                        |                    |             |
| `filterDate`                 | `func`                         |                    |             |
| `fixedHeight`                | `bool`                         |                    |             |
| `forceShowMonthNavigation`   | `bool`                         |                    |             |
| `formatWeekDay`              | `func`                         |                    |             |
| `formatWeekNumber`           | `func`                         |                    |             |
| `highlightDates`             | `array`                        |                    |             |
| `id`                         | `string`                       |                    |             |
| `includeDates`               | `array`                        |                    |             |
| `includeTimes`               | `array`                        |                    |             |
| `injectTimes`                | `array`                        |                    |             |
| `inline`                     | `bool`                         |                    |             |
| `isClearable`                | `bool`                         |                    |             |
| `locale`                     | `string`                       |                    |             |
| `maxDate`                    | `object`                       |                    |             |
| `maxTime`                    | `object`                       |                    |             |
| `minDate`                    | `object`                       |                    |             |
| `minTime`                    | `object`                       |                    |             |
| `monthsShown`                | `number`                       | `1`                |             |
| `name`                       | `string`                       |                    |             |
| `nextMonthButtonLabel`       | `string`                       | `"Next month"`     |             |
| `onBlur`                     | `func`                         | `function() {}`    |             |
| `onChange`                   | `func`                         | `function() {}`    |             |
| `onChangeRaw`                | `func`                         |                    |             |
| `onClickOutside`             | `func`                         | `function() {}`    |             |
| `onFocus`                    | `func`                         | `function() {}`    |             |
| `onInputClick`               | `func`                         | `function() {}`    |             |
| `onInputError`               | `func`                         | `function() {}`    |             |
| `onKeyDown`                  | `func`                         | `function() {}`    |             |
| `onMonthChange`              | `func`                         | `function() {}`    |             |
| `onSelect`                   | `func`                         | `function() {}`    |             |
| `onWeekSelect`               | `func`                         |                    |             |
| `onYearChange`               | `func`                         | `function() {}`    |             |
| `open`                       | `bool`                         |                    |             |
| `openToDate`                 | `object`                       |                    |             |
| `peekNextMonth`              | `bool`                         |                    |             |
| `placeholderText`            | `string`                       |                    |             |
| `popperClassName`            | `string`                       |                    |             |
| `popperContainer`            | `func`                         |                    |             |
| `popperModifiers`            | `object`                       |                    |             |
| `popperPlacement`            | `enumpopperPlacementPositions` |                    |             |
| `popperProps`                | `object`                       |                    |             |
| `preventOpenOnFocus`         | `bool`                         | `false`            |             |
| `previousMonthButtonLabel`   | `string`                       | `"Previous Month"` |             |
| `readOnly`                   | `bool`                         | `false`            |             |
| `renderCustomHeader`         | `func`                         |                    |             |
| `renderDayContents`          | `func`                         | `function(date) {  |

return date;
}`|| |`required`|`bool`||| |`scrollableMonthYearDropdown`|`bool`||| |`scrollableYearDropdown`|`bool`||| |`selected`|`object`||| |`selectsEnd`|`bool`||| |`selectsStart`|`bool`||| |`shouldCloseOnSelect`|`bool`|`true`|| |`showDisabledMonthNavigation`|`bool`||| |`showMonthDropdown`|`bool`||| |`showMonthYearDropdown`|`bool`||| |`showTimeSelect`|`bool`|`false`|| |`showTimeSelectOnly`|`bool`||| |`showWeekNumbers`|`bool`||| |`showYearDropdown`|`bool`||| |`startDate`|`object`||| |`startOpen`|`bool`||| |`tabIndex`|`number`||| |`timeCaption`|`string`|`"Time"`|| |`timeFormat`|`string`||| |`timeIntervals`|`number`|`30`|| |`title`|`string`||| |`todayButton`|`node`||| |`useShortMonthInDropdown`|`bool`||| |`useWeekdaysShort`|`bool`||| |`utcOffset`|`union(number\|string)`||| |`value`|`string`||| |`weekLabel`|`string`||| |`withPortal`|`bool`|`false`|| |`yearDropdownItemNumber`|`number`|||

---

### Packages Website Docs Components Data Grid Advanced Custom Body Rendering Index (`packages/website/docs/components/data-grid/advanced/custom-body-rendering/index.mdx`)

---
sidebar_position: 2
---

# Custom body rendering

For **extremely** advanced use cases, the `renderCustomGridBody` prop may be used to take complete control over rendering the grid body. This may be useful for scenarios where the default [virtualized](../../container-constraints.mdx#virtualization) rendering is not desired, or where custom row layouts (e.g., the conditional row details cell below) are required.

:::warning
This prop is meant to be an **escape hatch**, and should only be used if you know exactly what you are doing. Once a custom renderer is used, you are in charge of ensuring the grid has all the correct semantic and aria labels required by the <a href="https://www.w3.org/WAI/ARIA/apg/patterns/grid" target="_blank" rel="noopenner noreferrer">data grid spec</a>, and that keyboard focus and navigation still work in an accessible manner.
:::

import Demo from './demo';

<Demo />

## Props

import docgen from '@elastic/eui-docgen/dist/components/datagrid/data_grid_types.docgen.json';

<PropTable definition={docgen.EuiDataGridCustomBodyProps} />

---

### Packages Website Docs Getting Started Theming Tokens Borders Index (`packages/website/docs/getting-started/theming/tokens/borders/index.mdx`)

---
sidebar_position: 1
---

# Borders

```mdx-code-block
import { Example } from '@site/src/components';
```

The border tokens contain both individual border property values and full shorthand border properties.

## Types

```mdx-code-block
import { BorderPreview } from './border_preview';
import { BordersTable } from './borders_table';
```

<Example>
  <Example.Description>
    ### `euiTheme.border[type]` <Badge color="hollow">token</Badge>

    These common border types string together the base properties of color, width and style to form common full `border` properties.
  </Example.Description>
  <Example.Preview>
    <BorderPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      border: ${euiTheme.border.thin};
    `
    ```
  </Example.Snippet>
</Example>

<BordersTable />


## Color

EUI has one main base color it uses for almost all borders (or calculated borders).

Only form specific borders use the `euiTheme.colors.borderBasePlain` color token instead.

```mdx-code-block
import { ColorPreview } from './color_preview';
```

<Example>
  <Example.Description>
    ### `euiTheme.border.color` <Badge color="hollow">token</Badge>

    You can apply this color directly to any `border-color` property.
    - Default is `colors.lightShade`
    - In high contrast mode, this value becomes `colors.fullShade` and cannot be overridden.

  </Example.Description>
  <Example.Preview>
    <ColorPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      border-color: ${euiTheme.border.color};
    `
    ```
  </Example.Snippet>
</Example>

## Width

```mdx-code-block
import { BorderWidthPreview } from './border_width';
import { BorderWidthsTable } from './border_widths_table';
```

<Example>
  <Example.Description>
    ### `euiTheme.border.width[size]` token

    These basic properties make up the border thickness which can be used individually or in conjunction with`border.color`.
  </Example.Description>
  <Example.Preview>
    <BorderWidthPreview />
  </Example.Preview>
  <Example.Snippet>
    ```
    css`
      border: ${euiTheme.border.width.thick} dashed ${euiTheme.border.color};
    `
    ```
  </Example.Snippet>
</Example>

<BorderWidthsTable />

## Radius

```mdx-code-block
import { BorderRadiusPreview } from './border_radius_preview';
import { BorderRadiiTable } from './border_radii_table';
```

<Example>
  <Example.Description>
    ### `euiTheme.border.radius[size]` <Badge color="hollow">token</Badge>

    These basic properties make up the corner radii which can be used individually.
  </Example.Description>
  <Example.Preview>
    <BorderRadiusPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      border-radius: ${euiTheme.border.radius.medium};
    `
    ```
  </Example.Snippet>
</Example>

<BorderRadiiTable />

:::info Prefer semantic radius tokens

Use the semantic tokens `border.radius.inline` (4px), `control` (8px), `panel` (12px), and `frame` (16px). Legacy `small` / `medium` still resolve to 4px until migrated.

:::

---

### Packages Website Docs Getting Started Theming Tokens Breakpoints Index (`packages/website/docs/getting-started/theming/tokens/breakpoints/index.mdx`)

---
sidebar_position: 2
---

# Breakpoints

```mdx-code-block
import {
  EuiIcon,
  EuiText,
  EuiThemeProvider,
  useCurrentEuiBreakpoint,
  useEuiBreakpoint,
  useEuiTheme,
  useIsWithinBreakpoints,
  useIsWithinMaxBreakpoint,
  useIsWithinMinBreakpoint,
} from '@elastic/eui';

import { Example, ExampleDescription } from '@site/src/components';

import { UseEuiBreakpointPreview } from './use_eui_breakpoint_preview';
import { UseEuiMinMaxMaxBreakpointPreview } from './use_eui_min_max_breakpoint_preview';
import { BreakpointsTable } from './breakpoints_table.tsx';
import { CurrentCustomBreakpointPreview } from './current_custom_breakpoint_preview';
```

For most of your usages we recommend using the [responsive utilities](../../utilities/breakpoints.mdx) **instead** of consuming the theme values directly.

## Default values

If you want to align your custom responsive styles with EUI's breakpoints, or when using components that accept our named breakpoints, you'll want to utilize the following default values and provided hooks.

<Example>
  <Example.Description>
    ### `useCurrentEuiBreakpoint()` <Badge color="hollow">hook</Badge>

    This hook returns the named breakpoint size of the current browser window width, responsively updating whenever the window is resized.

    The hook automatically inherits breakpoint sizes from the current EUI theme and any theme overrides.
  </Example.Description>
  <Example.Preview>
    Current breakpoint: <strong>{useCurrentEuiBreakpoint()}</strong>
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    const currentBreakpoint = useCurrentEuiBreakpoint()
    ```
  </Example.Snippet>
</Example>

<Example>
  <Example.Description>
    ### `useIsWithinBreakpoints(sizes[], isResponsive?)` <Badge color="hollow">hook</Badge>

    This hook returns true or false if the current browser window width is within the passed breakpoint `sizes`. The `isResponsive` parameter allows it to easily be turned on/off from within your component.

    You can also use `useIsWithinMaxBreakpoint(size)` and `useIsWithinMinBreakpoint(size)`. The min/max hooks return true or false if the current browser window width is above or below the passed breakpoint `size` respectively.

    These hooks automatically inherits breakpoint sizes from the current EUI theme and any theme overrides.
  </Example.Description>
  <Example.Preview>
    Targeting large devices only: {useIsWithinBreakpoints(['l', 'xl']) ? <EuiIcon type="checkCircleFill" color="success" /> : <EuiIcon type="cross" color="danger" />}

    Targeting medium devices and below: {useIsWithinMaxBreakpoint('m') ? <EuiIcon type="checkCircleFill" color="success" /> : <EuiIcon type="cross" color="danger" />}

    Targeting small devices and above: {useIsWithinMinBreakpoint('s') ? <EuiIcon type="checkCircleFill" color="success" /> : <EuiIcon type="cross" color="danger" />}
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    useIsWithinBreakpoints(['l', 'xl'])
    useIsWithinMaxBreakpoint('m')
    useIsWithinMinBreakpoint('s')
    ```
  </Example.Snippet>
</Example>

<Example>
  <Example.Description>
    ### `useEuiBreakpoint(sizes[])` <Badge color="hollow">hook</Badge>

    Given an array of screen sizes, this hook generates a CSS media query string based on the minimum and maximum screen sizes provided.
  </Example.Description>
  <Example.Preview>
    <UseEuiBreakpointPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    ${useEuiBreakpoint(['s', 'l'])} {
      font-weight: bold;
    }
    ${useEuiBreakpoint(['xs', 's'])} {
      color: red;
    }
    ${useEuiBreakpoint(['m'])} {
      color: yellow;
    }
    ${useEuiBreakpoint(['l', 'xl'])} {
      color: green;
    }
    ```
  </Example.Snippet>
</Example>

<Example>
  <Example.Description>
    ### `useEuiMaxBreakpoint(size)` and `useEuiMinBreakpoint(size)` <Badge color="hollow">hook</Badge>

    Given a single breakpoint key, these hooks generate a min or max CSS media query string based on the single breakpoint dimension returned.
  </Example.Description>
  <Example.Preview>
    <UseEuiMinMaxMaxBreakpointPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      ${useEuiMaxBreakpoint('m')} {
        color: red;
      }
      ${useEuiMinBreakpoint('m')} {
        color: green;
      }
    `
    ```
  </Example.Snippet>
</Example>

<BreakpointsTable />

## Custom values

EUI's theme breakpoints can be overridden and extended. However, the default sizes (**xl** through **xs**) will always be present and cannot be removed.

<EuiThemeProvider
  modify={{ breakpoint: {
    xxs: 0,
    xs: 250,
    s: 500,
    m: 1000,
    l: 1500,
    xl: 2000,
    xxl: 2500,
  }
}}>
  <Example>
    <Example.Description>
      ### `EuiProvider` <Badge color="hollow">theme</Badge>

      Theme breakpoints can be overridden or added via `EuiProvider`'s or `EuiThemeProvider`'s `modify` prop.

      Excluding a default breakpoint key in your `breakpoint` override will use the EUI default value for that size as a fallback.
    </Example.Description>
    <Example.Preview>
      <CurrentCustomBreakpointPreview />
    </Example.Preview>
    <Example.Snippet>
      ```tsx
      <EuiThemeProvider
        modify={{
          breakpoint: {
            xxs: 0,
            xs: 250,
            s: 500,
            m: 1000,
            l: 1500,
            xl: 2000,
            xxl: 2500,
          },
        }}
      >
        <App />
      </EuiThemeProvider>
      ```
    </Example.Snippet>
  </Example>

  <BreakpointsTable />
</EuiThemeProvider>

---

### Packages Website Docs Getting Started Theming Tokens Colors Index (`packages/website/docs/getting-started/theming/tokens/colors/index.mdx`)

---
sidebar_position: 3
---

# Colors

import { EuiSpacer, EuiCodeBlock } from '@elastic/eui';

Elastic UI builds with a color palette that is based on predefined 14-step scales for a core set of three colors (blue / teal / pink) as well as a green / yellow / red qualitative set and combined with a 28-step grayscale.
Colors are defined to work well when combined for their semantic purpose.

When switching between light and dark color modes, the theme keys do not change, only their values do.

import ForcedColorsWarning from './_forced_colors_warning.mdx';

<ForcedColorsWarning />

## Brand colors

Elastic has two main brand colors. The other three are used for statefulness like indicating between successful and dangerous actions.

import { Example } from '@site/src/components';
import { BrandColorPreview } from './brand_color_preview';
import { BrandColorsTable } from './brand_colors_table';

<Example>
  <Example.Description>
    ### `euiTheme.colors[brand]` <Badge color="hollow">token</Badge>

    Most usages of the colors can be implemented simply by pulling and applying the values.
  </Example.Description>
  <Example.Preview>
    <BrandColorPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      background: ${euiTheme.colors.warning};
    `
    ```
  </Example.Snippet>
</Example>

<EuiSpacer />

<BrandColorsTable />

## Text colors

Each brand color also has a corresponding text variant that should be used specifically when coloring text. As is used in [EuiTextColor](../../../../components/display/text.mdx#coloring-text).

Use `textGhost` for text and icons on dark backgrounds and `textInk` on light backgrounds. 

import { TextColorPreview } from './text_color_preview';
import { TextColorsTable } from './text_colors_table';

<Example>
  <Example.Description>
    ### `euiTheme.colors[colorText]` <Badge color="hollow">token</Badge>

    Remember, when using any of the EUI colors for text, **use the text specific variant**.
  </Example.Description>
  <Example.Preview>
    <TextColorPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      color: ${euiTheme.colors.textWarning};
    `
    ```
  </Example.Snippet>
</Example>

<EuiSpacer />

<TextColorsTable />

## Background colors

Semantic background colors. These should be used according to their semantic purpose.

If a border is needed use the semantically related border color, e.g. `backgroundBasePrimary` with `borderBasePrimary`.

import { BackgroundColorPreview } from './background_color_preview';
import { BackgroundColorsTable } from './background_colors_table';

<Example>
  <Example.Description>
    ### `euiTheme.colors[background]` <Badge color="hollow">token</Badge>
  </Example.Description>
  <Example.Preview>
    <BackgroundColorPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      background-color: ${euiTheme.colors.backgroundFilledWarning};
    `
    ```
  </Example.Snippet>
</Example>

<EuiSpacer />

<BackgroundColorsTable />

## Borders

Semantic border colors. These should be used according to their semantic purpose.

The default border color (used as `border.color`) `borderBaseSubdued`.
Use the `base` border colors for most cases. Use `borderBasePlain` for a slightly stronger border (e.g. for forms).

import { BorderColorPreview } from './border_color_preview';
import { BorderColorsTable } from './border_colors_table';

<Example>
  <Example.Description>
    ### `euiTheme.colors[border]` <Badge color="hollow">token</Badge>
  </Example.Description>
  <Example.Preview>
    <BorderColorPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      border-color: ${euiTheme.colors.borderBaseWarning};
    `
    ```
  </Example.Snippet>
</Example>

<br />

<BorderColorsTable />

## Shades

A six-color grayscale palette. Variation beyond these colors is minimal and always done through computations against this set.

import { ShadeColorPreview } from './shade_color_preview';
import { ShadeColorsTable } from './shade_colors_table';

<Example>
  <Example.Description>
    ### `euiTheme.colors[colorShade]` <Badge color="hollow">token</Badge>

    Since the EUI colors usually evaluate to a hex value, the easiest way to perform color operations like transparency, shading, or tinting is by using the EUI provided methods of `transparentize()`, `shade()`, and `tint()` respectively.

    For all available color functions see the [Colors Utilities page](../../utilities/colors.mdx).
  </Example.Description>
  <Example.Preview>
    <ShadeColorPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      background: ${euiTheme.colors.lightShade};
    `
    ```
  </Example.Snippet>
</Example>

<EuiSpacer />

<ShadeColorsTable />

## Special colors

These are used a lot for special cases.

import { SpecialColorsPreview } from './special_colors_preview';
import { SpecialColorsTable } from './special_colors_table';

<Example>
  <Example.Description>
    ### `euiTheme.colors[special]` <Badge color="hollow">token</Badge>

    Constant colors are those that do not change no matter the theme or color mode and typically represent the polar extremes.
  </Example.Description>
  <Example.Preview>
    <SpecialColorsPreview />
  </Example.Preview>
  <Example.Snippet>
    ```
    css`
      color: ${euiTheme.colors.disabledText};
      background-color: ${euiTheme.colors.disabled};
    `
    ```
  </Example.Snippet>
</Example>

<EuiSpacer />

<SpecialColorsTable />

## Data visualization colors

:::note Guidance

Data visualization colors are semantically tied to data visualizations and are not meant for use in other contexts. Do not use these colors in other contexts.
:::

import { DataVisColorsTable, DataVisBackgroundColor } from './data_vis_colors_table';
import { DataVisColorsPreview } from './data_vis_colors_preview'


<Example>
  <Example.Description>
    ### `euiTheme.colors.vis[token]` <Badge color="hollow">token</Badge>

    The following colors are color-blind safe and should be used in categorically seried visualizations and graphics.
    They are meant to be contrasted against the value of `colors.backgroundBasePlain` for the current theme.

    See the [Data visualization text colors](#dataVisText) section for a note about text colors.

    See the [Color Contrast](#contrast) section for a note about color contrast.
  </Example.Description>
  <Example.Preview>
    <DataVisColorsPreview />
  </Example.Preview>
  <Example.Snippet>
    ```
    css`
      background-color: ${euiTheme.colors.vis.euiColorVis0};
    `
    ```
  </Example.Snippet>
</Example>

<EuiSpacer />

<DataVisColorsTable />

## Severity and Health colors

import { SeverityColorsTable } from './severity_colors_table';
import { SeverityColorsPreview } from './severity_colors_preview'

<Example>
  <Example.Description>
    ### `euiTheme.colors.severity[token]` <Badge color="hollow">token</Badge>

    Severity indicates an increasing level of risk and Health describes the status of an element that would 
    typically be associated with positive or negative values.

    More guidance is available in the [**Health and Color Pattern**](../../../../patterns/severity/).

    See the [Color Contrast](#contrast) section for a note about color contrast.
  </Example.Description>
  <Example.Preview>
    <SeverityColorsPreview />
  </Example.Preview>
  <Example.Snippet>
    ```
    css`
      background-color: ${euiTheme.colors.severity.risk};
    `
    ```
  </Example.Snippet>
</Example>

<EuiSpacer />

<SeverityColorsTable />


## Data visualization text colors {#dataVisText}

:::note Guidance

Data visualization text colors are semantically tied to data visualizations colors and are not meant for use in other contexts. 
:::

import { DataVisTextColorsTable } from './data_vis_colors_table';
import { DataVisTextColorsPreview } from './data_vis_colors_preview'


<Example>
  <Example.Description>
    ### `euiTheme.colors.vis[token]` <Badge color="hollow">token</Badge>

    The following colors are special text colors that are directly related to the data visualization colors. In dark mode these colors 
    equal the values of the regular data visualization colors and only differ in light mode to provide higher color contrasts. Their only purpose is to be used as possible 
    text fallbacks for data visualization colors.
  </Example.Description>
  <Example.Preview>
    <DataVisTextColorsPreview />
  </Example.Preview>
  <Example.Snippet>
    ```
    css`
      color: ${euiTheme.colors.vis.euiColorVisText0};
    `
    ```
  </Example.Snippet>
</Example>

<EuiSpacer />

<DataVisTextColorsTable />

## Contrast ratios and color modes {#contrast}

Our Data visualization colors and Health and Severity colors prioritize visual clarity and aesthetic appeal over strict contrast compliance in light mode. **This means some colors may not meet WCAG contrast requirements against light backgrounds**, as lighter and more saturated tones help differentiate data and create a more visually engaging experience.

However, in dark mode, all colors meet the minimum 3:1 contrast ratio, ensuring accessibility compliance. 

import { EuiTable, EuiTableHeader, EuiTableHeaderCell, EuiTableRow, EuiTableRowCell } from '@elastic/eui';

<EuiTable>
  <EuiTableHeader>
    <EuiTableHeaderCell>Color Mode</EuiTableHeaderCell>
    <EuiTableHeaderCell>Meets 3:1 contrast ratios?</EuiTableHeaderCell>
  </EuiTableHeader>
  <EuiTableRow>
    <EuiTableRowCell>Dark</EuiTableRowCell>
    <EuiTableRowCell>Yes</EuiTableRowCell>
  </EuiTableRow>
  <EuiTableRow>
    <EuiTableRowCell>Light</EuiTableRowCell>
    <EuiTableRowCell>No</EuiTableRowCell>
  </EuiTableRow>
  <EuiTableRow>
    <EuiTableRowCell>Light (high contrast)</EuiTableRowCell>
    <EuiTableRowCell>Yes</EuiTableRowCell>
  </EuiTableRow>
  <EuiTableRow>
    <EuiTableRowCell>Dark (high contrast)</EuiTableRowCell>
    <EuiTableRowCell>Yes</EuiTableRowCell>
  </EuiTableRow>
</EuiTable>

---

### Packages Website Docs Getting Started Theming Tokens Component Index (`packages/website/docs/getting-started/theming/tokens/component/index.mdx`)

# Components

Besides the global semantic tokens, EUI also provides a set of component-scoped tokens for customizing the appearance of specific EUI components in more detail.
These tokens are available via the `euiTheme.components` object and allow you to override or extend the default styles for specific EUI components. 
See the available component tokens <a href="https://github.com/elastic/eui/blob/main/packages/eui-theme-common/src/global_styling/variables/components.ts" target="_blank">here</a>.

:::warning Token stability
Not all component tokens are equally stable yet and might be changed or removed in the future. Use with caution.
:::

import { ButtonsTable } from './buttons_table';
import { FormsTable } from './forms_table';

### Buttons

import { Example } from '@site/src/components';
import { ButtonsPreview } from './buttons_preview';

<Example>
  <Example.Description>
    #### `euiTheme.components.buttons[token]` <Badge color="hollow">token</Badge>
  </Example.Description>
  <Example.Preview>
    <ButtonsPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      background: ${euiTheme.components.buttons.backgroundPrimary};
    `
    ```
  </Example.Snippet>
</Example>

<ButtonsTable />

### Forms

import { FormsPreview } from './forms_preview';

<Example>
  <Example.Description>
    #### `euiTheme.components.forms[token]` <Badge color="hollow">token</Badge>
  </Example.Description>
  <Example.Preview>
    <FormsPreview />
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    css`
      background: ${euiTheme.components.forms.backgroundDisabled};
    `
    ```
  </Example.Snippet>
</Example>

<FormsTable />

---

### Packages Website Docs Getting Started Theming Tokens Typography Index (`packages/website/docs/getting-started/theming/tokens/typography/index.mdx`)

# Typography

For most of your usages we recommend using [EuiText](../../../../components/display/text.mdx) or [EuiTitle](../../../../components/display/title.mdx) components directly **instead** of these theme tokens. Or head to the [text utilities](../../utilities/typography.mdx) page for helper classes and functions.

Hooks and tokens are provided for:

- [Font weight](./font-weight.mdx)
- [Font settings](./font-settings.mdx)
- [Font scale hook](./font-scale-hook.mdx)

---

### Packages Website Docs Getting Started Theming Utilities Shadows Index (`packages/website/docs/getting-started/theming/utilities/shadows/index.mdx`)

---
sidebar_position: 10
---

# Shadows

EUI provides 5 shadow sizes (`xs`, `s`, `m`, `l`, `xl`) that can be applied in two directions: `down` (default) and `up`.

The provided EUI shadow utilities use the underlying theme shadow tokens and automatically add required adjustments 
for dark mode and high contrast mode that ensure expected visibility.

:::warning Never use the underlying shadow tokens separately
Always use the shadow utilities to ensure proper styling.
:::

These shadow utilities handle the following additional style adjustments:

- adds a light, 4-sided `border` style in Dark mode to increase elevated item visibility
- replaces the `box-shadow` in High Contrast mode with `border` to ensure visibility in high contrast themes


import { Example } from '@site/src/components';
import { EuiSpacer } from '@elastic/eui';

## Usage

<Example.Snippet>
  ```ts
  import { euiShadow } from '@elastic/eui';

  const styles = css`
    ${euiShadow(euiThemeContext, 's')};
    ${euiShadow(euiThemeContext, 's', { direction: 'down' })};
  `;  
  ```
</Example.Snippet>



import { ShadowsTable } from './shadows_table';

### Direction: `down`

<ShadowsTable />

### Direction: `up`

<ShadowsTable direction="up" />

### Dark mode floating border customization

By default the shadow utilities add a light, 4-sided `border` style in Dark mode. In some cases where different shadowed elements are being composed together, 
this might result in duplicate neighboring borders. To adjust this, use the `border` option on the `euiShadow` utility to adjust or remove the border output.

:::info The additional border is only applied and visible in dark mode.
:::

<Example.Snippet>
  ```ts
  import { euiShadow } from '@elastic/eui';

  const styles = css`
    ${euiShadow(euiThemeContext, 's', { border: 'none'})}
    ${euiShadow(euiThemeContext, 's', { border: 'all'})}
    ${euiShadow(euiThemeContext, 's', { border: 'top'})}
    ${euiShadow(euiThemeContext, 's', { border: 'bottom'})}
    ${euiShadow(euiThemeContext, 's', { border: 'left'})}
    ${euiShadow(euiThemeContext, 's', { border: 'right'})}
    ${euiShadow(euiThemeContext, 's', { border: 'horizontal'})}
    ${euiShadow(euiThemeContext, 's', { border: 'vertical'})}
  `;  
  ```
</Example.Snippet>

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Scroll behavior

:::warning Do not combine shadow utils and scroll behavior styles on the same element
:::

Combining EUI shadow utils like `euiShadow()` and scroll behavior (e.g. via `overflow: scroll` or `overflow: auto`) on the same element will cause the floating border 
in DARK mode to be scrolled. If you want to combine both, separate the styles onto different elements by placing the shadow util on the outer wrapper and the scroll 
behavior on the inner one.

<Example.Snippet>
  ```ts
  import { euiShadow } from '@elastic/eui';
  import { css } from '@emotion/react';

  const Component = () => {
    const euiThemeContext = useEuiTheme();

    const shadowStyles = css`
      ${euiShadow(euiThemeContext, 's')};
    `;
    const scrollContainerStyles = css`
      max-height: 100px;
      overflow-y: auto;
      /* specific scroll bar styling */
      ${useEuiScrollBar()};
    `;

    return (
      <div css={shadowStyles}>
        <div css={scrollContainerStyles}>
          // scrollable content
        </div>
      </div>
    );
  }
  ```
</Example.Snippet>

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Hover states

Each shadowed surface, when interactive, follows the same hover effect rule: it moves up one level. 

- `xs` hovered → `s`
- `s` hovered → `m`
- `m` hovered → `l`
- `l` hovered → `xl`
- `xl` hovered → `hover.xl`

You don't need to remember this rule though. You can instead use the available `euiShadowHover` utility which 
applies the expected hover shadow based on the base size.

```tsx interactive
import React, { useState } from 'react';
import { useEuiTheme, EuiSelect, EuiSpacer, EuiCodeBlock } from '@elastic/eui';

type ShadowSize = 'xs' | 's' | 'm' | 'l' | 'xl';

export default () => {
  const euiThemeContext = useEuiTheme();
  const { euiTheme } = euiThemeContext;
  const [selectedSize, setSelectedSize] = useState<ShadowSize>('m');
  const options = [
    { value: 'xs', text: 'xs' },
    { value: 's' , text: 's' },
    { value: 'm' , text: 'm' },
    { value: 'l' , text: 'l' },
    { value: 'xl', text: 'xl' },
  ];

  const styles = css`
    ${euiShadow(euiThemeContext, selectedSize)}
    border-radius: ${euiTheme.border.radius.medium};
    
    &:hover {
      ${euiShadowHover(euiThemeContext, selectedSize)}}
    }
  `
  const stylesText = `
const styles = css\`
  \${euiShadow(euiThemeContext, '${selectedSize}')}
  &:hover {
    \${euiShadowHover(euiThemeContext, '${selectedSize}')}
  }
\`
  `

  return (
    <>
      <EuiCodeBlock css={styles} language="js">
        {stylesText}
      </EuiCodeBlock>
      <EuiSpacer />
      <EuiSelect
        aria-label="Shadow Size" 
        prepend="Size" 
        compressed 
        options={options}
        value={selectedSize}
        onChange={(e) => { setSelectedSize(e.target.value) }}
      />
    </>
  );
}
```

---

### Consuming Eui React Router (`wiki/consuming-eui/react-router.md`)

# Using react-router with EUI

EUI doesn't prescribe the use of any particular routing library, and we also don't want to incur
the maintenance burden of supporting router-specific components. For these reasons, EUI doesn't
publish any tools for working with `react-router` (or any other routing lib). However,
integrating EUI with `react-router` on the consumer's side is fairly straightforward.

## How react-router works

Links in `react-router` accept a `to` prop and convert this to both `href` and `onClick` props
under the hood. The `onClick` is used to push a new `history` location, and the `href` allows you to
open the link in a new tab. Any mechanism for integrating EUI with `react-router` needs to bridge
this `to` prop with EUI components' `href` and `onClick` props.

- [`react-router` 5.x](#react-router-5x) - Kibana uses 5.3.4
- [`react-router` 6.x / 7.x](#react-router-6x--7x) - Cloud UI uses 6.x (`react-router-dom`)
- [`react-router` 3.x](#react-router-3x) and [4.x](#react-router-4x) - historical

## Techniques

There are many techniques for integrating EUI with `react-router` ([see below](#techniques-we-dont-recommend) for some techniques we don't recommend), but we think these two are the strongest:

### 1) Conversion function (recommended)

You can use a conversion function to convert a `to` value
to `href` and `onClick` values, which you can then pass to any EUI button or link component.
Many EUI components are designed to accept both props if they accept one.

This technique is recommended because of its flexibility. As a consumer, you have the option to
use either the `href` or `onClick` values, or both. It's also terser than the second option.

```jsx
<EuiLink {...getRouterLinkProps('/location')}>Link</EuiLink>
```

### 2) Adapter component

Alternatively, you can create a component which will consume or encapsulate the
`getRouterLinkProps` logic, and use that in conjunction with a
[`render` prop](https://reactjs.org/docs/render-props.html).

```jsx
const RouterLinkAdapter = ({to, children}) => {
  const {href, onClick} = getRouterLinkProps(to);
  return children(href, onClick);
};

<RouterLinkAdapter to="/location">
  {(onClick, href) => <EuiLink onClick={onClick} href={href}>Link</EuiLink>}
<RouterLinkAdapter/>
```

## react-router 3.x

### Share `router` globally

To enable these techniques, you'll need to make the `router` instance available outside of React's
`context`. One method for doing this is to assign it to a globally-available singleton within your
app's root component.

```jsx
import { registerRouter } from './routing';

// App is your app's root component.
class App extends Component {
  // NOTE: As an alternative to consuming context directly, you could use the `withRouter` HOC
  // (https://github.com/ReactTraining/react-router/blob/v3/docs/API.md#withroutercomponent-options)
  static contextTypes = {
    router: PropTypes.shape({
      createHref: PropTypes.func.isRequired,
      push: PropTypes.func.isRequired,
    }).isRequired,
  }

  constructor(...args) {
    super(...args);

    // Share the router with the app without requiring React or context.
    registerRouter(this.context.router);
  }
}

// <App> *must* be a child of <Router> because <App> depends on the context provided by <Router>
ReactDOM.render(
  <Router history={history}>
    <Route path="/" component={App} />,
  </Router>,
  appRoot
)
```

### Hot module reloading

Note that if using HMR, you'll need to re-register the router after a hot reload.

```js
  componentDidUpdate() {
    // You may want to add some conditions here to cull this logic from a production build,
    // e.g. `if (process.env.NODE_ENV !== 'production' && module.hot)`
    this.registerRouter();
  }
```

### `routing.js` service

You can create a `routing.js` service to surface the `registerRouter` method as well as your
conversion function (called `getRouterLinkProps` here).

```js
// routing.js

const isModifiedEvent = event => !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);

const isLeftClickEvent = event => event.button === 0;

const resolveToLocation = (to, router) => typeof to === 'function' ? to(router.location) : to;

let router;
export const registerRouter = reactRouter => {
  router = reactRouter;
};

/**
 * The logic for generating href and onClick handlers from the `to` prop is largely borrowed from
 * https://github.com/ReactTraining/react-router/blob/v3/modules/Link.js.
 */
export const getRouterLinkProps = to => {
  const location = resolveToLocation(to, router);
  const href = router.createHref(location);
  const onClick = event => {
    if (event.defaultPrevented) {
      return;
    }

    // If target prop is set (e.g. to "_blank"), let browser handle link.
    if (event.target.getAttribute('target')) {
      return;
    }

    if (isModifiedEvent(event) || !isLeftClickEvent(event)) {
      return;
    }

    // Prevent regular link behavior, which causes a browser refresh.
    event.preventDefault();
    router.push(location);
  };

  return {href, onClick}
};
```

## react-router 4.x

### Share `router` globally

Setup is slightly different with `react-router` 4.x. To enable these techniques, you'll need to make
the `router` instance available outside of React's `context`. One method for doing this is to assign
it to a globally-available singleton within your app's root component.

```jsx
import { registerRouter } from './routing';

// App is your app's root component.
class App extends Component {
  static contextTypes = {
    router: PropTypes.shape({
      history: PropTypes.shape({
        push: PropTypes.func.isRequired,
        createHref: PropTypes.func.isRequired
      }).isRequired
    }).isRequired
  }

  constructor(...args) {
    super(...args);

    // Share the router with the app without requiring React or context.
    registerRouter(this.context.router);
  }
}

// <App> *must* be a child of <Router> because <App> depends on the context provided by <Router>
ReactDOM.render(
  <Router>
    <App />,
  </Router>,
  appRoot
)
```

### Hot module reloading

[See above](#hot-module-reloading).

### `routing.js` service

You can create a `routing.js` service to surface the `registerRouter` method as well as your
conversion function (called `getRouterLinkProps` here).

```jsx
// routing.js

import { createLocation } from 'history';

const isModifiedEvent = event => !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);

const isLeftClickEvent = event => event.button === 0;

let router;
export const registerRouter = reactRouter => {
  router = reactRouter;
};

/**
 * The logic for generating href and onClick handlers from the `to` prop is largely borrowed from
 * https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/Link.js.
 */
export const getRouterLinkProps = to => {
  const location = typeof to === "string"
    ? createLocation(to, null, null, router.history.location)
    : to;

  const href = router.history.createHref(location);

  const onClick = event => {
    if (event.defaultPrevented) {
      return;
    }

    // If target prop is set (e.g. to "_blank"), let browser handle link.
    if (event.target.getAttribute('target')) {
      return;
    }

    if (isModifiedEvent(event) || !isLeftClickEvent(event)) {
      return;
    }

    // Prevent regular link behavior, which causes a browser refresh.
    event.preventDefault();
    router.history.push(location);
  };

  return {href, onClick}
};
```

## react-router 5.x

### react-router 5.0

The React Context handling has changed in in 5.0 and we can't rely on it anymore. A solution is to create
an `extractRouter` HOC that will intercept the router and send it to your custom handler.


```jsx
// extractRouter.hoc.js
import { withRouter } from 'react-router-dom';

export const extractRouter = onRouter => WrappedComponent =>
  withRouter(
    class extends Component {
      componentDidMount() {
        const { match, location, history } = this.props;
        const router = { route: { match, location }, history };
        onRouter(router);
      }

      render() {
        return <WrappedComponent {...this.props} />;
      }
    }
  );
```

```jsx
import { extractRouter } from './hoc';
import { registerRouter } from './routing';

// App is your app's root component.
class App extends Component {
  ...
}

const AppMount = extractRouter(registerRouter)(App);

// <App> *must* be a child of <Router> because <App> depends on the context provided by <Router>
ReactDOM.render(
  <Router>
    <AppMount />,
  </Router>,
  appRoot
)
```

### react-router 5.1

In react-router 5.1, we can fully capitalize in the React Hooks utility, in this case, `useHistory`. Using this, we do not need other HOC wrapper files and global router variable. We just need to create the file below, and then use it anywhere by importing `EuiCustomLink`. There is an example repository for this: https://github.com/Imballinst/elastic-react-router-hooks.

```jsx
// File name: "EuiCustomLink.js".
import React from 'react';
import { EuiLink } from '@elastic/eui';
import { useHistory } from 'react-router';

const isModifiedEvent = (event) =>
  !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);

const isLeftClickEvent = (event) => event.button === 0;

const isTargetBlank = (event) => {
  const target = event.target.getAttribute('target');
  return target && target !== '_self';
};

export default function EuiCustomLink({ to, ...rest }) {
  // This is the key!
  const history = useHistory();

  function onClick(event) {
    if (event.defaultPrevented) {
      return;
    }

    // Let the browser handle links that open new tabs/windows
    if (isModifiedEvent(event) || !isLeftClickEvent(event) || isTargetBlank(event)) {
      return;
    }

    // Prevent regular link behavior, which causes a browser refresh.
    event.preventDefault();

    // Push the route to the history.
    history.push(to);
  }

  // Generate the correct link href (with basename accounted for)
  const href = history.createHref({ pathname: to });

  const props = { ...rest, href, onClick };
  return <EuiLink {...props} />;
}
```

```jsx
// App is your app's root component.
class App extends Component {
  ...
}

// <App> *must* be a child of <Router> because <App> depends on the context provided by <Router>
ReactDOM.render(
  <Router>
    <App />,
  </Router>,
  appRoot
)
```

## react-router 6.x / 7.x

Cloud UI uses `react-router-dom` 6.x. AutoOps uses 7.x. The same `useNavigate` / `useHref` pattern works for both.

```jsx
// File name: "EuiCustomLink.js".
import React from 'react';
import { EuiLink } from '@elastic/eui';
import { useHref, useNavigate } from 'react-router-dom';

const isModifiedEvent = (event) =>
  !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);

const isLeftClickEvent = (event) => event.button === 0;

const isTargetBlank = (event) => {
  const target = event.currentTarget.getAttribute('target');
  return target && target !== '_self';
};

export default function EuiCustomLink({ to, onClick: consumerOnClick, ...rest }) {
  const navigate = useNavigate();
  const href = useHref(to);

  function onClick(event) {
    consumerOnClick?.(event);

    if (event.defaultPrevented) {
      return;
    }

    if (isModifiedEvent(event) || !isLeftClickEvent(event) || isTargetBlank(event)) {
      return;
    }

    event.preventDefault();
    navigate(to);
  }

  return <EuiLink {...rest} href={href} onClick={onClick} />;
}
```

Wrap the app in a router from `react-router-dom` (`BrowserRouter`, `MemoryRouter`, etc.). `EuiCustomLink` must render inside that router.

## Techniques we don't recommend

### Using EUI classes with the react-router `<Link>` component

It's possible to integrate EUI with `react-router` by using its CSS classes only:

```jsx
<Link className="euiLink" to="/location">Link</Link>
```

But it's important to be aware of two caveats to this approach:

* EUI's components contain a lot of useful behavior. For example, `EuiLink` will render either
  a button or an anchor tag depending on the presence of `onClick` and `href` props. It will also
  create a secure `rel` attribute if you add `target="_blank"`. Consumers lose out on these
  features if they use EUI's CSS instead of its React components.
* This creates a brittle dependency upon the `euiLink` CSS class. If we were to rename this
  class in EUI, this would constitute a breaking change and we'd make a note of it in the change
  log. But if a consumer doesn't notice this note then the only way they could detect that something
  in their UI has changed (and possibly broken) would be through manual testing.

---

### Contributing To Eui Running Eui Locally (`wiki/contributing-to-eui/running-eui-locally.md`)

# Setting up and running EUI locally

The below instructions run EUI's [documentation site](https://eui.elastic.co/) locally, with any changes made in `packages/eui/src/` reflected.

> [!IMPORTANT]
> This repository is a monorepo, meaning that it contains sources of multiple packages within a single git repository. You can find all packages in the [`packages`](../../packages) directory.
> When dealing with EUI ([`@elastic/eui`](https://www.npmjs.com/package/@elastic/eui) package), most of the work will be done from within the [`packages/eui`](../../packages/eui) directory.

## Setup

### Node

We depend upon the version of node defined in [.nvmrc](../../.nvmrc).

You will probably want to install a node version manager. [nvm](https://github.com/nvm-sh/nvm) is recommended.

To install and use the correct node version with `nvm`:

```shell
nvm install
```

### Dependencies

EUI uses [Yarn v4](https://yarnpkg.com/getting-started/install) for dependency management. We use `npm` for release purposes only.

Unlike Yarn Classic and other package managers, Yarn v4 isn't supposed to be installed globally.
Instead, it utilizes [corepack](https://nodejs.org/api/corepack.html) - a modern way to manage package managers built straight into Node.js.

First, enable corepack:
```shell
corepack enable
```

`yarn` is now configured on your machine, and you can use it just like any other CLI command.
Corepack will always use the right Yarn version, even when switching branches.

With `yarn` set up and ready to go, use it to install EUI dependencies:

```shell
yarn
```

Remember to run `yarn` whenever you're switching branches to ensure all dependencies are installed and have correct versions.

## Running

### Storybook

This is the recommended way to work with components locally. Storybook runs at [http://localhost:6006/](http://localhost:6006/).

> [!IMPORTANT]
> The commands below must be run from the `packages/eui` directory. Running `yarn start` from the repo root will exit with an error message pointing you there.

If running for the first time, build dependent workspaces:

```shell
yarn build:workspaces
```

You can run Storybook with the following command:

```shell
yarn start
```

### Website

If running for the first time, build dependent workspaces:

```
yarn workspace @elastic/eui-website build:workspaces
```

You can run the documentation locally at [http://localhost:3000/](http://localhost:3000/) with the following command:

```shell
yarn workspace @elastic/eui-website start
```

If another process is already listening on port 3000, the next free port will be used. Alternatively, you can specify a port:

```shell
yarn workspace @elastic/eui-website start --port 9000
```

See http://docusaurus.io/docs/cli#docusaurus-cli-commands.

### Updating theme code

Theme specific code lives in standalone workspace packages in the EUI repo. `/eui-theme-common` holds shared code for base theme building and types, while `/eui-theme-borealis` holds theme specific token and style definitions.
When making changes to either of these packages you need to manually build the packages for the updates to be available in your local development environment.

For building both packages at the same time, run the following in `/packages/eui`:
```shell
yarn build:workspaces
```

For building the packages separately, run the following in the respective package directory:
```shell
yarn build
```

## VSCode setup

### Eslint

If you're developing in VSCode and you are using the [`ESLint`](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) extension for VSCode you will notice that ESLint is showing errors about not finding config files _since the monorepo setup changes_.
To fix this add `eslint.workingDirectories` to your VSCode settings and pass all working directories as relative paths.

```json
{
  "eslint.workingDirectories": ["./packages/eui"]
}
```

---

### Contributing To Eui Developing Creating Component Files (`wiki/contributing-to-eui/developing/creating-component-files.md`)

# Component file & folder architecture

## Creating components manually

### Create the component directory

1. Create a directory for your component in `packages/eui/src/components/`. All folder and file names should be `snake_cased`.

#### Logical groupings of directories

If a component has any of the following:

1. Subcomponents (`<EuiToolBar>` and `<EuiToolBarSearch>`),
2. Tightly-coupled components (`<EuiButton>` and `<EuiButtonGroup>`)
3. Or you just want to group some related components together (`<EuiTextInput>`, `<EuiTextArea>`, and `<EuiCheckBox>`)

then they belong in the same logical grouping (i.e., directory). A component directory can have as many subcomponents and corresponding `*.test.tsx` or `*.style.ts` as needed. If a component directory starts to feel overwhelmingly cluttered due to multiple internal sub-components (e.g. EuiDataGrid), make liberal use of subdirectories to help organize your component by concern or by feature.

### Create the React component

1. Create the React component(s) as TypeScript `.tsx` file(s) in your new component directory.
2. Export these components from an `index.ts` file.
3. Re-export these components from `packages/eui/src/components/index.ts`.

This makes your React component available for import into your project.

### Create component style files

1. Create a `{component name}.styles.ts` file inside the same component directory.

Refer to the [Writing styles with emotion](./writing-styles-with-emotion.md) guidelines for more instruction.

### Create tests and documentation examples

Your component folder should also contain `{component name}.test.tsx` unit tests for each component being created/exported. [See the testing wiki resources for more in-depth guidelines](../testing/).

Your component should have a corresponding `packages/website/` documentation page or example. [See the documenting wiki resources for more guidelines](../documenting/).

## Creating components with Yeoman

From the command line, run the following command:

```shell
yarn yo-component
```

First, you'll be prompted for what kind of component to create:

| Choice             | Description                               |
|--------------------|-------------------------------------------|
| Stateless function | A stateless functional React component    |
| Component class    | A class-based React component             |

Next, you'll reply to a series of prompts.

### "What's the name of this component?"

Yeoman will ask you what to name the file. It expects you to provide the name in snake case. Yeoman will automatically add file extensions and a "eui" prefix so you should leave those out.

### "Where do you want to create this component's files?"

The path to the directory where the files should live. Defaults to the last directory you specified for this prompt, or to EUI's components directory if you haven't specified one.

If you want Yeoman to automatically generate a directory to organize the files, that directory will be created inside of the location you specify (see next prompt).

### "Does it need its own directory?"

This will automatically generate a directory with the same name as the file, but without a "eui" prefix. This defaults to `YES`.

### Done!

Yeoman will generate the files you need in your project's folder system.

For your convenience, it will also output some snippets you can tweak to import and re-export the generated JS and style files.

### Generating documentation

To also use Yeoman to generate component documentation, see [creating documentation pages with Yeoman](../documenting/creating-documentation-pages.md#creating-documentation-pages-with-yeoman).

---

### Contributing To Eui Developing Creating Icons (`wiki/contributing-to-eui/developing/creating-icons.md`)

# Creating icons

EUI provides an ever-growing set of [icons][icons], but our set can be incomplete. If you find you need an icon that does not exist, create a new [icon request](https://github.com/elastic/eui/issues/new?template=06-icon-request.md) issue. A designer from the EUI team will respond to discuss your needs.

If you are willing and able to design the icon yourself, this document describes the [design guidelines](#design-guidelines), cleaning up the SVG, and getting it added to EUI. While designers on the EUI team are available to assist, we greatly appreciate your contributions and pull requests.

If you read through these guidelines or begin designing your icon and realize you're in too deep, then create an issue in this repo and request assistance. An EUI team member will reply and discuss options.

_**Note on 3rd-party / custom SVGs**_
- The `EuiIcon` component accepts external references to custom SVG files, so you can maintain the icon in your consuming application.
- This practice should also be used for any **3rd-party logos**. For a number of reasons, the EUI team has moved away from maintaining a set of 3rd party logos. Please use the custom SVG option going forward.

## Content

While we're pretty much open to all requests, we ask that you first try to use an existing icon as this helps us avoid having multiple versions of the same glyph.  Likewise, if there is a universally known icon that represents an action, we recommend leveraging those existing patterns (e.g. a scissors for cut).

Finding and sharing reference icons is a great way to get moving if you're uncertain of the general shape. Post these examples to your issue and we'll provide feedback.

Lastly, we reserve the right to reject any icons that do not fit the EUI style or may be deemed inappropriate.

## Design guidelines

### Linear icon scaling

- Each icon should be comprised of a single vector glyph that can be scaled linearly, up or down. 
- This approach greatly reduces maintenance and implementation complexity.
- Note that minor icon blurriness/anti-aliasing can occur when icons are sized to dimensions other than those divisible by the source viewbox dimensions.

<img width="622" height="309" alt="linear_icon_scaling" src="https://github.com/user-attachments/assets/87ec63aa-4237-4316-881f-180006d0c09e" />

### 16x16px viewbox

- All icons should be crafted on a 16x16px viewbox. 
- As this is the default size for all icons in EUI, this will help ensure all icons look their best by default.

<img width="622" height="320" alt="16x16_viewbox" src="https://github.com/user-attachments/assets/fe480f11-56c9-4b6b-bd94-0c12e3d54577" />

### Strokes only (with some exceptions)

- Nearly all icons should be lined/stroked, using a 1px stroke width (on a 16x16px canvas).
- In special cases, a filled variant of an icon can be created for concepts that convey a toggle action and need to represent this toggle action in an interface. For example, a star icon may have a filled variant to indicate toggling of “favorite” status.
- In a very limited subset of icons, a filled variant of an icon can be created for concepts that convey status (check, error, warning).
- In special cases, a circled variant of an icon can be created for use in empty/tertiary buttons when it comprises of a simple shape that may inadvertently appear awkward or overly diminished otherwise. Examples include simple icons such as a plus or minus.

<img width="622" height="320" alt="strokes_only" src="https://github.com/user-attachments/assets/af7e0da3-f780-41aa-9561-24862f6b8cee" />

### Snap to pixel grid (when possible)

- When possible, align/snap your icon to the 16x16px viewbox grid. Doing so will ensure that your icon appears as sharp as possible, with little or no blurring/anti-aliasing.
- It will not always be possible to snap to the grid in all situations. For example, if you have an element of your icon that is 1px and needs to be centered on the 16x16 viewbox, it is impossible to align to the grid in this case. In such situations, it is fine to snap to half-pixel increments in order to center that odd-width element on an even-width canvas.
- Do not offset your glyph in the viewbox only for the purpose of aligning it to the pixel grid. Doing so may inadvertantly make the icon appear misaligned agaisnt other elements in your design (due to the offset) or create other inconsistencies when compared with similar icons.

<img width="622" height="320" alt="snap_to_pixel" src="https://github.com/user-attachments/assets/e709124e-be89-4b28-addb-c7a3cdda27b8" />

### Square endpoints only

- All icon strokes should apply square endpoints. Rounded endpoints should never be used.

<img width="622" height="320" alt="square_endpoints_only" src="https://github.com/user-attachments/assets/ebd1fdb3-9e25-44a6-bb60-7e17c9966cc0" />

### Round outer corners, square inner corners

- All stroke corners should be round on the outside and square on the inside.
- Outer rounded corner radius should be 1px. How this is put into effect in Figma depends on how your stroke is aligned (ex. inside, center, outside).
  - If stroke is inside, set corner radius to 1px. 
  - If stroke is center, set corner radius to 0.5px.
  - If stroke is outside, set stroke join to be round.
- The only exception to this rule is when the application of rounded outer corners comes at the detriment to the icon being conveyed. In such situations, having both inner and outer corners square is acceptable.

<img width="622" height="320" alt="round_outer_corners" src="https://github.com/user-attachments/assets/010adae6-4b93-438e-9361-9438497ae2bf" />

### 2D perspective only (with some exceptions)

- Icons with three dimensional perspectives should generally be avoided, unless the concept being conveyed is significantly more identifiable with that perspective (ex. layers).
- Showing depth or a stacking order of objects (i.e. when something is in front of something else) should be achieved with the use of negative (subtraction) space.

<img width="622" height="320" alt="2d_perspective_only" src="https://github.com/user-attachments/assets/126d6e62-ddcf-4d79-8b3a-98534dd935b6" />

### 1px safe zone

- At the default 16x16px viewbox, a safe zone of 1px around the viewbox should be kept free of icon elements if possible. Doing so will avoid any inadvertent clipping if/when the icon is scaled.

<img width="622" height="320" alt="1px_safe_zone" src="https://github.com/user-attachments/assets/0c6401d1-ae0e-4311-9b66-c156dd749df0" />

### Consistent optical sizing and alignment

- Icons in close proximity to each other should have similar optical sizing, so as to not appear out-of-place. While this is subjective, designers should still evaluate newly created icons against a variety of existing icons to ensure icons are not disproportionately sized.
- Utilize the provided keyline shapes for general sizing guidance.
- Icons should appear optically in the vertical and horizontal center of their viewbox. In most cases, this means simply center aligning the icon in the frame. In other scenarios (ex. triagular shapes), the designer may need to offset the icon slightly in order to appear in the optical center.

<img width="622" height="320" alt="consitent_optical_sizing" src="https://github.com/user-attachments/assets/71471e69-e9c1-4f69-8692-bea9c1942de5" />

### Descriptive icon naming

- When possible, try to name icons by the object being conveyed.
- If the object is too abstract or obscure to use for the icon name, naming the icon by the action it is attempting to convey is an acceptable alternative.
- Grouped/related icons should have a common prefix string to ensure they are in close proximity when in alphabetical order.
- Common variants should use a consistent suffix string across (ex. Circle, Fill, Slash). Note that if the icon is not a variant, there is no need to apply such a suffix (ex. see the new `info` icon)
- Icon component and EUI prop names should be in camel case (ex. myIcon).
- SVG files for inclusion in the EUI repo should be in snake case (ex. my_icon.svg).
- Apply synonyms for the icon in the Figma component description to ensure designers are able to easily find icons, even if not searching for the exact name.

#### _For Figma users_
_As a reference, you can view and duplicate our [Figma Icon Template Component](https://www.figma.com/design/FHys7gLzyvD1gc9DrJM6D8/Elastic-UI--Borealis-?node-id=14007-378&t=hP0dvrW2tEiYGxA0-4)._

#### _For non-Figma users_
_While we use Figma to maintain our internal design library, you can use any design tool to produce the SVG file._

## Add the icon to the EUI repo

Once you've designed your new icon, the last step is adding it to the EUI repo.

### Clean the SVG

EUI provides SVG icon formats only. After exporting your icon as an SVG from your design tool, open it in a code or text editor and remove any unnecessary elements and attributes, such as:
- `<def>...</def>`
- `<use>...</use>`
- `id: <value>`
- `fill: <value>`

_**Note**: Figma users can use the [SVG Export plugin][svg-plugin] to optimize SVG sizes and code._

### Prepare the pull request

Create a new feature branch against this repo and make the following changes:

_1. Add your glyph to the `EuiIcon` component_
- Add your SVG file to the `/packages/eui/src/components/icon/svgs` folder.
- Add a reference to the SVG import in `/packages/eui/src/components/icon/icon_map.ts` in alphabetical order.

_2. Add metadata to the icon loader_ _(optional)_
- If you want the icon to participate in docs search or be grouped into a specific set, attach metadata next to the import.
- Example:

```ts
myIcon: withMetadata(() => import('./assets/my_icon'), {
  category: 'glyph',
  synonyms: ['my icon', 'alias'],
}),
```

- `category` and `synonyms` are optional, but useful when the icon should appear in the docs search experience.

_3. Compile and test_
- Go to the `packages/eui` directory
- Run `yarn compile-icons`
- Preview your icon locally by running `yarn workspace @elastic/eui-website build:workspaces && yarn workspace @elastic/eui-website start` and opening http://localhost:3000/docs/components/display/icons/
- Switch the docs to dark mode and verify that the icon is visible (all paths should be filled with the reverse color)
- Run `yarn run test-unit icon -u` to create/update the jest snapshots

If everything looks good, then commit your changes, push up your branch, and open a PR! :raised_hands:

Opening a PR will notify the EUI team that your work is ready for review. Please include a screenshot in the description and reference the issue that your PR fixes.

### Ship it
Once your PR is approved, you will be able to merge it and give yourself a well-deserved pat on the back. Finally, stay tuned for the next release of EUI at which point your icon will become available to the masses and appear on the EUI docs site.

:trophy: _**Welcome to the Official EUI Icon Design Club**_ :beers:

---

_\** Run `yarn workspace @elastic/eui-website start` to view the EUI docs site locally._


[icons]: https://eui.elastic.co/docs/components/display/icons/#glyphs
[icon-request-issue]: https://github.com/elastic/eui/issues/new?template=06-icon-request.md
[docs]: https://eui.elastic.co/
[svg-plugin]: https://www.figma.com/community/plugin/814345141907543603/SVG-Export

---

### Contributing To Eui Developing Developing In Kibana (`wiki/contributing-to-eui/developing/developing-in-kibana.md`)

# Developing EUI locally in Kibana

This guide explains how to develop EUI library locally while seeing changes reflected in a local Kibana instance.

> [!TIP]
> This is the workflow for **rapid local development** — a custom watcher rebuilds EUI packages and syncs them into your local Kibana's `node_modules` as you edit. To validate your EUI changes against **Kibana CI** (in a Kibana draft PR), use `yarn build-pack` instead — see [Testing EUI features in Kibana](../testing/testing-in-kibana.md).

## Prerequisites

- You have this repository forked and cloned:
  ```bash
  git clone https://github.com/<your-username>/eui.git
  cd eui
  nvm use
  yarn
  ```
- You have [Kibana repository](https://github.com/elastic/kibana) forked and cloned:
  ```bash
  git clone https://github.com/<your-username>/kibana.git
  cd kibana
  nvm use
  corepack enable
  corepack prepare pnpm@$(node -pe "require('./package.json').engines.pnpm.replace(/^\D*/, '')") --activate
  pnpm kbn bootstrap
  ```
- (Optional) EUI and Kibana should be sibling directories for simplest DX:
  ```text
  Projects/
  ├── eui/
  └── kibana/
  ```

## Usage

### Start Kibana from EUI

In the **EUI** repository root, run the Kibana processes in one terminal:

```bash
yarn watch:kibana
```

This starts the EUI watcher, then starts Elasticsearch and Kibana after the initial EUI build. Kibana's Rspack MultiCompiler watches the synced EUI output and rebuilds the affected shared and Kibana bundles. Press `Ctrl+C` to stop all managed processes.

If Elasticsearch already uses port `9200`, or Kibana uses port `5601`, the corresponding process is not started.

If your Kibana directory is located elsewhere:

```bash
yarn watch:kibana --kibana-dir=/path/to/kibana
# Shortcut:
yarn watch:kibana -d /path/to/kibana
```

To watch only one EUI package:

```bash
yarn watch:kibana --package @elastic/eui
# Shortcut:
yarn watch:kibana -p @elastic/eui
```

## How it works

The integration relies on a chain of file watchers and build triggers to propagate changes from EUI source code to the browser running Kibana.

### Data flow

1. The script watches `src` directories using `chokidar`.
2. With `--kibana`, `@elastic/eui` runs one complete `build:optimize-es`, then Babel-compiles only changed source files. Changed JSON and SVG files are copied directly.
3. `@elastic/eui` syncs only changed `optimize/es` files into Kibana's `node_modules` and touches `package.json` once per batch. Theme packages still rebuild and copy their full `files` list.
4. Kibana's Rspack MultiCompiler detects the change and rebuilds shared dependencies before rebuilding Kibana.
5. When Rspack has rebuilt, the browser reloads.

### Architecture diagram

```mermaid
flowchart TD
    %% EUI
    subgraph EUI [EUI repository]
        Change([Source change]) --> |Watch| Script(watch-eui.js)
        Script --> |Build| Artifacts(Artifacts)
    end

    Artifacts --> |Sync| NodeModules[node_modules]

    %% Kibana
    subgraph Kibana [Kibana repository]
        NodeModules --> |Detect| Rspack(Rspack MultiCompiler)
    end

    Rspack --> |Build shared deps and Kibana| Browser((Update in the browser))
```

## Troubleshooting

- **Change not showing up?**

Check the terminal output of the EUI watcher. If the `node_modules` propagation succeeded, check the Kibana terminal for Rspack rebuild output. Ensure you started the workflow with `yarn watch:kibana`.

- **Slow feedback loop?**

For `@elastic/eui`, the watcher skips `lib/`, `es/`, types and the rest of the package build. After the initial `optimize/es` build, only changed files are compiled. Theme packages still run a full build. Most of the remaining feedback time is Kibana's Rspack rebuild.

---

### Contributing To Eui Developing Props (`wiki/contributing-to-eui/developing/props.md`)

# Component props

Props are the main APIs through which consumers/developers interact with our components. As such, it's important that our props remain as consistent as possible between all components, as something like changing the name of a prop or removing a prop would be considered a breaking change.

## Naming props

### Enums

String literals should be used wherever possible and prioritized over booleans. This allows for the most extensibility when it comes to adding more features/options in the future. For example, use `layout: 'horizontal' | 'vertical'` instead of `isHorizontal: boolean`.

#### Size enums

We use abbreviations to refer to sizes, e.g. `xxl`, `xl`, `l`, `m`, `s`, `xs`, and `xxs`.

#### Typing enums

Enums should typically be declared as an `as const` array.

```tsx
// We first define the enum values as an array
export const COLORS = ['primary', 'success', 'warning', 'danger'] as const;

// We can then refer to the enum array for prop types.
export type EuiComponentProps = {
  color: COLORS[number];
  isDisabled?: boolean;
  /* ... */
};

// We can continue to use the enum array for iteration
const isNamedColor = (color: string) => COLORS.includes(color);
```

### Booleans

Generally, boolean props should have an `is` prefix, e.g. `isPlaceholder` or `isReadOnly`. The exception to this is when the prop matches an existing HTML attribute such as `disabled`; to avoid confusion the prop name should align with the HTML specification. Mirroring the attributes this way makes the most sense when the component is a thin wrapper around an existing HTML element, e.g. EuiButton -> `<button>` and EuiRadio ->   `<input type="radio">`.

### Event handlers

All event handlers should take the form `onEvent` and accurately describe when it will be called. e.g. `onClick` indicates the handler is called when the component is clicked, but if there is more granularity the handler should reflect that with `onItemClick`, `onRowClick`, etc.

## Common and required props

Try to leverage the `children` prop wherever possible. This will create a simpler more uniform
API throughout our components.

We also [require some props](../../../packages/eui/src/test/required_props.ts) to be supported by all components, as
reflected in our tests; for example, `className`. These are easily added via the `CommonProps` mentioned above.

## Pass-through props

To give the consumer as much flexibility as possible we use the destructuring assignment to pull
expected props out of the received props and pass `...rest` to one of the elements in the
`render()` method. This element is typically the root element, though in rare cases another element
makes more sense.

The main benefit behind this practice is that the consumer can specify any of
the [DOM attributes](https://reactjs.org/docs/dom-elements.html) supported by React, including
custom ones with the `data-` prefix.

In Typescript, it makes sense to then extend the props of that element when declaring the component's type. EUI also provides a shortlist of commonly used props like `className`, `aria-label`, and `data-test-subj` that you should extend as well.

```jsx
import { HTMLAttributes, FunctionComponent } from 'react';
import { CommonProps } from '../common';

export type EuiMegaMenuProps = HTMLAttributes<HTMLDivElement> &
  CommonProps & {
    color: EuiMegaMenuColor;
    isDisabled?: boolean;
    /* ... */
  };

export const EuiMegaMenu: FunctionComponent<EuiMegaMenuProps> = ({
  children,
  className,
  color = 'primary',
  size,
  className,
  isDisabled = false,
  ...rest
}) => {

  // Anything else specified by the consumer will be applied to the div as a DOM attribute.
  return (
    <div {...rest}>
      {/* ... */}
    </div>
  );
}
```

The component's TypeScript definition needs to properly include the target DOM element's props. A `Foo` component that passes `...rest` through to a `button` element would have the `HTMLButtonElement` props interface.

```ts
// passes extra props to a button
interface FooProps extends ButtonHTMLAttributes<HTMLButtonElement> {
  title: string
}
```

## Props documentation from Typescript

We use [react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript/) combined with some custom [props filters](../../../scripts/babel/react-docgen-typescript.js) to automatically generate our Props tab/table from our Typescript component types.

> :warning: [react-docgen-typescript currently has a bug](https://github.com/styleguidist/react-docgen-typescript/issues/395) that does not correctly generate props for all components if a file has multiple components that set a `displayName`. To avoid this bug and broken props tables, keep your component files atomic / limited to 1 major component per file.

---

### Contributing To Eui Developing Refs (`wiki/contributing-to-eui/developing/refs.md`)

# Component refs

Components should always accept a `ref` prop which should typically pass back the primary underlying native DOM element to the `ref` callback.

However, more complex components (e.g., `EuiDataGrid` and `EuiMarkdownEditor`) may instead pass back [a ref of imperative APIs](#providing-custom-or-additional-data) as a way to control said component.

## forwardRef

React's [`forwardRef`](https://reactjs.org/docs/forwarding-refs.html) should be used to provide access to the component's outermost element. We impose two additional requirements when using `forwardRef`:

1. Use `forwardRef` instead of `React.forwardRef`, otherwise [react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript/) does not understand it and the component's props table will error in our documentation
2. The resulting component must have a `displayName`, which is useful when the component is included in a snapshot or when inspected in devtools. There is an eslint rule which checks for this.

### Simple forward/pass-through

```tsx
import React, { forwardRef } from 'react';

interface MyComponentProps {...}

export const MyComponent = forwardRef<
  HTMLDivElement, // type of element or component the ref will be passed to
  MyComponentProps // what properties apart from `ref` the component accepts
>(
  (
    { destructure, props, here, ...rest },
    ref
  ) => {
    return (
      <div ref={ref} {...rest}>
        ...
      </div>
    );
  }
);

MyComponent.displayName = 'MyComponent';
```

### Combining with additional refs

Sometimes an element needs to have 2+ refs passed to it, for example a component interacts with the same element the forwarded ref needs to be given to. For this EUI provides a `useCombinedRefs` hook:

```tsx
import React, { forwardRef, createRef } from 'react';
import { useCombinedRefs } from '../../services';

interface MyComponentProps {...}

export const MyComponent = forwardRef<
  HTMLDivElement, // type of element or component the ref will be passed to
  MyComponentProps // what properties apart from `ref` the component accepts
>(
  (
    { destructure, props, here, ...rest },
    ref
  ) => {
    const localRef = useRef<HTMLDivElement>(null);
    const combinedRefs = useCombinedRefs([ref, localRef]);
    return (
      <div ref={combinedRefs} {...rest}>
        ...
      </div>
    );
  }
);

MyComponent.displayName = 'MyComponent';
```

## Providing custom or additional data

Rarely, a component's ref needs to be something other than a DOM element, or provide additional information. In these cases, React's `useImperativeHandle` can be used to provide a custom object as the ref's value. For example, **EuiMarkdownEditor**'s ref includes both its textarea element and the `replaceNode` method to interact with the abstract syntax tree. https://github.com/elastic/eui/blob/v31.10.0/src/components/markdown_editor/markdown_editor.tsx#L331

```tsx
import React, { useImperativeHandle } from 'react';

export const EuiMarkdownEditor = forwardRef<
  EuiMarkdownEditorRef,
  EuiMarkdownEditorProps
  >(
  (props, ref) => {
    ...

    // combines the textarea element & `replaceNode` into a single object, which is then passed back to the forwarded `ref`
    useImperativeHandle(
      ref,
      () => ({ textarea: textareaRef.current, replaceNode }),
      [replaceNode]
    );

    ...
  }
);
```

---

### Contributing To Eui Developing Writing Styles With Emotion (`wiki/contributing-to-eui/developing/writing-styles-with-emotion.md`)

# Writing styles with Emotion

EUI uses [`Emotion`](https://emotion.sh/) when writing CSS-in-JS styles.
A general knowledge of writing CSS is enough in most cases, but there are some JavaScript-related differences that can result in unintended output. Similarly, there are feaures that don't exist in CSS of which we like to take advantage.

## File patterns

```ts
/* {component name}.styles.ts */
import { css } from '@emotion/react';
import { UseEuiTheme } from '../../services';

// Always start the object with the first key being the name of the component
export const euiComponentNameStyles = ({ euiTheme }: UseEuiTheme) => {
  return {
    euiComponentName: css`
      color: ${euiTheme.colors.textPrimary};
    `,
  };
};
```

---
<details>
  <summary>🎉 <b>ProTip:</b> VS Code snippet</summary>
  To make generating component boilerplate just a little bit easier, you can add the following block to a global or local snippet file in VS Code. Once saved, you'll be able to generate the boilerplate by typing `euisc` `tab`. <a href="https://code.visualstudio.com/docs/editor/userdefinedsnippets#_create-your-own-snippets" target="_blank">Learn how to add snippets in VS Code</a>:

  ```json
  "euiStyledComponent": {
    "prefix": "euisc",
    "body": [
      "/*",
      "* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one",
      "* or more contributor license agreements. Licensed under the Elastic License",
      "* 2.0 and the Server Side Public License, v 1; you may not use this file except",
      "* in compliance with, at your election, the Elastic License 2.0 or the Server",
      "* Side Public License, v 1.",
      "*/",
      "",
      "import { css } from '@emotion/react';",
      "import {",
      "  euiFontSize,",
      "  logicalCSS,",
      "} from '../../global_styling';",
      "import { UseEuiTheme } from '../../services';",
      "",
      "export const ${1:componentName}Styles = ({ euiTheme }: UseEuiTheme) => {",
      "  return {",
      "    ${1:componentName}: css`",
      "      ${2:property}: tomato;",
      "    `",
      "  };",
      "};"
    ],
    "description": "EUI styled component"
  }
  ```
</details>

---

```tsx
/* {component name}.tsx */
import { useEuiTheme } from '../../services';
import { euiComponentNameStyles } from './{component name}.styles.ts';

export const EuiComponent = () => {
  const theme = useEuiTheme();
  const styles = euiComponentNameStyles(theme);
  const cssStyles = [styles.euiComponentName]

  return (
    <div css={cssStyles} />
  );
};
```

## CSS-aligned props

If a prop/value pair maps 1:1 to the CSS property: value, pass the value straight through. We encounter this scenario when it is apparent that a given css property is core to configuring a component, and it doesn't make sense to use an abstraction.

```tsx
position?: CSSProperties['position'];

const cssStyles = [
  { position }
];
```

## Component props that enable styles

### Building an array of styles

Use an array inside of the `css` prop for optimal style composition and class name generation. This is relevant even if only a single style object is passed.

_examples from [avatar.tsx](https://github.com/elastic/eui/blob/main/packages/eui/src/components/avatar/avatar.tsx)_

```tsx
export const EuiAvatar: FunctionComponent<EuiAvatarProps> = ({...}) => {
  // access the theme and compute avatar's styles
  const euiTheme = useEuiTheme();
  const styles = euiAvatarStyles(euiTheme);

  ...

  // build the styles array
  const cssStyles = [
    styles.euiAvatar, // base styles
    styles[size], // styles associated with the `size` prop's value
    styles[type], // styles associated with the `type` prop's value

    // optional styles
    isPlain && styles.plain,
    isSubdued && styles.subdued,
    isDisabled && styles.isDisabled,
  ];

  ...

  // pass the styles array to the `css` prop of the target element
  return (
    <div css={cssStyles} />
  )
}
```

### If a prop's value renders no styles

A. If it's necessary to still know the prop value while debugging, create an empty css`` map for that value

```tsx
paddingSize = 'none';

const euiComponentStyles = ({
  none: css``
})
```

B. If it's mostly just an empty default state, check for that prop before grabbing the css value

```tsx
paddingSize = 'none';

const cssStyles = [
  paddingSize === 'none' ? undefined : styles[paddingSize]
]
```

## Style maps

When building styles based on an array of possible prop values, you'll want to establish the array of values first in the component file then use that array to create your prop values and your styles map.

```tsx
export const SIZES = ['s', 'm', 'l', 'xl', 'xxl'] as const;
export type EuiComponentNameSize = typeof SIZES[number];

export type EuiComponentNameProps = CommonProps & {
  size?: EuiComponentNameSize;
};

export const EuiComponentName: FunctionComponent<EuiComponentNameProps> = ({...}) => {
  const euiTheme = useEuiTheme();

  const styles = euiComponentNameStyles(euiTheme);
  const cssStyles = [styles.euiComponentName, styles[size]];

  return (
    <div css={cssStyles} />
  )
}
```

```ts
const componentSizes: {
  [size in EuiComponentNameSize]: _EuiThemeSize;
} = {
  s: 'm',
  m: 'base',
  l: 'l',
  xl: 'xl',
  xxl: 'xxl',
};

export const euiComponentNameStyles = ({ euiTheme }: UseEuiTheme) => ({
  euiComponentName: css``,

  // Sizes
  s: css`
    width: ${euiTheme.size[componentSizes.s]};
    height: ${euiTheme.size[componentSizes.s]};
  `,
  m: css`
    width: ${euiTheme.size[componentSizes.m]};
    height: ${euiTheme.size[componentSizes.m]};
  `,
  ...etc
});
```

## Style helpers

EUI components often have style variants that use a similar patterns. In these cases, consider creating a helper function to create repetitive styles.

```ts
const _componentSize = ({
  size,
  fontSize,
}: {
  size: string;
  fontSize: string;
}) => {
  return `
    width: ${size};
    height: ${size};
    line-height: ${size};
    font-size: ${fontSize};
  `;
};
```

The helper function can then be used in the exported style block:

```ts
export const euiComponentNameStyles = ({ euiTheme }: UseEuiTheme) => ({
  // Sizes
  s: css(
    _componentSize({
      size: euiTheme.size.l,
      fontSize: euiTheme.size.m,
    })
  ),
  m: css(
    _componentSize({
      size: euiTheme.size.xl,
      fontSize: `calc(${euiTheme.size.base} * 0.9)`,
    })
  ),
  l: css(
    _componentSize({
      size: euiTheme.size.xxl,
      fontSize: `calc(${euiTheme.size.l} * 0.8)`,
    })
  ),
});
```

Note that the helper function returns a string literal instead of a `css` method from `@emotion/react`. This reduces the serialization work at runtime and makes the helper more flexible (e.g., could be used with a `style` attribute). Also note that the `css` method from `@emotion/react` can be [called as a normal function](https://emotion.sh/docs/@emotion/css#css) instead of as a template literal.

## Conditional styles

Styles can be added conditionally based on environment variables, such as the active theme, using nested string template literals.

```ts
`
    color: colors.primary;
    background: ${colorMode === 'light' ? 'white' : 'black'`}
`
```

Although possible in some contexts, it is not recommended to "shortcut" logic using the `&&` operator. Use ternary statements to avoid `undefined` statments from entering the compiled code.

```ts
`${font.body.letterSpacing ? `letter-spacing: ${font.body.letterSpacing}` : ''`}`
```

## Duplicate styles

When writing styles for prop enums (e.g. sizing enums: `s`, `m`, `l`, etc.), some props may have duplicated styles between two values. If the duplicated styles are just a line or two, repeating the CSS is not particularly problematic.

However, if the repeated CSS starts to get lengthy or unintuitive, consider using a [JS getter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) to return duplicate styles, for example:

```ts
export const euiComponentNameStyles = ({ euiTheme }: UseEuiTheme) => ({
  // Sizes
  s: css`
    /* lengthy or complex styles */
  `,
  get m() {
    // Same as `s`
    return this.s;
  },
  l: css`
    /* different styles */
  `,
});
```

For a production example of this scenario, see [EuiStep's styles](https://github.com/elastic/eui/blob/ea535de773703ec225804228aa3aa68d18d84dc5/src/components/steps/step.styles.ts#L86-L105).

## Child selectors

Most components also contain child elements that have their own styles. If you have just a few child elements, consider having them in the same function.

```ts
export const euiComponentNameStyles = ({ euiTheme }: UseEuiTheme) => ({
  euiComponentName: css``,
  euiComponentName__child: css``
});
```

```tsx
export const EuiComponentName: FunctionComponent<EuiComponentNameProps> = ({...}) => {
  const euiTheme = useEuiTheme();

  const styles = euiComponentNameStyles(euiTheme);
  const cssStyles = [styles.euiComponentName];
  const cssChildStyles = [styles.euiComponentName__child];

  return (
    <div css={cssStyles}>
      <span css={cssChildStyles} />
    </div>
  )
}
```

If you have multiple child elements, consider grouping them in different theme functions to keep things tidy. Keep them within a single `styles.ts` file if they exist in the same `.tsx` file.

```ts
export const euiComponentNameStyles = ({ euiTheme }: UseEuiTheme) => ({
  euiComponentName: css``
});

export const euiComponentNameHeaderStyles = ({ euiTheme }: UseEuiTheme) => ({
  euiComponentName__header: css``,
  euiComponentName__headerIcon: css``,
  euiComponentName__headerButton: css``
});

export const euiComponentNameFooterStyles = ({ euiTheme }: UseEuiTheme) => ({
  euiComponentName__footer: css``
});
```

```tsx
export const EuiComponentName: FunctionComponent<EuiComponentNameProps> = ({...}) => {
  const euiTheme = useEuiTheme();

  const styles = euiComponentNameStyles(euiTheme);
  const cssStyles = [styles.euiComponentName];

  const headerStyles = euiComponentNameHeaderStyles(euiTheme);
  const cssHeaderStyles = [headerStyles.euiComponentName__header];
  const cssHeaderIconStyles = [headerStyles.euiComponentName__headerIcon];
  const cssHeaderButtonStyles = [headerStyles.euiComponentName__headerButton];

  const footerStyles = euiComponentNameFooterStyles(euiTheme);
  const cssFooterStyles = [footerStyles.euiComponentName__footer];

  return (
    <div css={cssStyles}>
      <div css={cssHeaderStyles}>
        <span css={cssHeaderIconStyles} />
        <button css={cssHeaderButtonStyles}>My button</button>
      </div>
      <div css={cssFooterStyles} />
    </div>
  )
}
```

### Merging child element css with spread operators

Please keep in mind that while Emotion will automatically merge `css` props for **top** level components, it will **not** do so for any child elements. Take for example the following component:

```tsx
// This example is incorrect!
export const EuiComponentName: FunctionComponent<EuiComponentNameProps> = ({ iconProps, ...rest }) => {
  const euiTheme = useEuiTheme();

  const styles = euiComponentNameStyles(euiTheme);
  const cssStyles = [styles.euiComponentName];
  const cssIconStyles = [styles.euiComponentName__icon];

  return (
    // This will merge Emotion CSS as expected
    <div css={cssStyles} {...rest}>
      <EuiIcon
        // This will not!
        css={cssIconStyles}
        {...iconProps}
      />
    </div>
  )
}
```

If a consumer passes `<EuiComponentName css={{ color: 'red' }}>`, Emotion will automatically correctly combine EUI's component styles and the passed custom styles.

**However**, if a consumer passes `<EuiComponentName iconProps={{ css: { color: red } }}>`, Emotion will **not** handle merging in the child `css` props and will simply override/ignore whichever `css` prop came first in the prop order.

To ensure consumers do not either accidentally wipe our EUI's default styling, or are unable to pass in child `css` props, always check that you're manually merging in any `childProps.css` like so:

```tsx
// This example will correctly merge child CSS
export const EuiComponentName: FunctionComponent<EuiComponentNameProps> = ({ iconProps, ...rest }) => {
  const euiTheme = useEuiTheme();

  const styles = euiComponentNameStyles(euiTheme);
  const cssStyles = [styles.euiComponentName];

   // Include `childProps?.css` in the css array
  const cssIconStyles = [styles.euiComponentName__icon, iconProps?.css];

  return (
    <div css={cssStyles} {...rest}>
      <EuiIcon
        // Ensure that your merged `css` array comes after the props spread
        {...iconProps}
        css={cssIconStyles}
      />
    </div>
  )
}
```

You can confirm that this behavior correctly merges Emotion CSS by using the `shouldRenderCustomStyles` test utility. Example usage:

```tsx
import { shouldRenderCustomStyles } from '../../test/internal';
import { requiredProps } from '../../test/';

describe('EuiComponentName', () => {
  shouldRenderCustomStyles(<EuiComponentName />, {
    childProps: ['iconProps']
  });

  it('renders', () => {
    // ...
  })

  it('renders `iconProps`', () => {
    render(<EuiComponentName iconProps={requiredProps} />)
  });
});
```

## Nested selectors

For the most part, nested selectors should not be necessary. If a child element requires styling based on the parent's variant, pass the same variant type to the child element.

```ts
export const euiComponentNameStyles = ({ euiTheme }: UseEuiTheme) => ({
  euiComponentName: css``,
  // Sizes
  s: css``,
  m: css``,
});

export const euiComponentNameChildStyles = ({ euiTheme }: UseEuiTheme) => ({
  euiComponentName__child: css``,
  // Sizes
  s: css``,
  m: css``,
});
```

```tsx
export const EuiComponentName: FunctionComponent<EuiComponentNameProps> = ({...}) => {
  const euiTheme = useEuiTheme();

  const styles = euiComponentNameStyles(euiTheme);
  const cssStyles = [styles.euiComponentName, styles[size]];

  const childStyles = euiComponentNameChildStyles(euiTheme);
  const cssChildStyles = [childStyles.euiComponentName__child, childStyles[size]];

  return (
    <div css={cssStyles}>
      <span css={cssChildStyles} />
    </div>
  )
}
```

If for other reasons, it is absolutely necessary to target a child from within another selector, you should use the [class attribute selector](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) to match a part of the class string you expect to find.

```ts
export const euiComponentNameStyles = ({ euiTheme }: UseEuiTheme) => ({
  euiComponentName: css`
    [class*="euiComponentName__child"] {}
  `,
});
```

## Creating `colorMode` specific components

When creating components that rely on a specific `colorMode` from `<EuiThemeProvider>`, use this pattern to create a wrapper that will pass the entire component `<EuiThemeProvider>` details.

- `_EuiComponentName` is an internal component that contains the desired functionality and styles.
- `EuiComponentName` is the exportable component that wraps `_EuiComponentName` inside of `<EuiThemeProvider>`.

```tsx
const _EuiComponentName = ({ componentProps }) => {
  return <div />;
}

export const EuiComponentName = ({ componentProps }) => {
    const Component = _EuiComponentName;
    return (
      <EuiThemeProvider colorMode={ colorMode }>
        <Component {...componentProps} />
      </EuiThemeProvider>
    );
  }
);
```

**[Refer to EuiBottomBar to see an example of this pattern in practice and as an example of using `forwardRef`.](../../../packages/eui/src/components/bottom_bar/bottom_bar.tsx)**

## Emotion mixins & utilities

When creating mixins & utilities for reuse within Emotion CSS, consider the following best practices:

- Publicly-exported mixins & utilities should go in [`src/global_styling/mixins`](https://github.com/elastic/eui/tree/main/src/global_styling/mixins). Utilities that are internal to EUI only should live in [`src/global_styling/functions`](https://github.com/elastic/eui/tree/main/src/global_styling/functions).
- If the mixin is simple and does not reference `euiTheme`, you do not need to create a hook version of it.
- In general, prefer returning CSS strings in your mixin.
  - However, you should consider creating a 2nd util that returns a style object instead of a CSS string if the following scenarios apply to your mixin usage:
    - If you anticipate your mixin being used in the `style` prop instead of `css` (since React will want an object and camelCased CSS properties)
    - If you want your mixin to be partially composable, so if you think developers will want to obtain a single line/property from your mixin instead of the entire thing (e.g. `euiFontSize.lineHeight`)

## JS vs. CSS component variables

In general, most component-specific style variables can remain JS-only (e.g., [euiStepVariables](https://github.com/elastic/eui/blob/068f0000532e6433383093d3488d7b1c4979c022/src/components/steps/step.styles.ts#L13-L19), [euiFormVariables](https://github.com/elastic/eui/blob/d39c0e988409f90f62af57174590044664b2bfce/src/components/form/form.styles.ts#L19)). These JS variable examples are generally used internally by EUI, and are not public top-level exports.

There are some scenarios, however, where certain component style variables are important enough to be made globally available via a [CSS variable](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties).

An example of this is **EuiHeader**: Fixed header height(s) and the page offset they cause need to be accounted for by multiple other EUI components (e.g. **EuiFlyout**, **EuiPageTemplate**), and potentially by custom consumer layouts. Using a global CSS variable allows **EuiHeader** to dynamically track the number of fixed headers and calculate total height in a single place. Other components can reuse that CSS variable without extra JS logic needed ([#7144](https://github.com/elastic/eui/pull/7144)).

EUI components can set CSS variables in two places: globally, or at the nearest **EuiThemeProvider** wrapper level:

```tsx
import React, { useEffect } from 'react';
import { useEuiTheme, useEuiThemeCSSVariables } from '../../services';

const EuiComponent = ({ ...props }) => {
  const { euiTheme } = useEuiTheme();
  const {
    setGlobalCSSVariables,
    setNearestThemeCSSvariables,
  } = useEuiThemeCSSVariables();

  useEffect(() => {
    // Sets the CSS variable at `:root`
    setGlobalCSSVariables({ '--euiSomeGlobalVariable': euiTheme.color.success });

    // Sets the CSS variable on the nearest parent theme provider wrapper
    // If the nearest provider is EuiProvider, the variable is set globally on `:root` in any case
    setNearestThemeCSSVariables({ '--euiSomeThemeVariable': euiTheme.size.m });
  }, []);

  return <></>;
}
```

While a global CSS variable makes sense for **EuiHeader**, for most components, nearest theme variables would likely make more sense. For example, **EuiForm** should respect any custom theme modifications and pass its modified form variables to any children, but not siblings or parent forms that do not have modifications.

```tsx
// Normal form
<EuiForm>
  {/* ... Form controls that inherit global form variables */}
</EuiForm>

// Form with a custom size scale
<EuiThemeProvider modify={{ base: 10 }}>
  <EuiForm>
    {/* ... Form controls that inherit from the nearest theme variables */}
  </EuiForm>
</EuiThemeProvider>
```

[See our EuiThemeProvider stories](http://localhost:6006/?path=/story/euithemeprovider--css-variables-nearest) to view an example of this behavior in the browser.

### Naming

When naming your mixins & utilities, consider the following statements:

- Always prefix publicly-exported functions with `eui` unless it's purely a generic helper utility with no specific EUI consideration
- When creating both a returned string version and object version, append the function name with `CSS` for strings and `Style` for objects. Example: `euiMixinCSS()` vs `euiMixinStyle()`.

### API pattern

For consistency, use the following pattern for style mixins that accept required and/or optional arguments:

```ts
const euiMixin = (
  euiTheme: UseEuiTheme;
  required: RequiredProperty;
  optional?: {
    optionalKey1?: OptionalProperty;
    optionalKey2?: OptionalProperty;
  }
) => {}
```

If the mixin does not accept required or optional properties, the argument can be removed.

## Writing unit tests for output styles

If using complex utilities or calculations that leaves you unsure as to the output of your styles, it may be worth writing Jest snapshot tests to capture the final output. See [EuiText's style](https://github.com/elastic/eui/blob/main/packages/eui/src/components/text/text.styles.test.ts) [snapshots](https://github.com/elastic/eui/blob/main/packages/eui/src/components/text/__snapshots__/text.styles.test.ts.snap) or [EuiTitle](https://github.com/elastic/eui/blob/main/packages/eui/src/components/title/title.styles.test.ts) for an example of this.

If writing straightforward or static CSS, unit tests should be unnecessary.

## FAQ

### Can the `css` prop be forwarded to a nested element?

Emotion converts the `css` prop to a computed `className` value, merging it into any existing `className` prop on an element. We do not parse or handle these in any special way, so whichever element the `className` prop is applied to receives the styles created by Emotion. See https://codesandbox.io/s/emotion-css-and-classname-ohmqe7 for a playground demonstration.

Sometimes apps want or need to provide styles (or other props) to multiple elements in a component, and in these cases we add a prop to the component that captures the extra information, spreading it onto the element. We can continue with this approach, allowing the `css` prop to be added for flexible styling.

### Which element in a custom component gets the `css` styling?

Same as the above answer, whichever element is given the generated `className` is the styles' target.

### How should `createElement` usages be converted?

Emotion provides its own `createElement` function; existing uses of `import {createElement} from 'react'` can be converted to `import {createElement} from '@emotion/react'`

### Why is stylelint / `yarn lint-css-in-js` giving me an `Unknown word (CssSyntaxError)` error?

Unfortunately, a limitation of the CSS-in-JS syntax parser we're using is that `//` comments throw this error (see https://github.com/hudochenkov/postcss-styled-syntax#known-issues).

You must convert all `//` comments to standard CSS `/* */` comments instead.

### Should I use Emotion's `css={theme => {}}` API?

No. The [Emotion theme context](https://emotion.sh/docs/theming) that we include by default in `EuiThemeProvider` is intended for **consumer usage** and convenience, particularly with the goal of making adoption by Kibana devs easier.

It is not intended for internal EUI usage, primarily because it can be too easily overridden by consumers who want to use their own custom Emotion theme vars and set their own `<ThemeProvider>`. If this happens, and we're relying on Emotion's theme context, all of EUI's styles will break.

When you're styling EUI components internally, you should use only EUI's theme context/`useEuiTheme()`, and not on Emotion's theme context (i.e., do not use the `css={theme => {}}` API).

---

### Contributing To Eui Documenting Changelogs (`wiki/contributing-to-eui/documenting/changelogs.md`)

# Changelogs

All upcoming changelogs should go into the `changelogs/upcoming/` directories.

Our release script automatically handles collating these files on new EUI versions and appends a PR link.

## When to write a changelog

- Any updates to the `packages/eui/src/` folder should include a changelog
- `dependency` upgrades in `package.json` should contain a changelog

## When to skip a changelog

Changes that do not impact consumers or end-users may use the `skip-changelog` label on PRs to bypass CI checks. Examples of these types of changes:

- Documentation-only changes (e.g. changes to `wiki/` or `packages/website/`)
- Infra/dev-only changes (e.g. changes to `.github/`, `.buildkite/` or `scripts/`)
- Test-only changes (e.g. changes to `*.test.tsx`, `*.spec.tsx`, or `*.stories.tsx` files)
- `dev-dependency` upgrades in `package.json`

## How to write a changelog

* Create a new file with the ID/number of the pull request.
  * In `packages/eui`, you can use `yarn yo-changelog #####` (passing the PR ID/number) to automatically generate a changelog boilerplate file.
  * Reference [`packages/eui/changelogs/upcoming/_template.md`](/packages/eui/changelogs/upcoming/_template.md) for the canonical section ordering and formatting.
* Create `**` wrapped subheadings for bug fixes, deprecations, or breaking changes. New features/enhancements should go at the top, and do not need a subheading.
* Add a `-` list item for each significant change in the PR. Larger PRs may have multiple changes, whereas smaller PRs may have only one.
* Write your entry in the **past tense**, starting with a verb (e.g. Added... , Fixed...).
* Add a summary of what has changed, making sure it's informative to consumers who might be unaware of implementation details.
* Avoid documenting internal implementation changes that don't affect the public interface.
* Make sure the entry is as concise as can be.

---

### Contributing To Eui Documenting Writing Documentation (`wiki/contributing-to-eui/documenting/writing-documentation.md`)

# Writing documentation

- [Files and folders](#files-and-folders)
- [Partials](#partials)
- [Collapsible sidebar items](#collapsible-sidebar-items)
- [Front matter](#front-matter)
- [Documenting components](#documenting-components)
- [Custom components available](#custom-components-available)
- [Writing content](#writing-content)
  - [Headings](#headings)
  - [Links](#links)
  - [Admonitions](#admonitions)
  - [Code blocks](#code-blocks)
  - [Live demos](#live-demos)
  - [Full-screen example](#full-screen-example)
  - [Tables](#tables)
  - [Dos and Don'ts](#dos-and-donts)
  - [Figma asset](#figma-asset)
  - [Props table](#props-table)
  - [Images](#images)

Code for the Elastic UI [documentation site](https://eui.elastic.co) can be found in the `packages/website` directory. The site is built with [Docusaurus](https://docusaurus.io/).

## Files and folders

Documentation is written in Markdown.

Files are stored in the `docs` folder and document files use [MDX](https://mdxjs.com/docs/what-is-mdx/), thus the `.mdx` file extension. This format allows writing React code alongside Markdown. It's also possible to import React code from `.tsx` files, which is useful for more complex examples.

Check out the [MDX syntax documentation here](https://mdxjs.com/docs/what-is-mdx/#mdx-syntax).

> [!TIP]
> For formatting content always prefer using Markdown over React

The folder structure matches the navigation and content structure, similar to common static site builders like Jekyll. For instance, for editing the Components / Containers / Accordion page, the content will be found in the `docs/components/containers/accordion.mdx` file.

Files and folder names must use [kebab-case](https://developer.mozilla.org/en-US/docs/Glossary/Kebab_case), unlike the EUI convention to use snake_case. This makes it easier to keep URLs consistent without having to override Docusaurus defaults in the front matter.

### Custom components available

There are a few React components that can be used in `.mdx` files without being imported. They are part of the [MDX scope](https://docusaurus.io/docs/next/markdown-features/react/#mdx-component-scope). Some of them, documented below, are:

- [`Demo`](#demo-props)
- [`FigmaAsset`](#figma-asset)
- [`Guideline`](#guideline-props)
- [`PropTable`](#props-table)

## Front matter

The front matter is a section at the top of a Markdown file that contains metadata about the document. It's enclosed in triple dashes (`---`) and written in [YAML format](https://yaml.org/).

A few important aspects of the document can be configured here:

- `id` (unique to the document)
- `slug` (to customize the URL)
- `sidebar_label`
- `sidebar_position`
- `title` (if different from the h1)
- `description`

Check the Docusaurus docs for a [full list of fields](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-docs#markdown-front-matter).

## Collapsible sidebar items

To create a collapsible item in the sidebar, just add a folder in the file system containing one or more `.mdx` files. In Docusaurus these are called category items, and they can be configured by adding a `_category_.yml` file to the folder. By default the category label will be the folder name, this can be changed with the `label` field in the `_category_.yml` file. Other useful fields are `position` and `collapsed`.

It's possible to make a collapsible item be a document as well, though this is not recommended. Set the `link` field to have `type: doc` and `id: <DOCUMENT_ID>`, with the `id` from the document it should point to. If the `id` is not explicitly set in the document file's [front matter](#front-matter), it's the relative path starting from the `docs` folder, without the file extension, e.g. `docs/components/containers/accordion`.

Read more about [category metadata](https://docusaurus.io/docs/sidebar/autogenerated#category-item-metadata) and [file structure](https://docusaurus.io/docs/create-doc#organizing-folder-structure) in the Docusaurus docs.

> [!WARNING]
> Nesting items in the sidebar should be avoided when possible, deeply nested items can make the menu harder to use

## Documenting components

All component pages should follow the following architecture:

- Intro
- Component: a bare-bones example of the component in its default form
- Usage (_optional_): examples of different states and use-cases
- Guidelines (_optional_): e.g. dos and don'ts
- Props

## Partials

A document can be split into different files when content is too long, for easier editing.

Markdown files prefixed with an underscore will be ignored when generating the sidebar navigation. These hidden files can be imported and rendered in the main document.

For example, the document for the Modal page is `containers/modal/index.mdx`:

    containers/
      modal/
        _guidelines.mdx
        _usage.mdx
        index.mdx

Usage and Guidelines sections have their own file that can be imported:

    import Usage from './_usage.mdx';
    
    ## Usage
    
    <Usage />
    
    ## Guidelines
    
    import Guidelines from './_guidelines.mdx';
    
    <Guidelines />

Read more about [importing Markdown files](https://docusaurus.io/docs/markdown-features/react#importing-markdown) in the Docusaurus docs.

## Writing content

As previously mentioned, using Markdown is highly encouraged. It makes it easier for anybody to contribute to the documentation.

During the build step of the website, elements with a counterpart in EUI will be accordingly replaced, e.g. a link with `EuiLink`, a inline code block with `EuiCode`, etc.

### Headings

Headings in Markdown are created with a hash symbol in a new line. The number of hashes will determine the heading level, `#` for 1, `##` for 2, etc.

> [!IMPORTANT]
> Do not use heading levels for styling, use them to properly structure the document hierarchically

### Links

Markdown is the recommended syntax for creating links. Docusaurus will take care of rendering it correctly.

```md
[This is a link](https://example.com)
```

To link between documents, use **relative file paths, including the file extension**, e.g. `[EuiPanel](../containers/panel/index.mdx)`

Read more about [Markdown links](https://docusaurus.io/docs/markdown-features/links) in the Docusaurus docs.

### Admonitions

The syntax for creating admonitions is wrapping a paragraph in three colons, e.g. `:::`. The type of admonition and title can be defined after the first three colons. This will render `EuiCallOut`.

```mdx
:::info This is the title

Here's some content

:::
```

There are 6 types of admonitions supported, with icon and color respectively.

- `note`
- `tip`
- `info`
- `accessibility`
- `warning`
- `danger`

### Code blocks

A code block or code snippet can be created by wrapping text in backticks, e.g. \`code\`.

For a simple one-liner, single backticks are enough. To create a multiline snippet or code block, use three backticks. For syntax highlighting, the language name can be added right after the first three backticks.

    ```html  
    <span>Hello World</span>  
    ```

Code blocks can be used to generate live demos, where a React component that is exported in the snippet will be rendered on the page. To do that, append the word "interactive" after the language name, usually `tsx`.

    ```tsx interactive  
    export default () => (
      <div>Hello World</div>
    )
    ```

More advanced usage with the [`Demo` component](#live-demos) can be found right below.

### Live demos

When plain code blocks are not enough, the `Demo` component can be used. It's available without being imported so it can be used straightaway.

> [!NOTE]
> They're called "live" demos because the source code can be edited right there on the page and the preview will update

The benefits of the `Demo` component over plain code blocks are mainly:
- that the scope of the demo can be extended with imports from the document, and
- it's possible to add a wrapper component for the preview and adjust the padding.

#### `Demo` props

- `children` - A `tsx` code block
- `scope` - An object to extend the scope of the demo with additional properties
- `isSourceOpen` - Whether the source code editor is open by default (`false`)
- `previewPadding` - Adjust the padding of the preview
- `previewWrapper` - A wrapper component for the preview

Check the [source code here](https://github.com/elastic/eui/tree/main/packages/docusaurus-theme/src/components/demo).

#### Usage example

> [!TIP]
> Remember to wrap imports in ```mdx-code-block`

    ```mdx-code-block
    import previewWrapper from './preview_wrapper.tsx';
    ```

    <Demo previewWrapper={previewWrapper}>
    ```tsx
    import React, { useState } from 'react';
    import { EuiButton } from '@elastic/eui';

    export default () => {
      const [counter, setCounter] = useState<number>(0);
      const updateCounter = () => setCounter(x => x + 1);

      return (
        <EuiButton onClick={updateCounter}>
          Clicked {counter} times
        </EuiButton>
      )
    }
    ```
    </Demo>

#### CodeSandbox

The `<Demo />` component includes built-in **CodeSandbox integration**. It displays a button that, when clicked, opens a new CodeSandbox instance containing your snippet.

To ensure CodeSandbox functions properly, verify that all references are resolvable:

- all necessary React and EUI components are imported directly,
- all relative imports in the snippet are direct siblings (e.g. `import { Component } from './component';`),
- all local files used (such as components or SVGs) are passed to the  `extraFiles` prop as stringified content:

````mdx
```mdx-code-block
import icon from './icon.svg';
import iconSource from '!raw-loader!./icon.svg';
```

<Demo scope={{ icon }} extraFiles={{ 'icon.svg': iconSource }}>
  ```tsx
  import { EuiImage } from '@elastic/eui';
  
  import icon from './icon.svg';

  export default () => {
    return (
      <EuiImage url={icon} />
    )
  }
  ```
</Demo>
````

`scope` and `extraFiles` serve different purposes. `scope` is used to inject variables into the snippet execution context while `extraFiles` is used to pass additional files to the CodeSandbox instance.

### Full-screen example

The convention for creating full-screen examples, where the entire browser screen is needed to demo a certain component combination or pattern, is to create a Storybook story and link to it from the docs.

There's a `StorybookLink` component that makes this easy and consistent, by handling the URL appropriately depending on the environment.

It's expected for the link to be preceded by a heading and a short description.

The story's `id` can be found in the URL. It's the part after `/index.html?path=/story/`.

    ## A heading for the example

    Here it's explained what the examples represents.

    ```mdx-code-block
    import { StorybookLink } from '@site/src/components';
    ```

    <StorybookLink id="<STORY_ID>" />

### Tables

There are two supported ways to create tables in MDX - using Markdown tables syntax or using the EUI table components
like [`EuiTable`](https://eui.elastic.co/docs/components/tables/custom)
or [`EuiBasicTable`](https://eui.elastic.co/docs/components/tables/basic):

* **Markdown tables** syntax should only be used for simple, text-only tables. The Markdown representation of a table must
    be easily readable.
* **[EuiTable](https://eui.elastic.co/docs/components/tables/custom)** components should be used for longer
    and more complex tables
* **[EuiBasicTable](https://eui.elastic.co/docs/components/tables/basic)** should be used for multi-column tables,
    when the data comes from JS objects or isn't easily readable when directly defined using MDX syntax.

Just like with [partials](#partials), the code for the table can be separated in its own file and imported into the MDX document where it'll be displayed. For example:

    components/
      my-component/
        nice_table.tsx
        index.mdx

`nice_table.tsx` can export a component that renders [EuiBasicTable](https://eui.elastic.co/docs/components/tables/basic-tables):

```tsx
import { css } from '@emotion/react';

import {
  EuiBasicTable,
  EuiBasicTableColumn,
  // ...
} from '@elastic/eui';

export const NiceTable = () => {
  const items = [
    // ...
  ];
  const columns = [
    // ...
  ];

  return <EuiBasicTable items={items} columns={columns} tableLayout="auto" />;
}
```

And then in `index.mdx` the table can be rendered:

    ## A heading for the table

    ```mdx-code-block
    import { NiceTable } from './nice_table';
    ```

    <NiceTable />

### Dos and Don'ts

For dos and don'ts sections there's a `Guideline` component with the appropriate styles built-in. To display one next to the other, a [EuiFlexGroup](https://eui.elastic.co/docs/components/layout/flex/flex-group) can be used:

```tsx
<EuiFlexGroup gutterSize="m">
  <Guideline type="do" text="Lorem ipsum dolor sit amet consectetur adipiscing elit.">
    <div>Yep content</div>
  </Guideline>
  <Guideline type="dont" text="Quisque faucibus ex sapien vitae pellentesque sem placerat.">
    <div>Nope content</div>
  </Guideline>
</EuiFlexGroup>
```

#### `Guideline` props

- `children` - The content inside, can be other components
- `type` - `do`, `dont` or `default` 
- `text` - The actual guideline text
- `panelPadding` (optional) - To adjust the padding of the panel
- `panelStyle` (optional) - To further customize the panel styles

### Figma asset

Use `FigmaAsset` to show a Figma design in docs. By default it renders a static image (SVG preferred). Pass `type="embed"` to show an interactive Figma iframe instead.

Props are a discriminated union on `type`: image mode requires `src` (and forbids embedding-only combinations); embed mode forbids `src`. `title` is always required for accessibility.

**Image (default)** — import a colocated asset as a URL (use `!url-loader!` for SVGs; bare `.svg` imports become React components via SVGR). WebP/PNG imports work the same way if you need them later:

```mdx
import confirmationModal from '!url-loader!./assets/modal_confirming-an-action.svg';

<FigmaAsset
  url="https://www.figma.com/file/Uo8i…DX-0"
  src={confirmationModal}
  title="Title of the asset"
/>
```

**Embed** — interactive iframe from the Figma `url`:
> **Important note:** Use it only when necessary — only when users need to zoom into UI details. It impacts rendering performance and stability in the sections where applied.

```mdx
<FigmaAsset
  type="embed"
  url="https://www.figma.com/file/Uo8i…DX-0"
  title="Title of the embed"
/>
```

| Prop | Description |
| ---- | ----------- |
| `url` | Figma file/node URL (used for embed; kept as source reference for images) |
| `src` | Image URL string — SVG preferred; WebP/PNG supported (**required** for `type="image"`; not allowed for `type="embed"`) |
| `type` | `"image"` (default) or `"embed"` |
| `title` | **Required** accessible text (image `alt` / iframe `title`) |

### Props table

The Props table should always go last in a document. There is a `PropTable` component available without being imported that will take the props information from the `@elastic/eui-docgen` package in the `definition` prop.

If more than one table is needed because the component has many exports, place one table after the other. It should look like this:

    ## Props

    ```mdx-code-block
    import docgen from '@elastic/eui-docgen/dist/components/page';
    ```

    <PropTable definition={docgen.EuiPage} />

    <PropTable definition={docgen.EuiPageBody} />

    <PropTable definition={docgen.EuiPageSidebar} />

To customize the table `PropTable` also takes a `headingLevel` prop (h1–h6) and a `showTitle` boolean.

### Images

Typically, just use markdown:
```mdx

```

If you need to add CSS to do something like constraining the width, use an `img` tag:
```mdx
import error404 from './images/error-page-404.webp';

<img
  src={error404}
  alt="An empty prompt component which reads, 404, we can't find the page you're looking for. If you typed the URL, check it's correct. If you clicked a link, contact your administrator: admin@example.co."
  style={{ maxWidth: '480px' }}
/>
```

---

### Contributing To Eui Testing Automated Accessibility Testing (`wiki/contributing-to-eui/testing/automated-accessibility-testing.md`)

# Accessibility testing

The goal is for all EUI components to be run through [axe](https://www.deque.com/axe/).
Please refer to [issue #6300](https://github.com/elastic/eui/issues/6300) to see components under test.

## What is axe?

axe is an "[accessibility engine for automated Web UI testing](https://github.com/dequelabs/axe-core)".
Automated tests cover ~30% of accessibility requirements but ~60% of accessibility bugs are caught by automated tests.
Automated testing can't replace manual testing, but it's an important baseline for all of our components.

## How to run the Cypress accessibility tests?

* `test-cypress-a11y` runs the accessibility test suite in a local headless Cypress environment.
* `test-cypress-dev` runs the test suite using your dev server (assumed to be `http://localhost:8030`) and the Cypress test runner.

### How to run accessibility tests against 1 component?

Though it's not setup to be run this way, there are two ways to do it.

The recommended route is to install the axe addon (for [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd), [Firefox](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), or [Edge](https://support.microsoft.com/en-us/microsoft-edge/download-the-new-microsoft-edge-based-on-chromium-0f4a3dd7-55df-60f5-739f-00010dba52cf)).
Navigate to any page and run the analyzer from your browser's developer tools.
This will return the same* results to you while also giving you some convenience utilities like highlighting the exact element that's failing.

\* It might not actually be the same in a couple cases (e.g., we've disabled some rules or a recent update that was pushed to the addon but we haven't updated yet) but it will generally be more strict than we are, so you should never see something in CI that you can't see in the addon.

## Deconstructing an error message

We have updated how accessibility violations appear in your terminal or CI logs. Each URL with violations will write a table like the one shown here.

| index | id | impact | description | nodes |
| :---: | :---: | :---: | :---: | :---: |
| 0 | 'aria-valid-attr-value' | 'critical' | 'ARIA attributes must conform to valid values' | 1 | 
| 1 | 'nested-interactive' | 'serious' | 'Nested interactive elements are not announced by screen readers' | 3 |

All error messages follow this same structure:
* The `index` is a 0-based count of accessibility violations on a page.
* The `id` maps to an [axe-core rule description](https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md) on GitHub. These rules link to more information on the Deque University site.
* The `impact` describes how much a violation will prevent or degrade the user experience.
* The `description` will give a one sentence explanation of the problem.
* The `nodes` will tell you how many violations of this type are on the page.

The test runner will give you a total count of issues at the end of the run.

Any violations should be confirmed using the [axe browser plugin](https://deque.com/axe) in the [EUI design system site](https://eui.elastic.co), or running a server locally. The axe browser plugin is available for Chrome, Firefox, and Edge.

## Testing environment

Run the suite locally with `yarn test-cypress-a11y`. CI already runs it on every pull request (Buildkite job **Cypress accessibility (a11y) tests on React 18**).

---

### Contributing To Eui Testing Cypress Testing (`wiki/contributing-to-eui/testing/cypress-testing.md`)

# Cypress testing

Currently, EUI only uses [Cypress component testing](https://docs.cypress.io/guides/component-testing/introduction) as opposed to its full E2E test runner. This is ideal for isolating/focusing on specific components while reducing traditional E2E start times.

## Running tests

`yarn test-cypress` runs component tests headlessly (no window appears)

`yarn test-cypress-a11y` runs component accessibility tests headlessly (no window appears)

`yarn test-cypress-dev` launches a chrome window controlled by Cypress, which lists out the discovered tests and allows executing/interacting from that window.

### Setting the theme

By default tests are run using the light theme. Dark mode can be enabled by passing the `--theme=dark` option.

### Testing specific version of React

By default, EUI Cypress tests are run using the latest supported version of React (18).
You can change that behavior by passing `--react-version` set to `17` or `18` (peer range). 

### Cypress arguments

You can also pass [Cypress CLI arguments](https://docs.cypress.io/guides/guides/command-line). For example:

```bash
# Only run a single specific test file, e.g. onBoarding.js
yarn test-cypress --spec '**/{file}.spec.tsx'

# Opt to run Chrome headlessly
yarn test-cypress --headless

# Overriding config settings, e.g. enabling video recording
yarn test-cypress-dev --config video=true

# Overriding env variables
yarn test-cypress-dev --env password=foobar
```

## Writing tests

### When to write Cypress tests

Cypress tests should primarily be written for functionality that Jest/JSDom can't realistically replicate, for example:

- Focus state
- Portals
- 3rd party dependencies
- Native DOM behaviors (e.g., scrolling, label<>input clicks)

### How to write Cypress tests

Cypress has its own specific [`cy.` API/commands](https://docs.cypress.io/api/commands/get#Arguments), of which you will likely be using `cy.get()`, `cy.find()`, and either `cy.click()` or `cy.type()` to interact with DOM elements. Here's a small example test:

```jsx
import { mount } from '@cypress/react';
import TestComponent from './test_component';

describe('TestComponent', () => {
  it('takes user input, submits it, and displays the resulting output', () => {
    mount(<TestComponent />);

    cy.get('[data-test-subj="someInput"]').type('hello world');
    cy.get('[data-test-subj="submitButton"]').click();

    cy.get('[data-test-subj="someOutput"]').contains('HELLO WORLD');
  });
});
```

#### Naming your test files

Create Cypress test files with the following name patterns to run in specific situations:

* `{component name}.spec.tsx` will run a full component test as part of every build
* `{component name}.a11y.tsx` will run an accessibility test using [Cypress Axe](#cypress-axe)

These test files should be in the same directory as `{component_name}.tsx`.

#### Do's and don'ts

* DO read through Cypress's [best practices](https://docs.cypress.io/guides/references/best-practices) recommendations
* DO use the `data-test-subj` attribute to mark parts of a component you want to `find` later.
* DON'T depend upon class names or other implementation details for `find`ing nodes, if possible.
* DON'T extend the `cy.` global namespace - instead prefer to import helper functions directly

### Recording failed Cypress tests on CI
EUI now has the ability to record failed Cypress tests as Buildkite CI artifacts. This feature is turned off by default, but can be turned on by changing `video: false` to `video: true` in [`packages/eui/cypress.config.ts`](https://github.com/elastic/eui/blob/main/packages/eui/cypress.config.ts). You can verify videos are being recorded by changing a Cypress test to fail on purpose, then running `yarn test-cypress` locally. Video files will be stored in `packages/eui/cypress/videos/`.

The EUI team has configured Cypress to only keep videos for failing tests. Videos are automatically compressed to make the artifact upload smaller.

### Cypress Axe
EUI components are tested for accessibility on every pull request (Buildkite Cypress a11y job) and locally via `yarn test-cypress-a11y`. This allows us to test changes to the DOM such as accordions being opened, or modal dialogs being triggered, more comprehensively. We use [cypress-axe](https://github.com/component-driven/cypress-axe) to access the underlying axe-core API methods and rulesets.

#### How to write cypress-axe tests

```jsx
// Names must follow the `{component name}.a11y.tsx` pattern to be run correctly
// accordion.a11y.tsx

describe('Automated accessibility check', () => {
  it('has zero violations when expanded', () => {
    cy.mount(
      <EuiAccordion {...noArrowProps}>
        <EuiPanel color="subdued">
          Any content inside of <strong>EuiAccordion</strong> will appear
          here. We will include <a href="#">a link</a> to confirm focus.
        </EuiPanel>
      </EuiAccordion>
    );
    cy.get('button.euiAccordion__button').click();
    cy.checkAxe();
  });
});
```

#### Configuring `cy.checkAxe()`

The `cy.checkAxe()` helper method has four optional parameters:
 
 - `skipFailures` - Set to `true` to enable report-only mode. Report-only will run the entire suite without causing tests to return early.
 - `context` - This could be the document or a selector such as a class name, id, or element. The `context` default is `div#__cy_root`.
 - `axeConfig` - The [axe.run API](https://www.deque.com/axe/core-documentation/api-documentation/#api-name-axerun) can be modified to include or exclude elements, individual rules, or entire rulesets.
 - `callback` - Define a [custom violations callbac](https://github.com/component-driven/cypress-axe#violationcallback-optional) if you need to add side effects or change the reporting structure
 
 ```jsx
 // Create a custom ruleset by extending EUI defaults

import { defaultAxeConfig } from '../../cypress/support/a11y/axeCheck';

const customAxeConfig = {
  ...defaultAxeConfig,
  runOnly: {
    type: 'tag',
    // Add best-practices to existing rulesets
    values: [...defaultAxeConfig.runOnly.values, 'best-practices'],
  },
};

// Violations will use the custome ruleset and cause tests to fail
cy.checkAxe(false, customAxeConfig);
 ```

### Cypress Real Events

> Cypress default events are simulated. That means that all events like `cy.click` or `cy.type` are fired from JavaScript. That's why these events will be untrusted (`event.isTrusted` will be `false`) and they can behave a little different from real native events. But for some cases, it can be impossible to use simulated events, for example, to fill a native alert or copy to the clipboard. This plugin solves this problem.

[Cypress Real Events](https://github.com/dmtrKovalenko/cypress-real-events#why)

#### Why Cypress Real Events?

Cypress Real Events uses the [Chrome Devtools Protocol](https://chromedevtools.github.io/devtools-protocol/) to handle behaviors like a real browser. This gives us a better way to test complex events like mouse hover and keyboard focus. By using real events and making assertions against them, we can test keyboard and screen reader accessibility as users change the local state.

#### How to write Cypress (real event) tests

The [Cypress Real Events API](https://github.com/dmtrKovalenko/cypress-real-events#api) works seamlessly with existing `cy()` methods. If you want to press a button using Cypress Real Events, you could use `realPress('Tab')` as a replacement for the `cy.tab()` synthetic method. If you want to press multiple keys (also known as a **chord**), you should pass an array like `['Shift', 'Tab']` to your helper method.

All Cypress Real Events methods are prefixed with the string "real". Here's a small example test:

```jsx
import TestComponent from './test_component';

describe('TestComponent', () => {
  it('presses a button using the Enter key', () => {
    /* Use the `realMount()` command to set focus in the test window */
    cy.realMount(<TestComponent />);
    
    /* Activate a button with a real keypress event */
    cy.get('[data-test-subj="submitButton"]').realPress('Enter');
    
    /* Assert the button has focus and the aria-expanded attribute has updated */
    cy.focused().invoke('attr', 'aria-expanded').should('equal', 'true');
  });

  it('presses a button using the Space key', () => {
    /* Assert the button also accepts the Spacebar keypress */
    cy.realMount(<TestComponent />);
    cy.get('[data-test-subj="submitButton"]').realPress('Space');
    cy.focused().invoke('attr', 'aria-expanded').should('equal', 'true');
  });
});
```

#### Do's and don'ts for Cypress Real Events

* DO follow [all previous guidance](#dos-and-donts) for writing Cypress tests
* DO use the correct mounting method:
  * Use `cy.realMount()` if your component doesn't receive focus automatically **OR**
  * Use `cy.mount()` for components that receive focus on render
* DO be on the lookout for new features!

## Debugging tests

For debugging failures locally, use `yarn test-cypress-dev`, which allows you to run a single specific test suite and runs tests in a browser window, making dev tools available to you so you can pause and inspect DOM as needed.

> :warning: As a general rule, we generally recommend taking a break and not clicking around while tests are running. This can eliminate or lower the possibility of hard-to-reproduce/intermittently flaky behavior and timeouts due to user interference.

### Artifacts

All failed tests will output a screenshot to a `screenshots/` folder (`cypress/screenshots`). We strongly recommend starting there for debugging failed tests to inspect error messages and UI state at point of failure.

To track what Cypress is doing while running tests, you can pass in `--config video=true` which will output screencaptures to the `cypress/videos/` folder for all tests (both successful and failing). This can potentially provide more context leading up to the failure point, if a static screenshot isn't providing enough information.

> ℹ️ We have videos turned off in our config to reduce test runtime, especially on CI, but suggest re-enabling it for any deep debugging.

### CI debugging

Failing screenshot artifacts (as well as Cypress logs) are generated by our Jenkins CI.

TODO: Instructions on where to click to see the relevant artifact(s)/screenshots

---

### Contributing To Eui Testing Eui Test Helpers (`wiki/contributing-to-eui/testing/eui-test-helpers.md`)

# EUI test helpers

[`@elastic/eui-test-helpers`](../../../packages/test-helpers) ships Playwright Component Objects used by downstream end-to-end tests (Kibana Scout). Each helper has validation tests that run its public API against the real component in Storybook. This page covers how those tests run in CI; for the package itself (directory layout, adding a Component Object) see the package [CONTRIBUTING](../../../packages/test-helpers/CONTRIBUTING.md).

## Running locally

Start Storybook, then run the suite (it attaches to the running dev server):

```shell
yarn workspace @elastic/eui build:workspaces   # one-time
yarn workspace @elastic/eui start              # Storybook on http://localhost:6006
# in another terminal:
yarn workspace @elastic/eui-test-helpers exec playwright install chromium   # one-time
yarn workspace @elastic/eui-test-helpers test
```

See the package [CONTRIBUTING](../../../packages/test-helpers/CONTRIBUTING.md) for the full local workflow and the HTML report.

## On every pull request

`eui-pull-request-test` runs two helper steps (`test-helpers` task in [`pipeline_test.sh`](../../../.buildkite/scripts/pipelines/pipeline_test.sh)):

- **Validation** — builds the EUI workspaces and Storybook, then runs the full Playwright suite once. Storybook is served by Playwright's `webServer` from the static build.
- **Flake detection** — [`pipeline_test_helpers_flaky.sh`](../../../.buildkite/scripts/pipelines/pipeline_test_helpers_flaky.sh) diffs the PR against its merge base and, for any changed component with a correlated helper, runs that helper's specs `--repeat-each=25` to surface flakiness — even when the helper itself was not touched. A flaky failure fails the build. It is a no-op when no correlated component changed.

### Component ↔ helper correlation

The correlation is by directory path, so keeping the helper's directory in parity with the EUI component's is all that is required. See [Flake detection in the package CONTRIBUTING guide](../../../packages/test-helpers/CONTRIBUTING.md#ci-integration) for the exact rule.

---

### Contributing To Eui Testing Screen Reader Testing Matrix (`wiki/contributing-to-eui/testing/screen-reader-testing-matrix.md`)

# Screen reader testing matrix
This document was created based on analytics compiled in July 2022. The analytics reflect the most common browsers, screen resolutions, and operating systems among Elastic Cloud users. The data was compiled anonymously and will only be used to inform testing priorities.

## Testing tiers

* **Tier 1 (T1):** Should be tested for all new components or significant experience updates
* **Tier 2 (T2):** Test as time allows during a regular PR review cycle
* **Tier 3 (T3):** Test as requested by customers or teammates

## Testing matrix

| | JAWS<br/>(Win) | NVDA<br/>(Win) | VoiceOver<br/>(MacOS) | Orca<br/>(Linux) | iOS VoiceOver<br/>(Apple devices) | TalkBack<br/>(Android devices) |
| --- | :---: | :---: | :---: | :---: | :---: | :---: |
| Chrome | T1 | T1 | ❌ | T3 | ❌ | T3 |
| Firefox | T2 | T1 | T2 | T3 | ❌ | ❌ |
| Edge | T2 | T2 | ❌ | ❌ | ❌ | ❌ |
| Safari | ❌ | ❌ | T1 | ❌ | T3 | ❌ |

## Resources

### Desktop screen readers
* [Using JAWS to Evaluate Web Accessibility](https://webaim.org/articles/jaws/)
* [Keyboard shortcuts for JAWS](https://webaim.org/resources/shortcuts/jaws)
* [Using NVDA to Evaluate Web Accessibility](https://webaim.org/articles/nvda/)
* [Keyboard Shortcuts for NVDA](https://webaim.org/resources/shortcuts/nvda)
* [Using VoiceOver to Evaluate Web Accessibility](https://webaim.org/articles/voiceover/)

### Mobile device screen readers
* [VoiceOver on Mobile](https://webaim.org/articles/voiceover/mobile)
* [Using TalkBack to Evaluate Web Accessibility](https://webaim.org/articles/talkback/)

---

### Contributing To Eui Testing Testing In Kibana (`wiki/contributing-to-eui/testing/testing-in-kibana.md`)

# Testing EUI features in Kibana ahead of time

> [!TIP]
> **Which page?**
> - **This page** - run EUI in local Kibana or stage a `.tgz` Kibana draft PR.
> - **[Nightly and Regression](https://github.com/elastic/eui-private/wiki/Nightly-and-Regression-testing-pipeline)** (internal) - Kibana CI against an npm snapshot.
> - **[Upgrading EUI in Kibana](https://github.com/elastic/eui-private/wiki/Upgrading-EUI-in-Kibana)** (internal) - ship an official EUI release into Kibana.

Most PRs should be tested in Kibana before merging into EUI main. Test a built version of EUI against Kibana and consider [staging the integration](#staging-integrations) to ensure the upgrade process is as painless as possible.

## Staging Integrations

Use this **Staging Workflow** to assist the EUI maintainers in integrating your PR into Kibana during an upgrade. Useful when:
- PR involves breaking changes
- You want to apply a new feature in Kibana to ensure adoption
- Existing styles may need to be tweaked
- There are test failures, especially integration tests

1.  **Stage in Kibana:** Create a **Draft PR** in the Kibana repo. Use this to handle test failures, style tweaks, or API migrations.
2.  **Reference in EUI PR:** Link the Kibana Draft in your EUI PR description.
3.  **Prep commits:** Add each staged commit URL under `# @next` in [`packages/release-cli/kibana-prep-commits`](https://github.com/elastic/eui/blob/main/packages/release-cli/kibana-prep-commits) (one URL per line). Nightly and the upgrade PR cherry-pick that list.
4.  **Final Upgrade:** The upgrader will cherry-pick your staged commits into the final Kibana version bump PR.

### Example: Staging Workflow

| Step | Link | Action |
| :--- | :--- | :--- |
| **1. Staging** | [Kibana Draft \#248805](https://github.com/elastic/kibana/pull/248805) | Create commits for API updates, style adjustments, and test fixes. |
| **2. Source** | [EUI PR \#9308](https://github.com/elastic/eui/pull/9308) | Note: *"All commits in the linked PR should be included in the upgrade."* |
| **3. Prep list** | [`kibana-prep-commits`](https://github.com/elastic/eui/blob/main/packages/release-cli/kibana-prep-commits) | Add each staged commit URL under `# @next`. |
| **4. Final** | [Kibana Upgrade \#253286](https://github.com/elastic/kibana/pull/253286) | Upgrader cherry-picks staged commits into the version bump. |

### Recommended Commit Structure

Keep staged commits atomic to simplify cherry-picking for the upgrader:

  * `refactor: update [some Kibana code] to use new EUI API`
  * `style: adjust styles for [some EUI change]`
  * `test: update snapshots for [some EUI change]`
  * `test: fix broken integration tests for [some EUI change]`

## Testing local EUI in local Kibana

`yarn link` doesn't work between EUI and Kibana - EUI is on Yarn v4 and Kibana is on pnpm, and their package managers are not interoperable. Instead, you have two options depending on your goal:

- For **local development** against a Kibana instance running on your machine, use the [`yarn watch --kibana`](../developing/developing-in-kibana.md) watcher.
- For **CI validation** — opening a Kibana draft PR so Kibana's CI runs against your EUI changes — use `yarn build-pack` (described below) to produce a `.tgz` that you commit to the Kibana PR.

### In EUI:

EUI is a monorepo and to build and test `eui` locally in Kibana you'll need to ensure that the internal dependency packages are correctly linked as well.

First, update the `package.json` in `eui/packages/eui` as follows:

- remove `@elastic/eui-theme-common` from dependencies
- add `"@elastic/eui-theme-common": "workspace:^"` to devDependencies
- add `"@elastic/eui-theme-common": "{CURRENT_VERSION}"` to peerDependencies, e.g. `"@elastic/eui-theme-common": "1.0.0"`

Then run the following command:

```bash
# eui/packages/eui
yarn build-pack
```

If you made changes to `eui-theme-common` and/or `eui-theme-borealis` directories you'll need to build those packages as well:

```bash
# eui/packages/eui-theme-common
yarn build-pack
```

```bash
# eui/packages/eui-theme-borealis
yarn build-pack
```

This will create the required `.tgz` file(s) with the changes in your `eui` (and `eui-theme-common`/ `eui-theme-borealis`) directory. At this point you can move it anywhere.

> [!IMPORTANT]
> If the `.tgz` is going to be committed to Kibana, rename it to snake_case (e.g. `elastic_eui_xx.x.x.tgz`). Kibana's `file_casing` quick check fails the PR on hyphenated names like the `elastic-eui-xx.x.x.tgz` that `yarn pack` produces.

### In Kibana:

Point the `package.json` file in Kibana to that file: `"@elastic/eui": "/path/to/elastic_eui_xx.x.x.tgz"`. Then run the following commands at Kibana's root folder:

```bash
pnpm kbn bootstrap --no-validate && pnpm start
```

* The `--no-validate` flag is required when bootstrapping with a `.tgz`.
  * Change the name of the `.tgz` after subsequent `yarn build-pack` steps (e.g., `elastic_eui_xx.x.x_1.tgz`, `elastic_eui_xx.x.x_2.tgz`). This is required for the package manager to recognize new changes to the package.
* Running Kibana with `pnpm start` ensures it starts in dev mode and doesn't use a previously cached version of EUI.

### Deploying local EUI in Kibana

Elastic engineers have the option to deploy a local EUI package in Kibana. To do so, do the following:

#### Generate and link a local EUI package

- Follow the steps above to create a local package of EUI using `yarn build-pack`
- Copy the generated `.tgz` package file(s) to the Kibana root and rename them to snake_case (see the note above)
- Point the `package.json` file in Kibana to that local file: `"@elastic/eui": "file:./elastic_eui_xx.x.x.tgz"`.
- Add `"@elastic/eui-theme-common"` to the `package.json` and point it either to the local package you copied, or add the published version that matches the version listed as a dependency in your local `@elastic/eui` package

```bash
# default release version, no local package for @elastic/eui-theme-common
"@elastic/eui-theme-common": "3.0.0"

# with local package added
"@elastic/eui-theme-common": "file:./elastic_eui_theme_common_xx.x.x.tgz"

```

- Run `pnpm kbn bootstrap` (requires pnpm on PATH — see [Developing EUI locally in Kibana](../developing/developing-in-kibana.md))
- Commit the changed files (`package.json`, `pnpm-lock.yaml` and EUI `.tgz` package) and push your branch
- Create a Kibana (draft) pull request
  - Kibana CI will run tests on this instance with your custom EUI package
  - To ensure CI works correctly, you'll need to add `@elastic/eui-theme-common` to `packages/kbn-dependency-ownership/src/rule.ts` ([example](https://github.com/elastic/kibana/pull/227054/files)) and `src/dev/license_checker/config.ts` ([example](https://github.com/elastic/kibana/pull/227054/files#diff-373e937e773b0370ab1d28f3cf90251dcbd3cf95546f8c54b6bb6b1f999999dcR96))

#### Deploy the custom EUI package

After you have created a Kibana PR following the steps above, there are two ways you can deploy your local EUI package in Kibana.

##### Using labels

- Add the labels `ci:cloud-deploy` and `ci:cloud-persist-deployment` on your PR and ensure the CI pipelines run by checking the "Click to trigger kibana-deploy-cloud-from-pr for this PR!" checkbox in the comment from **elasticmachine**
- Once the pipelines are finished, **kibanamachine** will post a message with a link to the credentials on Buildkite, there you'll find a link to the deployment e.g. https://kibana-pr-228477.kb.us-west2.gcp.elastic-cloud.com and a command to get the credentials
- Run the `vault` command to get the credentials in your terminal (if you never used the `vault` CLI, continue reading)
- To use HashiCorp's `vault` CLI
  - [Install it](https://developer.hashicorp.com/vault/install), if you're on a Mac you can use [homebrew](https://brew.sh/)
  - Login for the [Infra Vault (production)]((https://docs.elastic.dev/vault/accessing)) by running:
    - `export VAULT_ADDR=https://secrets.elastic.co:8200`
    - `vault login -method=oidc`

##### Using Kibana a la carte

Follow the instructions in [Kibana a la carte](https://kibana-a-la-carte.kbndev.co/) to deploy your PR.

---

### Contributing To Eui Testing Unit Testing (`wiki/contributing-to-eui/testing/unit-testing.md`)

# Unit testing

EUI unit tests run on Jest. New tests should be written with [React Testing Library (RTL)](https://testing-library.com/docs/react-testing-library/intro/). A subset of legacy tests still uses [Enzyme](https://enzymejs.github.io/enzyme/) and is being migrated — see [Legacy: Enzyme](#legacy-enzyme) below.

## Running tests

`yarn test-unit` runs **all** Jest unit tests at once.

`yarn test-unit button` will run tests with "button" in the spec name.

You can pass other [Jest CLI arguments](https://jestjs.io/docs/cli). For example:

`yarn test-unit -u` will update your snapshots.
Note: if you are experiencing failed CI builds (Buildkite) related to snapshots, then try clearing the cache first `yarn test-unit --clearCache`.

`yarn test-unit --watch` watches for changes and runs the tests as you code.

`yarn test-unit --coverage` generates a code coverage report showing you how
fully-tested the code is, located at `reports/jest-coverage`.

## Naming your test files

Create test files with the name pattern of `{component name}.test.tsx` in the same directory which
contains `{component name}.tsx`.

## Targeting files to test

You can also add any string to the end of the command to run the tests only on test files whose path contains that string. For example, `yarn test-unit button` will match both `accordion/button.test.tsx` (filename match) and `button/icon.test.tsx` (parent directory match), but not `card.test.tsx`.

`yarn test-unit --testMatch=react / --testMatch=non-react` will test specifically only `.tsx` files vs. non-`.tsx` files. If not specified, both types of tests will run automatically.

`yarn test-unit --react-version=18` will run tests against a specific React version that EUI supports (currently 17-18).

## Test helpers

The [`packages/eui/src/test`](/packages/eui/src/test) module exports functions and constants to help you write better tests. **Use these for new tests:**

* `requiredProps` is a list of all props almost all components should support.
* `shouldRenderCustomStyles` automatically asserts that consumer classNames, Emotion CSS, and custom styles are merged correctly with EUI's styles.
* The exports within `test/rtl` (`render`, `screen`, and `within`) provide out-of-the-box `data-test-subj` querying. `render` provides automatic `EuiProvider` wrapping.
  * _Note:_ Unlike RTL's recommendation to [use `screen` for queries](https://testing-library.com/docs/queries/about/#using-queries), EUI prefers, for consistency, to destructure test queries from the `render()` API.

### Test helper naming pattern

If the test helper includes `enzyme` or other libraries included only in `devDependencies`, use the `*.test_helper.[ts, tsx]` naming pattern to exclude the component from production builds, or place the helper in a namespaced folder.

## Legacy: Enzyme

EUI is migrating away from Enzyme. **Do not write new Enzyme tests** — use RTL (see [Test helpers](#test-helpers) above). The helpers below exist only to support existing Enzyme tests until the migration completes:

* `findTestSubject` helps you find DOM nodes in mounted components.
* `takeMountedSnapshot` generates a snapshot of a mounted component.

When touching a legacy Enzyme test, prefer porting it to RTL if the change is non-trivial.

## Test design

### Do's and don'ts

* DO use the `data-test-subj` attribute to mark parts of a component you want to `find` later.
* DON'T depend upon class names or other implementation details for `find`ing nodes, if possible.
* DON'T use snapshots, except for an initial `it renders` test. Prefer using specific assertions instead.

### Anatomy of a test

A good test will document:

* The default state of the component.
* The inputs for each prop, and the associated outputs.
* Errors.
* Special behavior, e.g. keyboard navigation, async behavior, DOM manipulation under the hood.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Writing mock component files

A component file can be mocked for snapshot simplification or to mitigate nondeterministic rendering in test environments. See [`src/components/icon`](/packages/eui/src/components/icon/) for a example.

_Mock component files are currently only used as part of consuming project test environments. To use mock components in EUI's own testing environments, use `jest.mock()` manually._

### Using the mock namespace

Component mocking relies on using the `[name].testenv.*` namespace for identification. The mocked module will replace the standard import in the `test-env` build. Both `index` files and individual component files can mocked.

### Mapping all module exports

The rendered output of a mocked component is at the author's discretion, however, all public exports from a module must be preserved in the mock file. Note that this does not apply to exported TypeScript types and interfaces, which will always be derived from the original component file.

---

### Contributing To Eui Testing Visual Regression Testing (`wiki/contributing-to-eui/testing/visual-regression-testing.md`)

# Visual regression testing

EUI uses [Playwright Test Runner](https://playwright.dev/) with [`jest-image-snapshot`](https://github.com/americanexpress/jest-image-snapshot) for component visual regression testing. Tests run against a live Storybook instance and compare screenshots of stories against previously approved reference images.

Visual regression tests run automatically on every pull request against the Storybook build from that pipeline, served locally on the VRT agent (the same files that are deployed as the preview). When differences are found, a diff table is posted as a PR comment and a Buildkite block step appears for human approval before baselines are updated.

> [!IMPORTANT]
> VRT runs in **CI** which owns the baselines and auto-commits them to your PR. Run it locally only when you really need to verify that many stories render as expected.

## Running VRT locally

Make sure you have [Docker](https://docs.docker.com/get-docker/) installed and running. It's used to take screenshots in a Linux environment matching CI.

Run the visual regression tests:

```shell
yarn workspace @elastic/eui test-visual-regression
```

Locally this builds and serves a static Storybook (like CI) and rebuilds it each run, so no dev server is needed and every run reflects your current stories. To test against a specific URL instead (e.g. a deployed PR preview):

```shell
yarn workspace @elastic/eui test-visual-regression -- --url https://eui.elastic.co/pr_1234/storybook
```

### Static build vs. dev server

The static build is served from flat files (no HMR) which keeps `networkidle` settling instantly. The dev server's HMR can otherwise stall it under emulation and make stories time out (see [Troubleshooting](#every-story-fails-with-pagewaitforloadstate-timeout-30000ms-exceeded)). The build happens inside the container (Linux, matching CI) and is reused across variants.

```shell
# Reuse the existing build for fast iteration (skip the rebuild)
yarn workspace @elastic/eui test-visual-regression -- --no-build

# Use the dev server instead (requires `yarn storybook --no-open` running)
yarn workspace @elastic/eui test-visual-regression -- --no-static
```

`--static`/`--build` default locally and are ignored when `--url` is set.

## Updating baseline screenshots

```shell
# Update all baselines
yarn workspace @elastic/eui test-visual-regression update

# Update baselines against a specific URL
yarn workspace @elastic/eui test-visual-regression update -- --url https://eui.elastic.co/pr_1234/storybook
```

Reference images are stored in `packages/eui/.vrt/reference/`.

## Variants

Each story is snapshotted under multiple **variants** to catch e.g. responsive-layout regressions. Every variant produces its own baseline file, suffixed with the variant name:

    packages/eui/.vrt/reference/
      navigation-euibutton--playground-desktop.png
      navigation-euibutton--playground-mobile.png

The test-runner is invoked once per variant (similar to [Playwright projects](https://playwright.dev/docs/test-projects)), so each variant runs in its own process and browser context with the viewport applied before the story renders. Variants are defined in [`.storybook/vrt-variants.json`](https://github.com/elastic/eui/tree/main/packages/eui/.storybook/vrt-variants.json). CI runs one variant per parallel job. Locally, [`scripts/test-visual-regression.js`](https://github.com/elastic/eui/tree/main/packages/eui/scripts/test-visual-regression.js) reads that file and sets `VRT_VARIANT` for each run.

Current variants:

| Variant | Viewport |
|---|---|
| `desktop` | 1440 × 900 |
| `mobile` | 390 × 844 |

### Skipping specific variants

If a story can't render correctly under a particular variant, opt out of just that variant by passing an array to `parameters.vrt.skip` (see [Skipping stories](#skipping-stories)). The story still runs under the remaining variants.

## Filtering stories

Pass any [`test-storybook`](https://storybook.js.org/docs/writing-tests/test-runner) flags after `--`. Jest path filters need `--` before the pattern:

```shell
# By story name
yarn workspace @elastic/eui test-visual-regression -- -- euibutton
# By story file
yarn workspace @elastic/eui test-visual-regression -- -- --testPathPattern=button.stories

# By tag
yarn workspace @elastic/eui test-visual-regression -- --includeTags vrt-only
yarn workspace @elastic/eui test-visual-regression -- --excludeTags skip-vrt
```

The wrapper runs both variants. For one variant only:

```shell
VRT_VARIANT=desktop yarn workspace @elastic/eui test-storybook -- euibutton
```

## Skipping stories

Set `parameters.vrt.skip` to opt a story out of VRT. Leave a comment explaining why.

- `skip: true` skips the story under **all** variants.
- `skip: ['mobile']` skips only the listed variants; the story still runs under the rest.

```tsx
export const MyStory: Story = {
  parameters: {
    vrt: {
      // Skipped: this story is interaction-only, not a visual state
      skip: true,
    },
  },
};

export const MobileUnsupported: Story = {
  parameters: {
    vrt: {
      // Skipped on mobile: the toolbar control is hidden below this breakpoint
      skip: ['mobile'],
    },
  },
};
```

Skipping a variant also skips the story's `play` body for that variant, so e.g. interactions don't run at a viewport the story isn't built for.

When you add `vrt.skip` to a story that previously had a baseline, manually delete the affected snapshot files from `packages/eui/.vrt/reference/` (all variants for `true` or just the listed ones for an array).

## Using non-default selectors

By default the test runner screenshots `#story-wrapper > *`. For components that render outside the story wrapper (portals, popovers, dropdowns) specify a custom selector in `parameters.vrt.selector`.

Predefined selectors are exported from [`.storybook/vrt.ts`](https://github.com/elastic/eui/tree/main/packages/eui/.storybook/vrt.ts):

```tsx
import { VRT_SELECTORS } from '../../../.storybook/vrt';

export const Open: Story = {
  parameters: {
    vrt: {
      selector: VRT_SELECTORS.portal,
    },
  },
};
```

Available selectors:

| Selector | Value | Use case |
|---|---|---|
| `VRT_SELECTORS.default` | `#story-wrapper > *` | Default (no need to set) |
| `VRT_SELECTORS.textOnly` | `#story-wrapper` | Components rendering a text node |
| `VRT_SELECTORS.portal` | `page` | Portalled elements (popover, tooltip, dropdown); takes a full-page screenshot |

## Using interactions for specific states

Wrap play functions with `playDecorator` when they need to reach elements outside the story wrapper (e.g. portals). It injects `bodyElement` (`document.body`) into the context so `within(bodyElement)` can query portal content.

```tsx
import { userEvent, waitFor, within, expect } from '@storybook/test';
import { VRT_SELECTORS, playDecorator } from '../../../.storybook/vrt';

export const OpenDropdown: Story = {
  parameters: {
    vrt: { selector: VRT_SELECTORS.portal },
  },
  play: playDecorator(async (context) => {
    const { canvasElement, bodyElement } = context;

    // canvasElement: content inside the story wrapper
    const canvas = within(canvasElement);
    // bodyElement: use this to reach portalled elements
    const body = within(bodyElement);

    await userEvent.click(canvas.getByRole('combobox'));
    await waitFor(() => {
      expect(body.getByRole('listbox')).toBeVisible();
    });
  }),
};
```

By default the play function is skipped when not running under Playwright (i.e. in the Storybook UI). Pass `false` as the second argument to run it everywhere:

```tsx
play: playDecorator(async (context) => { ... }, false)
```

## Authoring stable stories

VRT compares screenshots pixel-for-pixel (4-pixel allowance for subpixel diff), so anything non-deterministic (network requests, animations, randomness, timing or capturing the wrong element) produces false diffs or flaky failures. The test-runner already neutralizes several sources globally:

- CSS animations are paused before the screenshot (`animations: 'disabled'`) and `prefers-reduced-motion: reduce` is emulated.
- The runner waits for the page to be ready: for all `<img>` elements to finish loading before capturing, for all fonts to be ready and for layout to be stabilized.
- Failed screenshots are retried automatically.

Some common failures and how to fix them:

### Only the first element is captured (fragment roots)

The default selector `#story-wrapper > *` screenshots the **first child element** of the wrapper. A `render` function or decorator that returns a fragment with multiple siblings therefore captures only the first one and clips the rest:

```tsx
// ❌ Only the first <EuiBanner> is captured
render: () => (
  <>
    <EuiBanner />
    <EuiBanner />
  </>
),

// ✅ Wrap in a single element so the whole set is captured
render: () => (
  <div>
    <EuiBanner />
    <EuiBanner />
  </div>
),
```

This also applies to decorators that add sibling content (e.g. wrapping the story in explanatory text) - wrap them in an element, not a fragment.

### Portalled content isn't captured

Popovers, tooltips, modals, flyouts and dropdowns render outside the story wrapper, so the default selector misses them. Use the portal selector to take a full-page screenshot (see [Using non-default selectors](#using-non-default-selectors)):

```tsx
parameters: { vrt: { selector: VRT_SELECTORS.portal } },
```

### Overlays captured before they finish opening

An overlay opened on mount (through `isOpen` or initial state) may not be rendered/positioned when the screenshot fires, producing a blank or half-positioned capture that flakes. Add a `play` that waits for it to be visible:

```tsx
import { within } from '../../../.storybook/test';
import { playDecorator } from '../../../.storybook/vrt';

export const Open: Story = {
  parameters: { vrt: { selector: VRT_SELECTORS.portal } },
  play: playDecorator(async ({ canvasElement }) => {
    await within(canvasElement).waitForEuiPopoverVisible();
  }),
};
```

For portalled panels you can also assert against `bodyElement`:

```tsx
play: playDecorator(async ({ bodyElement }) => {
  await waitFor(() =>
    expect(bodyElement.querySelector('[data-popover-open]')).toBeVisible()
  );
}),
```

### Remote assets (images, avatars, fonts)

Never reference remote URLs (`placehold.co`, `images.unsplash.com`, `picsum.photos`, `gravatar` etc.). Network fetches are slow and unreliable in CI, causing instability. Inline the asset as a `data:` URI instead:

```tsx
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64"><rect width="100%" height="100%" fill="#0B64DD"/></svg>`;

<EuiAvatar imageUrl={`data:image/svg+xml,${encodeURIComponent(svg)}`} />
```

If a story genuinely needs a real raster image (e.g. the `EuiImage` showcase), either bundle a committed local asset or `vrt.skip` the story.

### Randomized or time-based data

`faker` without a seed, `Math.random()`, `Date.now()` and `new Date()` render different output on every run. Pin them:

```tsx
import { faker } from '@faker-js/faker';

faker.seed(123); // consistent data across runs
```

Use fixed dates/values for anything rendered (e.g. `date="January 1st 1970"`).

### Oversized stories

Stories that render hundreds of rows/items produce very tall screenshots that are slow to capture and can time out (especially under the `mobile` variant where responsive layouts stack every cell vertically). Keep datasets small. Note that `EuiBasicTable`/`EuiInMemoryTable` don't paginate `items` themselves, so passing a large array renders every row.

### Interaction- or behavior-only stories

If a story exists to demonstrate behavior (focus return, callbacks, keyboard handling) and is visually identical to another captured story, it adds no VRT value and only risks flake - [skip it](#skipping-stories) with `vrt.skip` and a comment.

### Text-only components

A bare text node can have zero height under `#story-wrapper > *`. Use `VRT_SELECTORS.textOnly` so the wrapper itself is captured (see [Using non-default selectors](#using-non-default-selectors)).

## Troubleshooting

### Every story fails with `page.waitForLoadState: Timeout 30000ms exceeded`

`waitForPageReady` waits for `networkidle` on Playwright's own 30s timeout (separate from Jest's `--testTimeout`). The **dev server's** HMR keep the network busy. Under emulation it never goes idle in time, so *every* story times out and suites take 10-20 minutes.

**Fix:** don't pass `--no-static` locally. The default [static build](#static-build-vs-dev-server) has no HMR, so `networkidle` settles instantly.

### VRT is slow or times out locally on Apple Silicon

Local runs use a `linux/amd64` container to match CI. On Apple Silicon (arm64) that image is **emulated** and much slower than native, making large stories hang or time out:

- **Enable Rosetta (recommended).** In Docker Desktop, turn on _Settings → General → "Use Rosetta for x86_64/amd64 emulation on Apple Silicon"_, and raise CPU/memory under _Settings → Resources_. Far faster than the default QEMU emulation while still `linux/amd64`, so screenshots stay byte-identical to CI.
- **Run natively for quick checks only.** Dropping `--platform linux/amd64` runs the native arm64 image (no emulation, much faster). Renders are usually identical but architecture can introduce 1-2px anti-aliasing differences, so **don't commit baselines this way** - use it only to check stories run and let CI produce baselines.

The Docker path in [`scripts/test-visual-regression.js`](https://github.com/elastic/eui/tree/main/packages/eui/scripts/test-visual-regression.js) also caps `--maxWorkers` and raises `--testTimeout` for headroom.

## CI pipeline architecture

VRT runs automatically on every pull request as part of the `eui-deploy-docs` Buildkite pipeline.

```mermaid
flowchart TD
    PR[Pull request] --> WS[Build and deploy website]
    PR --> SB[Build and deploy Storybook]
    SB --> VRT[Test visual regression]
    VRT --> R[Report visual regression]

    R -->|skip-vrt label| N[Notify]
    R -->|Pass, new stories| C1[Commit baselines\nto PR branch]
    R -->|Pass, no changes| N
    R -->|Fail, infrastructure error| N

    R -->|Fail, visual diffs found| D[Post diff table\nto PR comment]
    D --> B[Approve visual changes]
    B --> U[Update VRT baselines]
    U --> N

    C1 --> N
    WS --> N
```

CI commits baselines directly to the PR branch:

- `chore(eui): add VRT baseline screenshots` - the PR adds new stories. Automatic, regardless of pass/fail.
- `chore(eui): update VRT baseline screenshots` - after approving the *Approve visual changes* block step in Buildkite.

A PR with both new and changed stories gets both commits, `add` first. Either commit retriggers CI.

### Skipping in a PR

If VRT itself is broken and blocking merges, add the `skip-vrt` label to the GitHub PR. The VRT step will detect the label, exit without running any tests and the notify comment will clearly state that VRT was skipped.

> [!WARNING]
> `skip-vrt` doesn't run the test runner, so new stories don't get baselines. Be especially careful if you're adding it on your PR that introduces visual changes.

The label is captured at build-trigger time. To affect an existing build, trigger a fresh one:

- Comment `buildkite test it` on the PR
- Push any new commit
- Close and reopen the PR
- Buildkite UI: click **New Build** (not "Rebuild", which reuses the original env)

---

### Packages Website Docs Content Accessibility (`packages/website/docs/content/accessibility.mdx`)

---
sidebar_position: 6
---

# Accessibility

This page shares common tips and tricks for writing accessible UI copy. It is not exhaustive and does not replace the official
[WCAG 2.0 guidelines](https://www.w3.org/TR/2008/REC-WCAG20-20081211/#guidelines).

Writing accessible UI copy is only one part of improving web accessibility. Check the [EUI documentation](https://eui.elastic.co/docs/utilities/accessibility/) for more accessibility guidelines.

## What is accessible content and why does it matter

**Accessibility** for content means making sure that the content can be consumed properly, independently of how users choose or have to interact with it.

Our users and readers are diverse, with different abilities and disabilities.
They also interact with our content in different ways: screen readers, mobile devices, Braille, and so on. The list is long, and always evolving.

As content authors, it is our responsibility to provide them with [perceivable, operable, understandable, and robust content](https://www.w3.org/TR/UNDERSTANDING-WCAG20/intro.html#introduction-fourprincs-head).

## Guidelines

✔️ **Make your content scannable.** A clear structure and meaningful words tell users if the feature or flow is relevant to them within seconds.

✔️ **Add alt text for all images, icons and media files.** Screen readers, Braille output devices, and search engines love concise, accurate alt text that describes what cannot always be displayed, viewed or heard on screen.


| Inaccessible                 |  | Accessible               |
| --------------------- | --- | ------------------------- |
| Image of in progress rule creation form. | → | User is setting up a new threshold rule. |
| Logs integrations | → | Integrations that let you to ingest logs. |


✔️ **Use plain language.** Clear, concise UI copy helps users perform tasks. Jargon and complex sentences can confuse or slow them down. You can find very helpful and detailed plain language guidance on the [plainlanguage.gov](https://www.plainlanguage.gov/guidelines/) website.


| Inaccessible                 |  | Accessible               |
| --------------------- | --- | ------------------------- |
| Update the sourcerer selection to be the default detections data view. | → | Choose the default Security data view. |
| **Cancel update rule?** You will lose changes to the rule. | → | **Discard rule changes?** Select **Discard** to reject these changes. |


✔️ **Use meaningful link text.** Descriptive text instead of "click here" or "read more" helps users understand what to expect when they open the link. Screen readers jump between links by generating a list of them, and spell out URLs.


| Inaccessible                 |  | Accessible               |
| --------------------- | --- | ------------------------- |
| Click here for more information. | → | Learn more about indices. |
| Create a query. Learn more. | → | Learn how to create an ES\|QL query. |


✔️ **Use device agnostic language.** Users can access content and products in many ways. We do not know if they use a mouse, keyboard, tablet, or another device.


| Inaccessible                 |  | Accessible               |
| --------------------- | --- | ------------------------- |
| Type in your username and password. | → | Enter your username and password. |
| Select a time range for the Alerts table. | → | Choose a time range for the Alerts table. |


✔️ **Avoid directional language.** Do not use above, below, left, right, and so on. All these terms assume that UI layouts never varies, that users can actually see the UI, and that they see it the way you think they do. Users might have disabilities or impairments that affect how they understand the UI.


| Inaccessible                 |  | Accessible               |
| --------------------- | --- | ------------------------- |
| Complete the form below. | → | Complete the following form. |
| Import values from a file by clicking the **Import values** button under the table. | → | Select **Import file** to import values from supported file types. |


## Words to avoid

Refer to [Word choice](./word-choice.mdx) to learn more about words to avoid and their replacements.

---

### Packages Website Docs Content Adapt Tone (`packages/website/docs/content/adapt-tone.mdx`)

---
sidebar_position: 4
---

# Tone

Adapt the way you write to each situation users can face.

During the users' journey with Elastic, there are times for excitement and discovery, but also times for help, support, and empathy.

## Stimulating

**Attributes**

    We're proud to show new and cool stuff. Be:

    - Motivational
    - Excited
    - Enthusiastic

    When using this tone, you may:
    - Use exclamation marks, but sparingly.
    - Take time to help the user understand how this feature benefits them.
    - Use visuals to support your text.

**When to use?**

    Although it can be very visible because of the way it's written and the UI elements it shows in, the **stimulating** tone is used **quite rarely** overall.

    We use it when we want to show new things to users, especially in:

    - Product tours
    - New feature announcements


## Informational

**Attributes**

    E=MC². Be:

    - Direct
    - Straight to the point
    - Neutral

    When using this tone:
    - Use a minimum of words.
    - Write for scanning and help users quickly locate what matters to them.
    - Use action verbs to:
        - Label selection controls.
        - Describe what settings do or what to do with a setting.
    - Use clear nouns for
        - menus, form field names


**When to use?**

    The **informational** tone is the **most used** one. It is everywhere in the UI, and sometimes seems so normal that we forget about it. Yet, it is very important!

    We use it for naming and describing things:

    - Menus, titles, setting names, hint text, placeholders, introductions, and descriptions
    - In-product assistance (tooltips, help popovers, setup guides, syntax references, etc.)
    - Information callouts
    - Confirmation modals
    - Calls to action (buttons and links)
    - Event logs


## Supportive

**Attributes**

    Something might be wrong and requires attention. Let us help you. Be:

    - Reassuring
    - Serious
    - Urgent

    When using this tone, you may:
    - Be more action-oriented than usual to offer direct paths to users.
    - Focus on what went wrong. Don't be apologetic.
    - Help users learn how something happened, how to prevent it, how to fix it.
    - Provide clear actions, or clearly state it if there's no action needed.


**When to use?**

    The **supportive** tone is used **sparingly** overall and is usually shown in places that draw the user's attention, for example in warnings and error messages.

    We use it when notifying users of things that require attention, especially in:

    - Errors
    - Licensing or billing-related content
    - Vulnerability and remediation content
    - Warnings and cautions
    - Upgrade and deprecation notices


## Stern

**Attributes**

    We don't advise this action, but you're the master of your destiny. Be:

    - Deterring
    - Heavy with caution
    - Advisory

    When using this tone, you may:
    - Use stronger words that highlight possible negative effects.
    - Format the content in a way that make the risks stand out.

**When to use?**

    The **stern** tone is **rarely** used. Reserve it for very specific cases, and for advanced or administrative features.

    We use it when insisting on the high risks an action could pose, especially in:

    - Danger type of warnings
    - Unsupported actions

---

### Packages Website Docs Content Inclusivity (`packages/website/docs/content/inclusivity.mdx`)

---
sidebar_position: 7
---

# Inclusivity

This page provides guidelines for writing inclusive UI copy for product content but it's not exhaustive.

## What is inclusive content and why does it matter

**Inclusivity** for content means making sure that the content we serve reflects the diversity of our community, respects it, and promotes positive change.

## Guidelines

### Write for an international audience

Our products use American English (en_US) as a standard for written content.
Yet they are used, read by persons all around the globe, for whom English is not always their primary language.
Our content must take that into account.

✔️ **Aim for simplicity.** Indeed, we are a technical company, writing for
  technically-savvy users. However, it benefits everyone if we try to keep our writing as simple as possible.

  * **Short sentences** - They leave less space for interpretation. They are easier to scan, read, and translate.

  * **Plain language** -  Use active voice, present tense, using examples, and so on.
  Some of these guidelines might already look familiar. Several countries have
  [plain language initiatives](https://www.plainlanguage.gov/guidelines/) to
  promote clearer communication. Do your
  best to embrace these guidelines and focus on the message.

  * **Negation** - It is easier to say what something IS
  versus what it is NOT. When you add a negative construction, it takes the
  reader longer to parse the meaning of the phrase. For example, instead of saying "You cannot access the content without signing up", say "Sign up to access the content."

  * **Words with multiple meanings** -
  Don't skip helper words if they make the sentence clearer and easier to read. In UI copy, we try to be as literal and unambiguous as possible to ensure that it can be easily consumed by our users from around the globe. One way to achieve that is to choose words that have fewer meanings, especially when a word's intended meaning is not its primary meaning.

✔️ **Be aware of differences and diversity in content and examples.**
Different people are used to different names, currencies, date and time formats, different units of measurement (like for temperature, distance, speed), and so much more.
* Avoid ambiguous values, like `04/05/06` for a date. Is it May 4 or April 5, and which year? `11/17/1987` leaves less room for interpretation if the exact format is not specified nearby.
* If there is no obvious example standard (RFC) to follow, try to be diverse to represent our audience.

✔️ **Avoid idioms or expressions that are not commonly known, a.k.a regionalisms.**

In our Elastic documentation we aim for a fun, friendly, and sometimes quirky
tone. To achieve that, it can help to use informal, playful language. However, we also have to be careful that our text is as inclusive as possible, so we try to avoid expressions that might be unknown or opaque for some users. Here are a few examples of what to avoid:

* Idioms (for example, _It's a piece of cake_ or _So far so good_)
* Regional expressions (for example, _G'day!_, _Y'all_, or _eh_)
* Sports expressions (for example, _touched base_ or _threw a curve ball_)
* Pop culture references (for example, _Elvis has left the building_ or _Same bat-time, same bat-channel_)

We're all pretty good at avoiding these, but there's one problematic type of
expression that sometimes shows up in UI copy. Latin terms and
abbreviations are a common source of confusion, particularly for people whose
first language does not have Latin roots.

Here are some terms to avoid and suggested alternatives:

| Avoid      |  | Use instead     |
--- | --- | ---
| _e.g._ (exempli gratia) | → | _for example_ |
| _etc._ (et cetera) | → | _and more_ or _and so on_ |
| _i.e._ (id est) | → | _that is_ |
| _via_ | → | _by way of_, _by means of_, or _through_ |

✔️ **Aim for readability.** Tools like the [Hemingway App](https://hemingwayapp.com/) can help you make content simpler. Be conversational, but prioritize clarity.

### Use gender-neutral language

Writing gender-neutral mainly consists in avoiding gender bias and word choices implying that one gender is the norm.

✔️ **Pronouns.** In the UI, this can be avoided by addressing users directly.
When it's not possible, use *they*/*their*, even for singular. There's more than one gender, and it's not binary either.

✔️ **Biased words and expressions.** Guys, mankind, policeman... Words that we're all used to hear and use. But the default is not male.
Most expressions and words that perpetuate this bias (that exists in many cultures and languages!) can be replaced with neutral alternatives or synonyms: Folks, humanity, police officer...

### Avoid violent, offensive, ableist terminology

Earlier in this page, we discussed avoiding ambiguous terms, especially when a word's intended meaning is
not its primary meaning. Other types of words and phrases best avoided are:

* buzzwords (_incentivize_, _synergies_)
* superhero terms (_rock star_, _wizard_, _ninja_)
* violent imagery (_crush the competition_)
* non-specific superlatives (_unrivaled_, _unparalleled_, _world class_)

Some words have nuances that fall into the above categories, which may cause
them to be misinterpreted. Here are some alternatives:

| Avoid      |      | Use instead   |
--- | --- | ---
| Abort	     | → | _stop_, _cancel_, or _end_ |
| Boot 	     | → | _start_ or _run_ |
| Execute     | → | _run_ or _complete_ |
| Hack (noun) | → | _tip_ or _workaround_ |
| Hack (verb) | → | _configure_ or _modify_ |
| Hit (verb)  | → | _click_ or _press_ |
| Hit (noun)  | → | _visits_ (as in _website visits_) |
| Invalid     | → | _not valid_ or _incorrect_ |
| Kill		  | → | _cancel_ or _stop_ |
| Terminate	  | → | _stop_ or _exit_ |

---

### Packages Website Docs Content Language (`packages/website/docs/content/language.mdx`)

---
sidebar_position: 5
---

import {
  EuiFlexGroup,
  EuiButton,
  EuiSideNav,
  htmlIdGenerator,
  EuiIcon,
  EuiCallOut,
} from '@elastic/eui';

# Language

Guidelines for using consistent spelling and terminology in the UI.

## Spelling

Use American English when writing UI copy. American English is a version of the English language used in the United States. It's sometimes called United States English or U.S. English.

Certain words are spelled differently in American English and British English. You'll find some of these key spelling differences in the following sections.

### Verbs that end with 'ize' or 'yze'

In American English, verbs that end with 'ize' usually end with 'ise' in British English. Similarly, verbs that end with 'yze' in American English usually end with 'yse' in British English.

| American English | British English |
| ------------- |:-------------:|
| organize | organise |
| authorize | authorise |
| analyze | analyse |

### Nouns that end with 'or'

In American English, nouns that end with 'or' usually end with 'our' in British English.

| American English | British English |
| ------------- |:-------------:|
| flavor | flavour |
| color | colour |
| behavior | behaviour |

### Nouns that end with 'ense'

In American English, nouns that end with 'ense' usually end with 'ence' in British English.

| American English | British English |
| ------------- |:-------------:|
| license | licence |
| defense | defence |
| pretense | pretence |

### Nouns that end with 'og'

In American English, nouns that end with 'og' usually end with 'ogue' in British English.

| American English | British English |
| ------------- |:-------------:|
| dialog | dialogue |
| catalog | catalogue |
| epilog | epilogue |

## Case and capitalization

<EuiCallOut title="Use sentence case by default" color="primary">
  This goes for navigation menus, titles and headers, buttons, and so on.
</EuiCallOut>

Use **sentence case** by default for UI copy, including actions, views, settings, section headers, and dialog titles. Sentence case is easier to read, even in headings, and helps branded names stand out. It also makes those names easier to recognize and preserve when localizing an interface. Title Case can feel more formal, so don't use it just to make a label look prominent.

Reserve **Title Case** for proper names: branded products, apps, and features such as Entity Analytics and Machine Learning. A useful check is whether you'd refer to the item by that name in a product announcement, rather than using the words to describe what a section contains. For example, Stack management, GenAI settings, Budgets and notifications, API keys, and Trust management are descriptive labels, so use sentence case. Keep a proper name's established capitalization wherever it appears, and use sentence case for the surrounding words, as in "Open in Entity Analytics" or "Entity Analytics settings."

Even with sentence case, make sure to capitalize the following terms and expressions:

- [Branded terms](https://brand.elastic.co/302f66895/p/194a3b-writing-style-guide/t/159934) like solution and application names. For example, always write Elastic Observability, **not** elastic observability.
- Acronyms, such as URL and API.

Note that some names don't need to be capitalized when they're used as common names. For example, **Elastic Cloud Serverless** and **our serverless architecture** are both correct.

| UI text | Casing | Why |
| --- | --- | --- |
| Entity Analytics | Title Case | Feature name |
| Add data | Sentence case | Action, not a name |
| Open in Entity Analytics | Sentence case, with the name unchanged | Sentence-case action containing a capability name |
| Create Entity Analytics dashboard | Sentence case, with the name unchanged | "Entity Analytics" is a name; "dashboard" is generic |
| Entity Analytics settings | Sentence case, with the name unchanged | "Settings" is a generic descriptor |
| Add to case | Sentence case | "Case" is a generic object, not a name |
| Open in Cases | Sentence case, with the name unchanged | "Cases" is the app name |

<EuiFlexGroup>
<Guideline type="do" text="Sentence case fits most situations.">
  <EuiButton fill>Check for new data</EuiButton>
</Guideline>

<Guideline type="dont" text="Capitalize every word in buttons or titles.">
  <EuiButton fill>Check For New Data</EuiButton>
</Guideline>
</EuiFlexGroup>

<EuiFlexGroup>
<Guideline type="do" text="Use sentence case for actions and keep names capitalized.">
  <EuiFlexGroup gutterSize="s">
    <EuiButton fill>Add data</EuiButton>
    <EuiButton>Open in Entity Analytics</EuiButton>
  </EuiFlexGroup>
</Guideline>

<Guideline type="dont" text="Don't use Title Case for actions or change a name's capitalization.">
  <EuiFlexGroup gutterSize="s">
    <EuiButton fill>Add Data</EuiButton>
    <EuiButton>Open in entity analytics</EuiButton>
  </EuiFlexGroup>
</Guideline>
</EuiFlexGroup>

<EuiFlexGroup>
<Guideline type="do" text="Use Title Case for the app name and sentence case for navigation labels.">
  <EuiSideNav
    mobileBreakpoints={[]}
    aria-label="Entity Analytics navigation"
    style={{ width: 220 }}
    items={[
      {
        name: 'Entity Analytics',
        id: htmlIdGenerator('entityAnalyticsDo')(),
        icon: <EuiIcon type="logoElasticsearch" />,
        items: [
          { name: 'Overview', id: htmlIdGenerator('overviewDo')() , onClick: () => {}},
          { name: 'Entities', id: htmlIdGenerator('entitiesDo')() , onClick: () => {}},
          { name: 'Settings', id: htmlIdGenerator('settingsDo')() , onClick: () => {}},
        ],
      },
    ]}
  />
</Guideline>

<Guideline type="dont" text="Don't change the app name's capitalization or capitalize generic navigation labels as titles.">
  <EuiSideNav
    mobileBreakpoints={[]}
    aria-label="Entity analytics navigation"
    style={{ width: 220 }}
    items={[
      {
        name: 'Entity analytics',
        id: htmlIdGenerator('entityAnalyticsDont')(),
        icon: <EuiIcon type="logoElasticsearch" />,
        items: [
          { name: 'Overview', id: htmlIdGenerator('overviewDont')(),  onClick: () => {}},
          { name: 'Entities', id: htmlIdGenerator('entitiesDont')() , onClick: () => {}},
          { name: 'Entity Analytics Settings', id: htmlIdGenerator('settingsDont')() , onClick: () => {}},
        ],
      },
    ]}
  />
</Guideline>
</EuiFlexGroup>

## Punctuation

### Ellipsis

Only use ellipsis for truncated text or situations that require the user to wait.

- **Do:** Page loading... **not** Elastic offers many features such as Dashboards, Machine Learning, Synthetics...

### Exclamation mark

Avoid exclamation marks in most cases. A single exclamation mark when sharing exciting news may be appropriate.

### Oxford comma

Use the Oxford comma before the final item in a list.

- **Do:** Elastic's solutions are Elasticsearch, Observability, and Security **not** Elastic's solutions are Elasticsearch, Observability and Security

### Periods (full stops)

Use periods with:

* description text
* messages
* notifications
* list items that are complete sentences

Don't use periods with:

* headers
* titles
* placeholders
* list items that are incomplete sentences

## Contractions

Use contractions if they make your text flow more naturally, such as "didn't" instead of "did not" and "can't" instead of "cannot."

<EuiFlexGroup gutterSize="m">
  <Guideline type="do" text="Use contractions if they make the text easier to read.">
    Didn't find what you were looking for?
  </Guideline>
  <Guideline type="dont" text="Without the contraction, this text sounds stilted.">
    Did not find what you were looking for?
  </Guideline>
</EuiFlexGroup>

## Vocabulary

Check [Word choice](./word-choice.mdx) for guidance on specific terms to use or to avoid.

---

### Packages Website Docs Content Style (`packages/website/docs/content/style.mdx`)

---
sidebar_position: 3
---

# Voice and writing style

Our **Voice** represents the personality we want to convey through the UI copy in our products.
The following principles define the foundation of our voice.

## Conversational

Real people, talking to real people.

| ✔️ Be...            | How?                                                                        |
|--------------------|-----------------------------------------------------------------------------|
| User-focused       | Address users directly. Don't abuse possessive markers like "yours".[1]        |
| Plainspoken | Be conversational, yet professional. Write close to how you'd talk. Use contractions and active voice.      |
| Inclusive    | Write for all audiences. Our users are from everywhere. Don't use terms that might discriminate or offend and avoid complex language for non-native English speakers such as phrasal verbs. |
| Empathetic | Write what matters to users. Use words that you and users normally use.               |

> [1] Sometimes, we give the user full ownership of an action. In that case, it's acceptable to use "I" and "my". For example, for a legal agreement checkbox "I agree to follow the terms of service". We can also use "We" when talking about actions Elastic takes for users.

## Practical

Get the user's job done.

| ✔️ Be...     | How?                                                                                    |
|-------------|-----------------------------------------------------------------------------------------|
| Timely      | Help users when it's needed. Not everything is critical to describe in more details or at once. Make information discovery progress at the same pace as the user.   |
| Informative | Ensure all content serves a purpose and is not just decoration. Be straight to the point. It's not mandatory to have help text and descriptions for everything.|
| Action-oriented | Whenever possible, drive actions and support user intent with action verbs.|
| Precise | Avoid using verbs or determiners alone without a noun in buttons and action menus to add clarity. For example, prefer "Save dashboard" over "Save". Or "this setting" over "this".|
| Consistent | Use the same terminology to mean the same thing. Make sure spelling, capitalization, punctuation, labels, and use of abbreviations are all consistent.|
| Succinct    | Shorten the content to something meaningful and scannable, without sacrificing clarity. Delete unnecessary or vague wording like most adverbs. |


## Authentic

Inspire trust.

| ✔️ Be...     | How?                                                                               |
|-------------|------------------------------------------------------------------------------------|
| Optimistic   | Help users progress and succeed with what they are doing right now. Do not blame them in case of errors and instead let them know what to do and encourage actions.    |
| Confident   | Encourage best practices but let users choose their path. Provide them with just enough information to help them make informed decisions.         |
| Transparent | Help users connect the dots without jargon or vague statements. Provide values or realistic ranges to set the right expectations. For example "This operation can take up to 5 minutes" instead of "Wait a few minutes while we get you set up". |

---

### Packages Website Docs Content Word Choice (`packages/website/docs/content/word-choice.mdx`)

---
sidebar_position: 8
---

# Word choice

Find the right term to use in your UI copy.

## Use these preferred words and terms

Use these words and terms in the scenarios described in the following table:

| Word | Usage notes |
| ------- | ------------ |
| **add** | Use for establishing a new relationship. Often used in create-then-add scenarios. Create a dashboard, then add a visualization. In button labels, always follow _add_ by an object. Remove is the correct opposite. |
| **cancel** | Use to stop an action without saving pending changes. |
| **can't** | Use to indicate you don't have the ability to do something. Often confused with _unable_. |
| **create** | Use for creating an object from scratch. In button labels, always followed by an object. Do not use _create new_. Delete is the correct opposite. |
| **delete** | Use when deleting data that users can no longer retrieve. Create is the correct opposite. |
| **edit** | Don't use _change_ or _modify_. Edit is the better choice for localization. |
| **enter** | Use when the user enters text. Don't use _type_. |
| **later** | Use when referring to versions of the product. For example, Elastic Stack 8.13 and later.
| **open** | Use when opening an application or program. Don't use _launch_. |
| **press** | Use _press_ for keyboard keys. Don't use _hit_.
| **remove** | Use when removing a relationship, but not permanently deleting the data. For example, you remove a visualization from a dashboard. Add is the correct opposite. |
| **select** | _Select_ is preferred over _choose_. |
| **use**| Use instead of _utilize_ and _make use of_. |
| **view** | Use instead of _see_ because _view_ is more inclusive. |

## Avoid these words and terms

This section includes terms that you should avoid in most instances. These terms might be offensive, non-inclusive, unclear, or unnecessary.
Use the alternate suggestions in the following tables or a more specific term.

### Latin abbreviations

Latin abbreviations can be unclear.
Use the following suggestions instead:

| Word | Usage notes |
| ------- | ------------ |
| **e.g.** | Use _for example_ or _such as_ instead. |
| **i.e.** | Use _that is_ instead.|
| **via** | Use _with_, _by using_, or _through_ instead. |

### Directional language

Directional language does not meet accessibility requirements and you should avoid it, especially as the only way to find an element in the UI.
Use the following suggestions instead:

| Word | Usage notes |
| ------- | ------------ |
| **above** | Use a link, _previous_, or _preceding_ instead. |
| **below** | Use a link or _following_ instead|

### Nouns created from verbs

Avoid using nouns created from adjectives or verbs.
These words often make text unnecessarily complex.
For example:

- Use _choose_ instead of _make a choice_.
- Use _register_ instead of _complete your registration_.
- Use investigate instead of _conduct an investigation_.

### General words and terms to avoid

Avoid the following words and terms, and use the suggestions instead:

| Word | Usage notes |
| ------- | ------------ |
| **abort** |  Use _shut down,_ _cancel,_ or _stop_ instead. |
| **as well as** | Use _and_ instead. |
| **blacklist** | Use _blocked list_ instead. |
| **boot** | Use _start_ or _run_ instead. |
| **bottom left, bottom right** | Use _lower left_ or _lower right_ instead. Hyphenate when using as an adjective. For example, lower-left corner. |
| **choose** |  Use _select_ instead. See Words for interacting with UI|
| **disable** | Use _turn off_, _block_, or _hide_. |
| **enable** | Use _turn on_ or _allow_. |
| **easy**, **easily** | It can be frustrating for users to think that something is easy, but then struggle to do the task. Typically the same meaning can be conveyed without this word.|
| **execute** | Use _run_ or _start_ instead.|
| **hack** | For a noun, use _tip_ or _work-around_ instead. For a verb, use _configure_ or _modify_. |
| **hit** | For a noun, use _visits_ (as in web visits). For a verb, use _select_ or _press_.|
| **hear**, **hear about** | Use _learn_ instead. |
| **impact** | Don't use impact as a verb. Use _affect_ instead. |
| **in order to** | Use simple verbs like _to_ instead. |
| **invalid** | Use _not valid_ or _incorrect_ instead. |
| **just** | Don't use before a command, like "_just_ click here."
| **launch** | Use _open_ instead.  |
| **ok** | Don't use when labeling buttons. Use words that explain the action instead, for example, _Delete rule_. |
| **normal**, **normally** | Use _usual_ or _typical_ instead. For _normally_, use _usually_, _typically_, or _generally_ instead.
| **please** | In most cases, _please_ is unnecessary. Only use when the user must wait or do something inconvenient. |
| **simple**, **simply** | Unnecessary because it doesn't add any information or value.|
| **sorry** | Only use _sorry_ in error messages that cause serious problems for the user. |
| **success** | Unnecessary because _success_ is generally implied.  |
| **terminate** | Use _stop_ or _exit_ instead.|
| **type** | Use _enter_ because there is typically more than one way to enter text. |
| **top left, top right**| Use _upper left_ or _upper right_ instead. Hyphenate when using as an adjective. For example, upper-left corner. |
| **utilize** | Don't use _utilize_ when you mean _use_. |
| **whitelist** | Use _allow list_ instead. |

## Use caution with these words and terms

These words and terms might be appropriate in some situations and inappropriate in others.
Only use them when appropriate.

| Word | Usage notes |
| ------- | ------------ |
| **app**, **application**| Use only when needed for clarity. Otherwise, a Kibana application name can stand alone. App is a well-known abbreviation for application and is preferred. |
| **begin** | Use context to decide between _begin_ and _start_. For example, _begin a procedure_, _begin an analysis_, or _begin an installation_ are common phrases. Similarly, _start a program_, _start an engine_, or _start a timer_ are frequently used. _Start_ is considered less formal than _begin_. _End_ is the correct opposite of _begin_.|
| **can** | Use for capability. Rewrite as an action if possible. For example, instead of _you can add..._ use _add..._. |
| **click** | Acceptable to use when describing mouse actions. Otherwise, use verbs that work with multiple devices, such as _select_. |
| **clone** | Use when creating a copy that is linked to the original. Often confused with _copy_ and _duplicate_. |
| **copy** | Use when the file is added to a clipboard and can be pasted in a new location. Often confused with _clone_ and _duplicate_. |
| **disable** | Don't use to describe something that is broken. Use _inactive_, _unavailable_, _deactivate_, _turn off_, or _deselect_, depending on the context.|
| **duplicate** | Use when immediately creating a copy of an object in the same location as the original. Often confused with _copy_ and _clone_.  |
| **kill** | Use _cancel_ or _stop_ unless the actual command is `kill`. |
| **may** | Use _may_ for permissibility. Use _can_ for capability. Use _might_ for possibility. |
| **start** | Use context to decide between _start_ and _begin_. For example, _start a program_, _start an engine_, or _start a timer_ are common phrases. Similarly, _begin a procedure_, _begin an analysis_, or _begin an installation_ are frequently used. _Start_ is considered less formal than _begin_.|
| **unable** | Unable means not being able to perform an action. Often confused with _cannot_. |

---

### Packages Website Docs Dataviz Accessibility Features (`packages/website/docs/dataviz/accessibility-features.mdx`)

---
sidebar_position: 3
---

import useChartBaseThemeSource from '!raw-loader!./use_chart_base_theme';

# Accessibility features

import VersionBadge from './version_badge';

<VersionBadge />

```mdx-code-block
import * as ElasticCharts from '@elastic/charts';
import { useChartBaseTheme } from './use_chart_base_theme.ts';
```

Elastic Charts provides some accessibility features for all users.

**Available a11y-related features**

*   Chart titles
*   Chart descriptions
*   Chart data in tabular form\*
*   Texture fill\*
*   Semantic groupings\*

\*Not all chart types that may benefit from this feature have it implemented as of yet

## Titles

`ariaLabel` and `ariaLabelledBy` props can be set through the `<Settings />` component.

`ariaLabel` takes a string label which will be visually hidden whereas the`ariaLabelledBy` prop can tie the chart to other accessible elements elsewhere in your app.

```tsx
<>
  <h1 id="randomHeadingId">Days of the week: weekdays vs weekends</h1>
  <Chart>
    <Settings
      ariaLabelledby="randomHeadingId"
    />
    <BarSeries {...props} />
  </Chart>
</>
```

If using `ariaLabel`, you can set a heading level for it by passing in `ariaLabelHeadingLevel`. `h1` through `h6` are valid options (`p` is the default).

You may want to set a heading level if there are multiple charts on the page but you want to draw attention to a select few or if a specific chart is the main content of the page.

```tsx
<Chart>
  <Settings
    ariaLabel="Days of the week: weekdays vs weekends"
    ariaLabelHeadingLevel="h1"
  />
  <BarSeries {...props} />
</Chart>
```

## Descriptions

`ariaDescription` and `ariaDescribedBy` props can be set through the `<Settings />` component.`ariaDescription` takes a string description which will be visually hidden whereas `ariaDescribedBy` prop takes an `id` that you have rendered elsewhere in your app.

```tsx
<Chart>
  <Settings
    ariaLabel="Days of the week: weekdays vs weekends"
    ariaDescription="Bar one is labelled weekdays and has a value of 5. Bar two is labelled weekends and has a value of 2."
  />
  <BarSeries {...props} />
</Chart>
```

:::warning
`ariaDescribedBy` will override `ariaDescription` if both are specified.
:::

`ariaUseDefaultSummary` is a boolean defaulted to `true`. The default summary is bare bones and only reports the chart type(s). Some chart types provide more information but today that is only Gauge and Goal charts. If you are passing in a custom description, you can disable this prop.

```tsx
<>
  <h1 id="randomHeadingId">Days of the week: weekdays vs weekends</h1>
  <p id="randomDescId">Bar chart with two bars. Bar one is labelled weekdays and has a value of 5. Bar two is labelled weekends and has a value of 2.</p>
  <Chart>
    <Settings
      ariaLabelledby="randomHeadingId"
      ariaDescribedBy="randomDescId"
      ariaUseDefaultSummary={false}
    />
    <BarSeries {...props} />
  </Chart>
</>
```

## Tables

A visually hidden data table is rendered for some chart types. `ariaTableCaption` sets a custom caption on that table. Consider the table caption supplementary to the description. Use it to fill in any gaps that might be created when converting the chart to a tabular format.

:::note
In version 64.1.0, data tables are only available for **partition charts**.

Partition charts include: sunburst, treemap, icicle, flame, mosaic, and waffle.
:::

<Demo scope={{ ...ElasticCharts, useChartBaseTheme }} extraFiles={{ 'use_chart_base_theme.ts': useChartBaseThemeSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

For the provided example, a visually hidden data table is rendered with the caption we passed on `ariaTableCaption`.

```tsx
<p>There is a great variety of reported favorite fruit</p>

<dl>
  <dt>Chart type:</dt>
  <dd>sunburst chart</dd>
</dd>

<table>
  <caption>
    After Clementine (22), individual results are not labelled as the segments become too small
  </caption>
  <thead>
    <tr>
      <th scope="col">Label</th>
      <th scope="col">Value</th>
      <th scope="col">Percentage</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Apple</th>
      <td>100</td>
      <td>27%</td>
    </tr>
    {/* rows abbreviated */}
    <tr>
      <th>Durian</th>
      <td>1</td>
      <td>0%</td>
    </tr>
  </tbody>
</table>
```

## Texture fill

You can set a texture fill for charts with `TextureStyles` interface.

:::note
In version 64.1.0, texture fills are only available for **XY charts**.

XY charts include: area, bar, and histogram.
:::

<Demo scope={{ ...ElasticCharts, useChartBaseTheme }} extraFiles={{ 'use_chart_base_theme.ts': useChartBaseThemeSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Semantic groupings

You can add meaning to your color segments by using the `bandLabels` prop.

:::note
In version 64.1.0, semantic groupings are only available for **goal and gauge charts**.
:::

<Demo scope={{ ...ElasticCharts, useChartBaseTheme }} extraFiles={{ 'use_chart_base_theme.ts': useChartBaseThemeSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>
For the provided example, visually hidden content is rendered with a goal description list generated from the `bandLabels` prop.

```tsx
<p>Revenue 2020 YTD</p>
<p>(thousand USD</p>
<p>This goal chart has a target of 260.</p>
<dl>
  <dt>Chart type:</dt>
  <dd>horizontalBullet chart</dd>
  <dt>Minimum:</dt>
  <dd>0</dd>
  <dt>Maximum:</dt>
  <dd>300</dd>
  <dt>Target:</dt>
  <dd>260</dd>
  <dd>Value:</dd>
  <dt>280</dt>
</dl>
...
<dl class="echScreenReaderOnly echGoalDescription">
  <dt>0 - 100</dt>
  <dd>cold</dd>
  <dt>100 - 125</dt>
  <dd>brisk</dd>
  <dt>125 - 150</dt>
  <dd>warm</dd>
  <dt>150 - 250</dt>
  <dd>hot</dd>
</dl>
```

---

### Packages Website Docs Dataviz Dashboard Good Practices (`packages/website/docs/dataviz/dashboard-good-practices.mdx`)

---
sidebar_position: 2
---

import figmaDashboardGoodPracticesStructure from '!url-loader!./assets/dashboard-good-practices_structure.svg';
import figmaDashboardGoodPracticesClosure from '!url-loader!./assets/dashboard-good-practices_closure.svg';
import figmaDashboardGoodPracticesHierarchy from '!url-loader!./assets/dashboard-good-practices_hierarchy.svg';
import figmaDashboardGoodPracticesAspectRatio from '!url-loader!./assets/dashboard-good-practices_aspect-ratio.svg';
import figmaDashboardGoodPracticesPickTheRightChartModel from '!url-loader!./assets/dashboard-good-practices_pick-the-right-chart-model.svg';
import figmaDashboardGoodPracticesRelevance from '!url-loader!./assets/dashboard-good-practices_relevance.svg';
import figmaDashboardGoodPracticesTitles from '!url-loader!./assets/dashboard-good-practices_titles.svg';
import figmaDashboardGoodPracticesMargins from '!url-loader!./assets/dashboard-good-practices_margins.svg';

# Dashboard good practices

import VersionBadge from './version_badge';

<VersionBadge />

Dashboards are the most common way to monitor our own data, to be alerted of important events and to gather insights. They typically work combining different charts that might be completely unrelated as they can share the same data source from different points of view.

To understand the role of dashboards it's important to frame what they are and what is their function, to avoid using them in the wrong way. We will use the definition that Stephen Few uses in his “Information design dashboard”, where he states:

**A dashboard is a visual display of the most important information needed to
achieve one or more objectives; consolidated and arranged on a single screen
so the information can be monitored at a glance.**

It's important to learn how to get the best out of this tool, to do so we put together a series of high level principles that could help you to create a dashboard that leverages your data and facilitates its understanding.

NOTE: if you are looking for a practical guide of the functionalities of dashboards and a basic tutorial on how to handle them, have a look at this page: [Kibana Guide](https://www.elastic.co/guide/en/kibana/current/dashboard.html "Kibana Guide")

---

## Structure

A preliminary research conducted on dashboards made by Elastic customers showed a tendency to relate on one of the following templates when building a monitoring application. Unfortunately, we don't offer (yet) a simplified way to re-created on of these templates but we suggest to take inspiration from one of these four major categories when building your own dashboard, according to your needs and to the goal of your product.

<FigmaAsset
  url="https://www.figma.com/file/ljx7zNE8mIzGtXA39k4dMU/Dashboard-Good-Practices-%5B220%5D?type=design&node-id=1713-24059&mode=design&t=NfN1OtaqWM9sHBJN-4"
  src={figmaDashboardGoodPracticesStructure}
  title="Most common dashboard templates"
/>

---

## Context

A wide assumption in design is that everything depends on the context and dashboards are not different. Similar charts could work differently in different environments and therefore we should always try to understand as much as possible what kind of context we are working with.

To help this process you can try asking yourself questions like:

#### 1 / <u>Who is going to use this dashboard?</u>

Identifying your users is the most important thing that you have to do. This will help you understand how descriptive you have to be with title, charts typologies and explanation according to users skills and field knowledge.

#### 2 / <u>How much time will the users have?</u>

Dashboards should always be conceived for an immediate, clear and fast fruition. Don't overcomplicate it, give the users the information they need in the best and clearest way possible.

#### 3 / <u>What is the main goal of this dashboard and if there are, what are the secondary ones?</u>

This could help you identify your primary charts and how to build up a narrative that could go from primary to secondary charts, creating a comprehensive overview of the context.

#### 4 / <u>What kind of charts can help users identify insights in the most immediate and clear way?</u>

We know this is not a simple task and we are currently working on a proper series of guidance on how to choose a chart, our plan is to have a dedicated page for each chart typology where you will be able to find all the information needed to use it properly. In the meanwhile we can recommend two great resources that will help you decide what to do with a set of data. First, the chart classification made by dr. Andrew Abela is a classic in the determination of the best charts based on function. You can find it [here](https://flowingdata.com/wp-content/uploads/2009/01/chart-chart1.jpg?w=640 "Andrew Abela chart suggestions").
Second, this great archive made by the Danish design studio Ferdio helps you learn about charts and filter by purpose. You can find the archive [here](https://datavizproject.com/ "Ferdio Dataviz Project").

---

## Organization and hierarchy

Studies such as Gestalt show how the positioning of elements in space can define their belonging, with a certain degree this can be applied to dashboards.

### Closure

Charts that are related to the same typology of data or that are somehow connected by meaning should stay close together. When two related charts are placed away from each other the effort required of the user to move from one to the other could be too much, it's better to try to reduce this effort by putting them close together.

Sometimes they can also work together. In the following example we show how two Metric Charts could live next to a Line Chart that share a more detailed version of the same data.
As you can see the charts colors match, this way we can safely remove the legend from the line chart which is no longer necessary and we can have a wider understanding of the data.

<FigmaAsset
  url="https://www.figma.com/file/ljx7zNE8mIzGtXA39k4dMU/Dashboard-Good-Practices-%5B220%5D?type=design&node-id=1713-24245&mode=design&t=NfN1OtaqWM9sHBJN-4"
  src={figmaDashboardGoodPracticesClosure}
  title="Concept of closure for dashboard panels."
/>

### Hierarchy

There are two main concepts that you have to keep in mind when organizing charts in a dashboard:

<u>Reading Direction</u>

Most people are used to reading from top to bottom, this concept can be applied on dashboards as well. Place at the top of your page the most important charts and the ones that could give a brief and immediate summary of the context. A good general suggestion would be to increase the level of detail while you reach the bottom of the dashboard, this way users that are interested in getting all the information can obtain them without requiring too much effort from user that only need a quick glance of the situation.

<u>Central focal point</u>

Placing a big chart, especially with big visual shapes such as rectangles, at the center of the dashboard would help reinforce a natural visual focal point that lies in the center of the interface. As you can see in the following example, the barchart with blue bears is clearly the predominant piece of information and where we want the users to focus primarily.

Keep in mind these two concepts and use them according to your needs.

<FigmaAsset
  url="https://www.figma.com/file/ljx7zNE8mIzGtXA39k4dMU/Dashboard-Good-Practices-%5B220%5D?type=design&node-id=1732-43337&mode=design&t=NfN1OtaqWM9sHBJN-4"
  src={figmaDashboardGoodPracticesHierarchy}
  title="Concept of hierarchy for dashboard panels."
/>

### Rows

A simple and common practice to structure your dashboard would consist in dividing it into rows. Placing charts in rows would make them belong to “sections” and therefore they will be considered related among each other.
It's a good principle to follow when structuring a dashboard from top to bottom into different layers of detail and complexity.

## Aspect ratio

Within the data visualization field there have been multiple attempts to create a solid and unique rule to guide people in designing well proportioned charts. When is it ok to have an horizontal layout, how much can we shrink it without losing readability?

There is no universal answer to these questions and the rules that currently are shared among the data community are far too complex to be understood and correctly used by anybody. We believe that a high level concept could do the work in our case.

We suggest avoiding charts that are too narrow or too short, since we mainly deal with time series data and keep in mind that an horizontal proportion might be the best in showing trends and small variations.

There are as usual exceptions, some charts (e.g. scatterplot) might benefit from squared proportions, look for specific instructions on each chart's page.

<FigmaAsset
  url="https://www.figma.com/file/ljx7zNE8mIzGtXA39k4dMU/Dashboard-Good-Practices-%5B220%5D?type=design&node-id=1732-45544&mode=design&t=NfN1OtaqWM9sHBJN-4"
  src={figmaDashboardGoodPracticesAspectRatio}
  title="Different chart proportions."
/>

---

## Pick the right chart model

When creating a new chart please consider its implied features. In the following example we can see how the area chart on the left is hard to read when we have really small numbers. Lines that move diagonally tend to hide small numbers due to the oblique direction that they follow, a stacked barchart instead is way better in showing details such as the one described.

This is just an example useful to explain the concept and can be applied to several typologies of visualization, if you are stuck and don't know which chart to pick please feel free to reach out to the datavis team.

<FigmaAsset
  url="https://www.figma.com/file/ljx7zNE8mIzGtXA39k4dMU/Dashboard-Good-Practices-%5B220%5D?type=design&node-id=1701-19998&mode=design&t=NfN1OtaqWM9sHBJN-4"
  src={figmaDashboardGoodPracticesPickTheRightChartModel}
  title="Good and bad example of correct chart according to context."
/>

---

## Colors

#### Consistency

The most important thing to keep in mind is that the best option is always to stick with the guidelines provided by our EUI. Colors provided there for visualization have been tested for accessibility contrast and using them you would be sure to properly serve the biggest audience. You can find this documentation [here](https://eui.elastic.co/docs/dataviz/ "EUI Charts page")

In addition to that, following these guidelines you'll be sure to get a consistent interface that will work perfectly with all other solutions.

#### Relevance

If your dashboard is made to identify specific behaviors it might be interesting to consider a color setting that could help pointing it out. Use a neutral color for generic elements and an accent one for the things that you are looking for.

<FigmaAsset
  url="https://www.figma.com/file/ljx7zNE8mIzGtXA39k4dMU/Dashboard-Good-Practices-%5B220%5D?type=design&node-id=1732-43797&mode=design&t=NfN1OtaqWM9sHBJN-4"
  src={figmaDashboardGoodPracticesRelevance}
  title="Use of color to highlight specific element."
/>

#### Custom brands

Sometimes it happens that a dashboard needs to be customized according to a client brand identity. When so, be cautious and pick really few colors to work with, try to make the charts consistent among each other and don't forget about accessibility.

If you want to go deeper and study how to work with colors, consider reading [this](https://blog.datawrapper.de/colors-for-data-vis-style-guides/ "Colors for data vis styleguides") great summary by Lisa Charlotte Muth from Datawrapper.

---

## Titles, labels and margins

### Titles

Titles can have a strong visual impact on dashboards, especially when there are a lot of small charts. Two principles can generally be followed:

<ol>
    <li>
        remove unnecessary or repetitive titles when the information is already
        explained or written within the chart (e.g. Metric Charts)
    </li>
    <li>
        when title is needed make it self explanatory and exhaustive, this way
        you will be able to remove axis titles and other specifications leaving
        more space for the charts itself.
    </li>
</ol>

<FigmaAsset
  url="https://www.figma.com/file/ljx7zNE8mIzGtXA39k4dMU/Dashboard-Good-Practices-%5B220%5D?type=design&node-id=1732-45159&mode=design&t=NfN1OtaqWM9sHBJN-4"
  src={figmaDashboardGoodPracticesTitles}
  title="Good and bad use of titles in panels."
/>

### Margins

Kibana dashboards offer the possibility to apply margins between chart panels, we would suggest to always do that.
Margins create separation between charts which is an important visual feature, it helps identifying when two elements belong together or not while, at the same time, they provide more spacing and empty spaces that are always useful in making our interface more clean and elegant.

Using margins will also automatically apply little shadows to panels, this will make them stand out from the background.

<FigmaAsset
  url="https://www.figma.com/file/ljx7zNE8mIzGtXA39k4dMU/Dashboard-Good-Practices-%5B220%5D?type=design&node-id=1732-45435&mode=design&t=NfN1OtaqWM9sHBJN-4"
  src={figmaDashboardGoodPracticesMargins}
  title="Example of panels with and without margins"
/>

### Labels, numbers and formatting

<ol>
    <li>
        Reduce the number of decimal places to the absolutely necessary ones.
        Use tables whenever you need precise numbers.
    </li>
    <li>
        If possible, remove redundant labels. If we are talking about Usage
        metrics, then you can easily remove the Usage word used across 7 charts
        out of 8 charts in the prev example.
    </li>
</ol>

---

## Lens

Always use Lens, when possible. There are still a few functionalities that you might not find in Lens (within [this document](https://docs.google.com/document/d/1uyyFGx6xA5Kvl8c-ZdvXdvBGrHTylxU9F69TGqfzdmw/edit?usp=sharing "Integration dashboard best practices") you can learn more about them) but everything is gradually moving into this application.
It's the best choice to be consistent and up to date and it should always be your first choice when creating new visualizations.

---

### Packages Website Docs Dataviz Sizing (`packages/website/docs/dataviz/sizing.mdx`)

---
sidebar_position: 5
---

import useChartBaseThemeSource from '!raw-loader!./use_chart_base_theme';

# Sizing

import VersionBadge from './version_badge';

<VersionBadge />

When placing charts into smaller containers or panels, you must re-evaluate your data to provide a more simplified version. This could be as simple as shifting legend positions from the right side to the bottom or adding annotations to give context and describe the key points in your data.

```mdx-code-block
import { Sizes } from './sizes';
import BrowserOnly from '@docusaurus/BrowserOnly';
```

<BrowserOnly>
  {() => <Sizes />}
</BrowserOnly>

## Sparklines

Sparklines are quick visual summaries of data where actual values are not important. They should be only a single series and not contain more than 12 values. Be sure to remove all extraneous markings like ticks, labels, tooltips and grid. The surrounding content should give context to the sparkline.

EUI also provides a quick theme alteration object that you can merge with the correct dark or light theme to properly style your sparklines.

```tsx
import { DARK_THEME, LIGHT_THEME } from '@elastic/charts';

const MyChart = () => {
  const sparklineOverrides = chartsPlugin.theme.useSparklineOverrides(); // requires kibana charts plugin
  const chartBaseTheme = isDarkTheme ? DARK_THEME : LIGHT_THEME;
  return (
    <Chart>
      <Settings baseTheme={chartBaseTheme} theme={sparklineOverrides} />
      //...
    </Chart>
  );
};
```

**Other key configurations**

*   `Settings.showLegend = false`
*   `Tooltip.type = "none"`

```mdx-code-block
import * as ElasticCharts from '@elastic/charts';
import { useChartBaseTheme } from './use_chart_base_theme';
```

<Demo scope={{ ...ElasticCharts, useChartBaseTheme }} extraFiles={{ 'use_chart_base_theme.ts': useChartBaseThemeSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

---

### Packages Website Docs Dataviz Theming (`packages/website/docs/dataviz/theming.mdx`)

---
sidebar_position: 6
---

import useChartBaseThemeSource from '!raw-loader!./use_chart_base_theme';

# Theming

import VersionBadge from './version_badge';

<VersionBadge />

```mdx-code-block
import { useChartBaseTheme } from './use_chart_base_theme';
import * as ElasticCharts from '@elastic/charts';
```

EUI provides both light and dark theme files to use in tandem with Elastic Charts. Simply import these objects from the themes folder and pass the correct one to the Settings.theme property.

```tsx
import { DARK_THEME, LIGHT_THEME } from '@elastic/charts';

const chartBaseTheme = isDarkTheme ? DARK_THEME : LIGHT_THEME;

<Settings baseTheme={chartBaseTheme} />
```

:::note Kibana engineers

EUI provides a plugin utility for ease of pulling in the correct theme object depending on the current Kibana theme. Learn more from this [readme](https://github.com/elastic/kibana/tree/main/src/platform/plugins/shared/charts).

:::

EUI also provides some basic [color palettes and functions](../utilities/color-palettes/index.mdx) if you would like to change the default color blind safe scheme to another palette. You can import these from the services folder. Create a new partial theme object with your chosen colors and prepend it to the list of themes supplied to Settings.

```tsx
import { DARK_THEME, LIGHT_THEME } from '@elastic/charts';
import { euiPaletteGreen } from '../../../../src/services';

const MyChart = () => {
  const customColors = {
    colors: {
      vizColors: euiPaletteGreen(5),
    },
  };
  const chartBaseTheme = isDarkTheme ? DARK_THEME : LIGHT_THEME;
  return (
    <Chart>
      <Settings baseTheme={chartBaseTheme} theme={customColors} />
      //...
    </Chart>
  );
};
```

You'll find an example of these in the demo below.

<Demo scope={{ ...ElasticCharts, useChartBaseTheme }} extraFiles={{ 'use_chart_base_theme.ts': useChartBaseThemeSource }}>
  ```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Coloring charts

**Use color to distinguish categories, represent quantity/density, and highlight data. When using color in this way, be aware that too many colors in a single chart can create noise and hinder quick comprehension.**

When creating a multi-series chart where each series shows **contrasting** data, use the color blind safe palette of contrasting colors. This will also avoid implying levels of magnitude.

Think about the data you are delivering and if there is a way to **highlight** key indicators. If you can combine the series into logical groups, use contrasting shapes and styles, but keep the same color for within groups.

### Quantity vs trends

When coloring for sequential series data (not categorical), rely on conventions. If the data signifies **quantities**, use a single color that spans from light colors for low amounts to dark colors for high amounts. If the data signifies **trends**, use a two-color divergent scheme, with the darkest colors at the extremes.

When signifying quantities, group values into intervals instead of a continuous gradient scale.

```mdx-code-block
import { Categorical } from './types/categorical';
```

<Categorical />

---

### Packages Website Docs Getting Started Accessibility (`packages/website/docs/getting-started/accessibility.mdx`)

---
sidebar_label: Accessibility
sidebar_position: 4
---

# Accessibility guidelines

```mdx-code-block
import Link from '@docusaurus/Link';
import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
```

:::info Check component-level guidance

This page provides some general accessibility guidelines. For component specific recommendations, be sure to check out their individual documentation pages.

:::

EUI provides a strong start to building accessibility into your apps. The components provided strive to meet <Link to="https://www.w3.org/TR/WCAG21/">WCAG 2.1</Link> guidelines on semantics, keyboard functionality, color contrast, and so on. How you stitch together these components in the overall page structure also plays a large role in meeting accessibility goals. Headings, landmarks, page titles, focus management, and accessible names all work together to create accessible apps.

Building accessibility into your app is as important as code quality, visual design, and performance, and it’s also important that you test as you go. You can approach accessibility testing from three dimensions: automated, manual, and empathetic thinking. Use automated tests to quickly cover as much ground as possible, manual tests to address more complicated scenarios, and empathy to fill in the gaps.

For a technical intro to accessibility and how EUI tackles it

import { EuiAspectRatio } from '@elastic/eui';

<EuiAspectRatio width={16} height={9}>
  <iframe
    src="https://www.youtube.com/embed/iDXoEe8NkrE?si=qsx1lihTqUnJ2RYT"
    title="Building and testing accessibility with EUI video on YouTube"
    frameBorder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerPolicy="strict-origin-when-cross-origin"
    allowFullScreen
  />
</EuiAspectRatio>

## Headings and landmarks

You can aid navigation and make pages more accessible for screen reader users by using solid headings and landmarks. **Headings** are the simplest way for screen readers to navigate pages. A good heading hierarchy:

- Uses only one `<h1>` on each page
- Doesn't skip levels `<h1> → <h6>`
- Doesn't duplicate content

### Heading examples

<EuiFlexGroup gutterSize="m">
  <Guideline type="do" panelPadding="none" text="Descend through headings as you work your way through the document.">
    ```tsx
    <EuiText>
      <h1>Discover your data</h1>
      <p>Some content</p>
      <h2>Drill into site metrics</h2>
      <h3>An important site metric</h3>
      <h3>Another important site metric</h3>
    </EuiText>
    ```
  </Guideline>
  <Guideline type="dont" panelPadding="none" text="This heading hierarchy is confusing. Also EuiText is not a good solution when you need to change heading presentation.">
    ```tsx
    <EuiText>
      <EuiScreenReaderOnly>
        <h1>Discover your data</h1>
      </EuiScreenReaderOnly>
      <p>Some content</p>
      <h2>Discover your data</h2>
      
      <h4 className="myLargeTitle">
        An important site metric
      </h4>
    </EuiText>
    ```
  </Guideline>
</EuiFlexGroup>


:::tip
[**EuiTitle**](../components/display/title.mdx) gives you a way to separate your presentation from your semantic markup.
:::

<Guideline type="do" panelPadding="none" text="This is a good heading hierarchy. Though visible headings are certainly better, sometimes that is difficult to accommodate so hidden headings can give additional context.">
  ```tsx
  <EuiTitle size="s"><h1>Discover your data</h1></EuiTitle>
  <EuiScreenReaderOnly><h2>Drill into site metrics</h2></EuiScreenReaderOnly>
  <EuiTitle size="l"><h3>An important site metric</h3></EuiTitle>
  <EuiTitle size="m"><h3>Another important site metric</h3></EuiTitle>
  ```
</Guideline>

**Landmarks** are another way for screen readers to navigate pages. A benefit of landmarks is that they offer more context on the type of content to expect than a heading. This is useful for tech that offers reader modes (e.g., Firefox, Safari, and apps like Pocket) and new form factors (e.g., smartwatches). Many landmarks are mapped to HTML elements, such as `<main>`, `<aside>`, `<article>`; others are exposed through the `role` attribute.

You can implement named landmarks with `aria-label` or `aria-labelledby`. However, having a heading inside of the landmark (even if it is visually hidden) and referenced by `aria-labelledby` is preferred.

### Landmarks example

<EuiFlexGroup gutterSize="m">
  <Guideline type="do" panelPadding="none" text="Use HTML5 elements which convey semantic meaning about their purpose. Notice that all of the content is inside of semantic elements.">
    ```tsx
    <body>
      <header className="appHeader">
        
      </header>
      <main></main>
      <footer className="appFooter">
        
      </footer>
    </body>
    ```
  </Guideline>
  <Guideline type="dont" panelPadding="none" text="Classes provide no semantic meaning and not all elements provide semantic meaning either.">
    ```tsx
    <body>
      <div className="appHeader"></div>
      <discover-app></discover-app>
      <ul className="appFooter"></ul>
    </body>
    ```
  </Guideline>
</EuiFlexGroup>

### Headings and named landmarks example

<Guideline type="do" panelPadding="none" text="Use landmarks and headings together to build complex pages.">
  ```html
  <header aria-labelledby="pageHeading">
    <h1 id="pageHeading">Discover your data</h1>
    <form role="search" aria-label="Site search">  </form>
  <header>
  <main aria-labelledby="contentHeading">
    <h2 id="contentHeading">Drill into site metrics</h2>
    <form role="search" aria-label="Search your data">
      
    </form>
  </main>
  ```
</Guideline>

### Further reading

- <Link to="https://www.w3.org/TR/wai-aria-practices/examples/landmarks/HTML5.html">W3C: Aria Landmarks</Link>
- <Link to="https://www.w3.org/WAI/tutorials/page-structure/">W3C: Page Structure Concepts Tutorial</Link>
- <Link to="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML#Good_semantics">MDN: Good Semantics</Link>
- <Link to="https://www.upyoura11y.com/page-layout/">Up Your A11y: Accessible Page Layouts</Link>
- <Link to="https://www.upyoura11y.com/reusable-components-with-headers/">Up Your A11y: Heading Levels in Reusable Components</Link>

## Page titles

Each page requires a unique, informative title that accurately reflects what the page does. The best page titles put the unique content first. Effectively, they're reverse-order breadcrumbs.

**<Icon type="checkCircleFill" color="success" size="l" /> Use this format:** `{Unique page title} - {Site title}`

<Guideline type="do" panelPadding="l" text="These are good example of page titles.">
  **Discover - Kibana**

  **Rollup Jobs - Management - Kibana**
</Guideline>

<Guideline
  type="dont"
  panelPadding="l"
  text={
    <>
      <GuidelineText type="dont">
        Though unique, this does not provide enough context.
      </GuidelineText>
      <GuidelineText type="do">
        Watchers - Management - Kibana
      </GuidelineText>
    </>
  }
>
  **Watchers**
</Guideline>

<Guideline
  type="dont"
  panelPadding="l"
  text={
    <>
      <GuidelineText type="dont">
        Although it provides all the context, putting the most important bit at the end is hard to find.
      </GuidelineText>
      <GuidelineText type="do">
        Spaces - Management - Kibana
      </GuidelineText>
    </>
  }
>
  **Elastic Kibana - Spaces**
</Guideline>

<Guideline
  type="dont"
  panelPadding="l"
  text={
    <>
      <GuidelineText type="dont">
        Although this provides all the context and in a good order, a title is not the place for any extra words.
      </GuidelineText>
      <GuidelineText type="do">
        Reporting - Management - Kibana
      </GuidelineText>
    </>
  }
>
  **This is the Reporting page of the Management section of Kibana.**
</Guideline>

### Further reading

- <Link to="https://www.w3.org/WAI/WCAG21/quickref/?showtechniques=242#page-titled">WCAG 2.4.2 Page Titled - Level A</Link>

## Focus management

### Where is the focus state right now?

Focus states are an important part of design because they let keyboard users know where focus is currently at. All browsers ship with focus states for interactive elements, and most of the time you shouldn’t need to alter these. EUI goes further to customize focus states to match the Elastic brand and provide better visual states, including color contrast.

### Where is the focus state going?

Given that a keyboard user primarily navigates pages in one direction (either forward or backward), it’s important to have an intuitive focus order. Focus order should follow the flow of the page to make it easy to follow. If you’ve made a normally non-interactive element like a `<div>` interactive via JavaScript, you can enable a tab stop using `tabIndex=0`. If you want something that is only focusable programmatically, you can use `tabIndex=-1`.

:::danger
Using `tabIndex` values greater than 0 is problematic and should be avoided.
:::

### How do I get back to where I was?

Navigating complex sites sometimes means your focus state will jump around (e.g., skip links, modals, typeahead, and so on). If you remove an element that currently has focus without setting focus anywhere else, users start over at the beginning of the page. Unless there’s a strong reason to do otherwise, focus state should always return to where it was previously if the currently focused element disappears. For example, closing a modal might mean your focus is on a close button; when the modal closes, you should return focus to the button that opened the modal.

### Further reading

- <Link to="https://www.w3.org/WAI/perspective-videos/keyboard">W3C: Keyboard Compatibility</Link>
- <Link to="https://reactjs.org/docs/accessibility.html#programmatically-managing-focus">React docs: Programmatically managing focus</Link>
- <Link to="https://developer.mozilla.org/en-US/docs/Web/Accessibility/Keyboard-navigable_JavaScript_widgets">MDN: Keyboard-navigable JavaScript widgets</Link>
- <Link to="https://webaim.org/techniques/keyboard">WebAIM: Keyboard Accessibility</Link>
- <Link to="https://www.upyoura11y.com/screen-reader-keyboard-navigation">Up Your A11y: Getting Started with Keyboard Navigation and Screen Readers</Link>
- <Link to="https://tink.uk/the-difference-between-keyboard-and-screen-reader-navigation/">The difference between keyboard and screen reader navigation</Link>

## Disabled elements

Browsers remove disabled elements from the tab order. This means keyboard users cannot tab to those elements or activate nested focus behaviors.

If you disable a button or form element, you need to provide clear instructions to users how to correct errors or remove the disabled state.

When you add the HTML `disabled` attribute to an element, you must remove tooltips or other focus interactions. You must also remove focus interactions if you pass the `isDisabled` prop to components like [EuiAccordion](../components/containers/accordion.mdx#disabled-state).

### Further reading

- <Link to="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex">MDN: Tabindex</Link>
- <Link to="https://www.w3.org/TR/2014/REC-html5-20141028/disabled-elements.html#disabled-elements">W3C: Disabled elements</Link>

## Naming

An accessible name is the name of an HTML element as it’s exposed to assistive technology. An accessible name can then be read by a screen reader or can be targeted for an action.

### Most elements

For most content, the accessible name comes from the element’s inner text, such as: `<a href="https://elastic.co">Elastic.co</a>`. A screen reader can now read it out something like “Elastic.co, link” or, using voice commands, it can be controlled with “Click Elastic.co link”.

### Images and other elements

Some content might require special attributes to give an element an accessible name. For images, you can use `alt` attributes, such as:

```
<img src="image1.jpg" alt="An apple lays on a table">
```

### Buttons without inner text

For buttons without descriptive text content, you can rely on ARIA to bring meaning back:

```
<button aria-label="Close modal">Ｘ</button>
```

### Forms and more complex patterns

Some HTML elements have associated elements that provide accessible names. Form elements are the most ubiquitous example: a checkbox doesn’t have a name by itself, but when it is associated with a label, assistive technologies can make the connection:

```
<input type="checkbox" id="subscribe">
<label for="subscribe">Subscribe to Elastic news</label>
```

### Of note: Repeated calls to action

Having only an accessible name, however, doesn’t always lead to the best UX. Take a list of available fields that someone might want to add to their filter (say, on the discovery page of a popular open source project):

```
<h3>Available fields</h3>
<ul>
  <li>
    @timestamp
    <button>add</button>
  </li>
  <li>
    _id
    <button>add</button>
  </li>
  <li>
    _index
    <button>add</button>
  </li>
</ul>
```

Here, the 3 buttons have the same accessible name. There are a few different patterns you can use to differentiate between repeated items. For example, each button below shows a possible pattern you can use (in order of recommended best practice):

```
<h3 id="available">Available fields</h3>
<ul aria-labelledby="available">
  <li>
    _id
    <button aria-label="add _id field to your current filter">
      add
    </button>
  </li>

  

  <li>
    @timestamp
    <button>
      add
      <EuiScreenReaderOnly>
        @timestamp field to your current filter
      </EuiScreenReaderOnly>
    </button>
  </li>

  <li>
    
    <span id="filed3">_index</span>
    <button id="button3" aria-labelledby="button3 field3">add</button>
  </li>
</ul>
```

:::tip Give lists an accessible label to improve their discoverability!
```

<h1 id="a1b2c3">My favorite fruit</h1>
<ul aria-labelledby="a1b2c3"></ul>


<ul aria-label="My favorite vegetables">...</ul>
```
:::

### Further reading

- <Link to="https://www.w3.org/WAI/tutorials/forms/labels/">W3c: Labeling Controls</Link>
- <Link to="https://developer.paciellogroup.com/blog/2017/04/what-is-an-accessible-name">The Paciello Group: What is an accessible name?</Link>
- <Link to="https://webaim.org/techniques/forms/controls">WebAIM: Creating Accessible Forms</Link>
- <Link to="https://hacks.mozilla.org/2019/06/how-accessibility-trees-inform-assistive-tech">Mozilla: How accessibility trees inform assistive tech</Link>
- <Link to="https://alistapart.com/article/semantics-to-screen-readers">A List Apart: Semantics to Screen Readers</Link>

## Testing considerations

There are a lot of aspects to accessibility, and covering all the bases can be a lot to keep in mind. By relying on standards, you can minimize the amount of special casing you have to do in code, but you should still be cognizant of the many modalities in which users might use your products.

### Low-vision

While low-vision users may use many assistive technologies in tandem, this section focuses on zooming. Two ways that users can zoom the page are by increasing the base font-size with browser tools or by using a 3rd-party magnifier (sometimes, a physical magnifier) to better see the screen.

<Link to="https://www.w3.org/WAI/WCAG21/quickref/#resize-text">WCAG 1.4.4</Link> defines 200% browser zoom should continue to work with no further action from the user as a Level AA criteria.

<Link to="https://www.youtube.com/watch?v=QjKG4Tx9ER8&t=473s">ZoomText</Link> is the most popular 3rd-party magnifier that gives users a window they can drag over content to magnify and read it out loud. Testing for the best experiences here is exceptionally difficult because you must make visual judgement calls. Specifically, related pieces of information should be close enough together for a low-vision user to efficiently interact with the UI.

### Low-vision/blind (screen readers)

Blind and low-vision users often rely on tools, such as screen readers and braille readers, to navigate the web. Screen and braille readers read the page from top to bottom. Building a page with a good structure, will make it quick and easy to navigate. Braille readers are a textual representation of what a screen reader would say so we can focus on screen reader compatibility.

The 3 most common, desktop, screen readers, and their most common browser pairings are:

- JAWS with Chrome
- NVDA with Firefox
- VoiceOver with Safari

Mobile is a little simpler:

- VoiceOver for iOS
- TalkBack for Android

- <Link to="https://www.apple.com/voiceover/info/guide/_1124.html">Apple docs: Learning VoiceOver Basics</Link>
- <Link to="https://webaim.org/articles/voiceover">WebAIM: Using VoiceOver to Evaluate Web Accessibility</Link>
- <Link to="https://webaim.org/articles/nvda">WebAIM: Using NVDA to Evaluate Web Accessibility</Link>
- <Link to="https://webaim.org/articles/jaws">WebAIM: Using JAWS to Evaluate Web Accessibility</Link>
- <Link to="http://uncaughtreferenceerror.com/a-crash-course-to-screenreaders-for-sighted-developers">An Intro To Screen Reader Testing for Sighted Developers</Link>

## Learning resources

- A wide-reaching <Link to="https://developer.mozilla.org/en-US/docs/Learn/Accessibility">guide on accessibility on MDN</Link> covering basics and best practices for a variety of subjects
- The <Link to="https://a11ysupport.io">caniuse of ARIA attributes: Accessibility support</Link>
- <Link to="https://developers.google.com/web/fundamentals/accessibility">Accessibility web fundamentals by Google</Link>, similar in content to the MDN guide, but more guided
- If you prefer videos to reading, a great “pick your subject” style series <Link to="https://www.youtube.com/playlist?list=PLNYkxOF6rcICWx0C9LVWWVqvHlYJyqw7g">A11ycasts</Link> is available

### Practical examples

For many things, there’s no need to reinvent the wheel. If your component is featured in one of these two sources, feel free to borrow heavily!

- <Link to="https://inclusive-components.design">Inclusive Components</Link>
- <Link to="https://github.com/scottaohara/accessible_components">Accessible Components</Link>

### Tooling

- Axe plugin for <Link to="https://chrome.google.com/webstore/detail/axe/lhdoppojpmngadmnindnejefpokejbdd">Chrome</Link> and <Link to="https://addons.mozilla.org/en-US/firefox/addon/axe-devtools">FF</Link>

### Spec docs

- <Link to="https://www.w3.org/TR/using-aria">Using ARIA</Link>
- <Link to="https://www.w3.org/TR/WCAG21">WCAG 2.1</Link>
- <Link to="https://www.w3.org/WAI/WCAG21/quickref">How to Meet WCAG (Quick Reference)</Link>
- <Link to="https://www.w3.org/TR/wai-aria-1.1">WAI ARIA 1.1</Link>


[def]: https://www.upyoura11y.com/reusable-components-with-headers/

---

### Packages Website Docs Getting Started Setup (`packages/website/docs/getting-started/setup.mdx`)

---
sidebar_position: 1
---

# Setup

import Link from '@docusaurus/Link';

## Installation

EUI is published through <Link to="https://www.npmjs.com/package/@elastic/eui">NPM</Link> as a dependency. To install EUI into an existing project, use the `yarn` CLI (`npm` is not supported).

```bash
yarn add @elastic/eui
```

Note that EUI has <Link to="https://github.com/elastic/eui/blob/main/packages/eui/package.json">several `peerDependencies` requirements</Link> that will also need to be installed when starting with a blank project.

```bash
yarn add @elastic/eui @elastic/eui-theme-borealis @elastic/datemath @emotion/react @emotion/css moment
```

You can read more about other ways to <Link to="https://github.com/elastic/eui/blob/main/wiki/consuming-eui/">consume EUI</Link> in our wiki.

## Supported environments

EUI is designed to work in the following environments:

```mdx-code-block
import { EuiTable, EuiTableHeader, EuiTableHeaderCell, EuiTableBody, EuiTableRow, EuiTableRowCell } from '@elastic/eui';
import { css } from '@emotion/react';
```

<EuiTable>
  <EuiTableHeader>
    <EuiTableHeaderCell>Environment</EuiTableHeaderCell>
    <EuiTableHeaderCell align="center">Supported?</EuiTableHeaderCell>
    <EuiTableHeaderCell>Details</EuiTableHeaderCell>
  </EuiTableHeader>
  <EuiTableBody>
    
    <EuiTableRow>
      <EuiTableRowCell>React 16</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell>
        Support ended with EUI v106.0.0. Please upgrade to a modern React version.
      </EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>React 17</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell>Fully supported</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>React 18</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell>Fully supported (recommended)</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>React 19</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell>
        Not supported (plans to <Link href="https://github.com/elastic/eui/issues/8720">introduce support for React 19</Link>)
      </EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Webpack</EuiTableRowCell>
      <EuiTableRowCell align="center">✅</EuiTableRowCell>
      <EuiTableRowCell>Fully supported</EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Vite/Rollup/Parcel/esbuild</EuiTableRowCell>
      <EuiTableRowCell align="center">⚠️</EuiTableRowCell>
      <EuiTableRowCell>
        Supported with caveats (<Link href="https://github.com/elastic/eui/issues/7630">details</Link>)
      </EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Strict Mode</EuiTableRowCell>
      <EuiTableRowCell align="center">❌</EuiTableRowCell>
      <EuiTableRowCell>
        Not supported (<Link href="https://github.com/elastic/eui/issues/7774">details</Link>)
      </EuiTableRowCell>
    </EuiTableRow>
    <EuiTableRow>
      <EuiTableRowCell>Server-side Rendering</EuiTableRowCell>
      <EuiTableRowCell align="center">⚠️</EuiTableRowCell>
      <EuiTableRowCell>
        Supported with caveats (<Link href="https://github.com/elastic/eui/issues/5419">details</Link>)
      </EuiTableRowCell>
    </EuiTableRow>
  </EuiTableBody>
</EuiTable>

If you have questions about your environment or run into issues, please open a [GitHub issue](https://github.com/elastic/eui/issues/new/choose) or start a [discussion](https://github.com/elastic/eui/discussions/new/choose).

## Setting up your application

EUI uses CSS-in-JS (specifically <Link to="https://emotion.sh/">Emotion</Link>) for its styles and theming. As such, we require an `<EuiProvider>` wrapper around your application in order for various theme-related UI & UX (such as dark/light mode switching) to work as expected.

```tsx
import React from 'react';

import { EuiProvider, EuiText } from '@elastic/eui';

const MyApp = () => (
  <EuiProvider>
    <EuiText><p>Hello World!</p></EuiText>
  </EuiProvider>
);

export default MyApp;
```

For more configuration options of the provider, see the [**EuiProvider** documentation](../utilities/provider.mdx).

## Styling your application

You can build custom components using EUI's theme tokens, consumed via `useEuiTheme()`. The below example uses Emotion's `css` prop, but any CSS-in-JS library should be able to interpolate the JS variables.

For more ways to consume EUI's theme, see the [**EuiThemeProvider** documentation](./theming/theme-provider.mdx#consuming-with-the-react-hook).

```tsx
import React from 'react';
import { EuiIcon, EuiCode, EuiText, useEuiTheme } from '@elastic/eui';
import { css } from '@emotion/react';

export default () => {
  const { euiTheme } = useEuiTheme();

  return (
    <EuiText>
      <p>
        <EuiIcon
          type="stopFill"
          size="xxl"
          css={{ color: euiTheme.colors.primary }}
        />{' '}
        This primary color will adjust based on the light or dark theme value
      </p>

      <p
        css={css`
          background: ${euiTheme.colors.lightShade};
          padding: calc(${euiTheme.size.base} * 2);
        `}
      >
        The padding of this box is created using <EuiCode>calc()</EuiCode>{' '}
        because EUI&apos;s theme sizes are string pixel values that are
        calculated off the theme&apos;s <EuiCode>base</EuiCode>
      </p>
    </EuiText>
  );
};
```

### Customizing with classes

For consumers using vanilla or preprocessed CSS, all components allow you to pass a custom `className` prop, which will be appended onto the component.

:::warning Avoid overwriting `.eui` class names

EUI's class names are not a guaranteed API and are prone to change, which will risk breaking your theme. Target your custom classNames instead.

:::

While EUI's styles are generally low in <Link to="https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity">specificity</Link> due to our usage of CSS-in-JS, you may need to ensure that your CSS is defined after ours in your `<head>`. See [**EuiProvider's** cache customization for more style injection options](../utilities/provider.mdx#emotioncache-customization).

```tsx
import React from 'react';
import { EuiButton } from '@elastic/eui';

const myCustomCSS = `
  .myCustomButton {
    background-color: pink;
  }
`;

export default () => (
  <>
    <style>{myCustomCSS}</style>
    <EuiButton className="myCustomButton">Hello world!</EuiButton>
  </>
);
```

### Customizing the style tokens

EUI can be slightly customized to fit your branding needs by altering the base tokens like color and typography. You can pass a full or partial list of override tokens to the **EuiProvider**'s `modify` prop.

:::warning Touch the least amount of variables possible

By nature, EUI is very rigid. You shouldn't need much to make drastic changes to color. Most themes are less then a dozen variable overwrites in total.

:::

For more examples of the `modify` prop, see the [**EuiThemeProvider** docs](./theming/theme-provider.mdx#simple-instance-overrides).

```tsx
import React, { FunctionComponent, ReactNode } from 'react';
import { EuiCode, EuiText, EuiThemeProvider, useEuiTheme } from '@elastic/eui';

const Box: FunctionComponent<{ children: ReactNode }> = ({ children }) => {
  const { euiTheme } = useEuiTheme();

  return (
    <EuiText
      css={{
        background: euiTheme.colors.lightShade,
        padding: euiTheme.size.xl,
      }}
    >
      <p>{children}</p>
    </EuiText>
  );
};

export default () => {
  const overrides = {
    colors: {
      LIGHT: { lightShade: '#d3e6df' },
      DARK: { lightShade: '#394c4b' },
    },
  };

  return (
    <div>
      <EuiThemeProvider modify={overrides}>
        <Box>
          The background of this box is using the locally overridden value of{' '}
          <EuiCode>euiTheme.colors.lightShade</EuiCode>
        </Box>
      </EuiThemeProvider>
    </div>
  );
};
```

## Fonts

By default, EUI ships with a font stack that includes some outside, open source fonts. If your system is internet available you can include these by adding the following imports to your SCSS/CSS files, otherwise you'll need to bundle the physical fonts in your build. EUI will drop to System Fonts (which you may prefer) in their absence.

```html
<link
  href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@300;400;500;600;700&family=Roboto+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap"
  rel="stylesheet"
/>
```

Or grab all weights, including italics, between 400 and 700 as a variable font.

```html
<link
  href="https://fonts.googleapis.com/css2?family=Inter:slnt,wght@-10,300..700;0,300..700&family=Roboto+Mono:ital,wght@0,400..700;1,400..700&display=swap"
  rel="stylesheet"
/>
```

### Embedding with `@font-face`

If your application doesn't allow grabbing the font assets from a CDN, you'll need to download and locally provide the font files. You can download the files directly from their source site <Link to="https://rsms.me/inter/">rsms.me/inter/</Link>, then follow the instructions in the provided CSS file for importing. We recommend using the single variable font file and importing with the following settings:

```css
@font-face {
  font-family: 'Inter';
  font-weight: 300 900;
  font-display: swap;
  font-style: oblique 0deg 10deg;
  src: url("Inter.var.woff2") format("woff2");
}
```

## Components, Services and Testing imports

You can import React components from the top-level EUI module.

```tsx
import {
  EuiButton,
  EuiCallOut,
  EuiPanel,
} from '@elastic/eui';
```

Most services are published from the `lib/services` directory. Some are published from their module directories in this directory.

```tsx
import { keys } from '@elastic/eui/lib/services';
import { Timer } from '@elastic/eui/lib/services/time';
```

Test utilities are published from the `lib/test` directory.

```tsx
import { findTestSubject } from '@elastic/eui/lib/test'; // Enzyme
import { findByTestSubject, render, screen } from '@elastic/eui/lib/test/rtl'; // React Testing Library
```

## Customizing component defaults

While all props can be individually customized via props, some components can have their default props customized globally via **EuiProvider's** `componentDefaults` API. [Read more in EuiProvider's documentation](../utilities/provider.mdx#component-defaults).

```tsx
<EuiProvider
  componentDefaults={{
    EuiTable: { responsiveBreakpoint: 's', },
    EuiTablePagination: { itemsPerPage: 20, },
    EuiFocusTrap: { crossFrame: true },
    EuiPortal: { insert },
    EuiFlyout: { includeSelectorInFocusTrap: ['.custom-selector', '[data-custom-selector]'], includeFixedHeadersInFocusTrap: false },
    EuiPopover: { repositionOnScroll: true },
    EuiToolTip: { repositionOnScroll: true },
  }}
>
  <App />
</EuiProvider>
```

---

### Packages Website Docs Getting Started Tree Shaking (`packages/website/docs/getting-started/tree-shaking.mdx`)

---
sidebar_position: 2
keywords: [tree-shaking, bundle size, optimization, dead code elimination]
---

# Tree-shaking

```mdx-code-block
import Link from '@docusaurus/Link';
```

Tree-shaking (dead code elimination) allows bundlers to remove unused code from your production builds, reducing the amount of JavaScript shipped to users.

## How EUI supports tree-shaking

EUI publishes two build outputs:

- **`es/`** — ES modules (used by modern bundlers via the `module` field in `package.json`)
- **`lib/`** — CommonJS (used as fallback via the `main` field)

The `es/` build preserves `import`/`export` syntax, which bundlers like Webpack, Rollup, and esbuild can statically analyze to determine which exports are actually used.

EUI's `package.json` also declares:

```json
{
  "sideEffects": ["*.css", "*.scss"]
}
```

This tells bundlers that all JavaScript modules are side-effect-free and safe to remove if unused. Only CSS/SCSS files are marked as having side effects.

## What you need

For tree-shaking to work, your bundler must resolve `@elastic/eui` to the **ES module build** (`es/`). Most bundlers do this automatically via the `module` field. Verify that you're importing from the top-level package:

```tsx
import { EuiButton, EuiPanel } from '@elastic/eui';
```

No special configuration is needed — a properly configured bundler will tree-shake unused components automatically.

## Icons and code-splitting

**EuiIcon** uses dynamic imports to load icon assets only when actually used. Depending on your bundler's configuration, each icon may become a fully separate chunk loaded lazily at runtime, or be otherwise grouped together with other code. It's common for bundlers to decide that based on the minimum and maximum chunk sizes to optimize code delivery efficiency. Please check your bundler documentation to learn more.

```ts
// Simplified example of how EUI maps icon names to dynamic imports
const typeToPathMap = {
  calendar: () => import('./assets/calendar'),
  check: () => import('./assets/check'),
  // ...
};
```

This means icon SVGs are **not** included in your main bundle — they're fetched only when a specific icon renders on the page. However, the mapping object itself (which associates icon names with their chunk references) is always included when `EuiIcon` is used.

:::info
There is an ongoing effort to <Link to="https://github.com/elastic/eui/issues/8860">refactor EuiIcon</Link> for improved performance and reduced mapping overhead.
:::

## Verifying tree-shaking in your project

To confirm tree-shaking is working:

1. **Webpack**: Use <Link to="https://www.npmjs.com/package/webpack-bundle-analyzer">webpack-bundle-analyzer</Link> to visualize your bundle and check that unused EUI components are not present
2. **Vite/Rollup**: Use <Link to="https://www.npmjs.com/package/rollup-plugin-visualizer">rollup-plugin-visualizer</Link> for a similar analysis

A minimal app importing only `EuiButton` should produce a production bundle significantly smaller than the full EUI library.

## CommonJS consumers

If your project resolves to the **`lib/`** (CommonJS) build, tree-shaking will **not** work because CommonJS modules are not statically analyzable. In this case, you can use direct subpath imports to limit what gets included:

```tsx
import { EuiButton } from '@elastic/eui/lib/components/button';
import { keys } from '@elastic/eui/lib/services';
```

:::warning
Subpath imports are not a guaranteed API and may change between versions. Prefer using the ES module build with top-level imports for reliable tree-shaking.
:::

---

### Packages Website Docs Patterns Help Content (`packages/website/docs/patterns/help-content.mdx`)

---
sidebar_position: 4
---

import figmaHelpContentShortDefinitions from '!url-loader!./assets/help-content_short-definitions.svg';
import figmaHelpContentForASpecificSettingOrGroup from '!url-loader!./assets/help-content_for-a-specific-setting-or-group.svg';
import figmaHelpContentForAnEntirePageOrApp from '!url-loader!./assets/help-content_for-an-entire-page-or-app.svg';
import figmaHelpContentFieldsAndSettings from '!url-loader!./assets/help-content_fields-and-settings.svg';
import figmaHelpContentAdditionalInformation from '!url-loader!./assets/help-content_additional-information.svg';
import figmaHelpContentSyntaxReferences from '!url-loader!./assets/help-content_syntax-references.svg';
import figmaHelpContentLegendsForGraphsAndTables from '!url-loader!./assets/help-content_legends-for-graphs-and-tables.svg';

# Help content

Help content includes any copy added to the product experience to help users understand a concept or complete a task. It can be definitions, context, explanations, hints, references, and more.

## Considering help content

Before thinking about how to display and write help content, it's important to consider the messaging, importance, scope and role of that content in the user experience.

- **The right content at the right time**. Focus on what users need to reach their next step. They don't need to know everything from the start. If anything, too much information will confuse them. Consider what you're sure they know, and what they may not know that they need.
- **Be intentional**. Don't push everything to the user's face. While some information is absolutely critical, some might be useful for specific cases or for a particular type of users only. Some might even just be additional context that would digress from the user's flow. Consider letting users choose to consume or not that non-critical, yet useful, content through a simple and recognizable interaction.
- **Anticipate errors and questions**. Don't wait for errors or questions to provide guidance. We help users avoid them, and when they happen, [we're here](./error-messages/index.mdx) for them.


## Short definitions
Defining terms is particularly useful in onboarding experiences or in the first few steps that users go through when using a feature.

<FigmaAsset
  url="https://www.figma.com/file/1ryJM0lhbUopALKHwPUhFC/Help-content?type=design&node-id=6-343&mode=design&t=vZqFprizypJOJryZ-0"
  src={figmaHelpContentShortDefinitions}
  title="Short definitions"
/>

**Interaction**
- Question mark icon <Icon type="question" title="question mark in a circle" /> with the `primary` color directly following the term to explain.
- On hover, a [tooltip](../components/display/tooltip.mdx) appears.
- Use it anywhere needed: navigation, titles, or inline.

**Tooltip content**
- Body
  - Less than 40 words (that’s about 2 short sentences).
    > If you need more, you are likely [explaining a concept](#concepts) instead.
  - Sentence case.
  - Full punctuation.
  - Start the definition with the full term you are defining to leave no ambiguity.
  - Audience level: beginners.
  - Don’t include interactions inside of the tooltip (like links). If you need some or rich formatting, you're likely not just providing a simple definition and are instead [explaining a concept](#concepts).
- No header, title, footer or call to action.


## Concepts
Concepts are more than quick definitions. They help users understand how something works, why they should or shouldn't use something, and can include resources or links with further details.

### For a specific setting or group

<FigmaAsset
  url="https://www.figma.com/file/1ryJM0lhbUopALKHwPUhFC/Help-content?type=design&node-id=1-192&mode=design&t=vZqFprizypJOJryZ-0"
  src={figmaHelpContentForASpecificSettingOrGroup}
  title="Help popover with additional context"
/>


**Interaction**
- Information icon <Icon type="info" title="information icon" /> with the `primary` color directly following the setting to explain.
- On click, a [popover](../components/containers/popover.mdx) appears. It is dismissed by a second click outside of the popover area.

**Popover content**
- Header _required_
  - Be explicit about what users are about to read.
  - Sentence case.
  - No punctuation.
- Body _required_
  - If necessary, structure the content into sections. It should be no more than 2 to 3 short paragraphs. If the content is longer than that, use a flyout to avoid disrupting the user from their main task.
  - Format keywords, code blocks, input examples, links, etc.
  - You can add images or gifs.
  - Sentence case.
  - Full punctuation.
  - Audience level: beginners.
- Footer _optional_
  - For any call to action.

### For an entire page or app

<FigmaAsset
  url="https://www.figma.com/file/1ryJM0lhbUopALKHwPUhFC/Help-content?type=design&node-id=6-278&mode=design&t=vZqFprizypJOJryZ-0"
  src={figmaHelpContentForAnEntirePageOrApp}
  title="Help flyout with additional information"
/>

_Note: the formatting of the flyout here is just an example._


**Interaction**
- Use a [Flyout](../components/containers/flyout/index.mdx), in `push` mode if possible, as overlays can be disruptive.
- Locate the interaction to open the flyout somewhere visible and that matches with the context of the content:
  - If that is for an entire app, use the help button from the header
  - If that is for a significant section or area of the UI, use an explicit link near the top of the area or section or a button.
- Add an explicit **Close** action to the footer as a way to dismiss the flyout.

**Flyout content**
- Header
  - Action-oriented title.
  - Sentence case.
  - No punctuation.
- Body
  - Structure content to help users scan.
  - Keep it short, it doesn't have to be the fully-detailed documentation. Keep the most important to keep it readable.
  - Format keywords, code blocks, input examples, etc.
  - You can add images or gifs.
  - Sentence case.
  - Full punctuation.
  - Audience: all levels.
- Footer
  - Call to action to **Close** the flyout.
  - If necessary, add another call to action to read the full documentation.

## Fields and settings
Several mechanisms exist to provide additional help around a specific field. All of these mechanisms are **optional**.

<FigmaAsset
  url="https://www.figma.com/file/1ryJM0lhbUopALKHwPUhFC/Help-content?type=design&node-id=60-6885&mode=design&t=vZqFprizypJOJryZ-0"
  src={figmaHelpContentFieldsAndSettings}
  title="Different types of help for form controls and fields"
/>


**Hint text (shows below a field)**
- Use it for explaining:
  - the accepted syntax, the format, range or number of accepted values, or how to enter multiple values if needed.
  - the consequences of changing the value or enabling the setting if they're critical to know.
- Hint text should be short. If the text is more than 2 lines, there might be an underlying design issue, or you need a different help mechanism like a [syntax reference](#syntax-references).

**Placeholder text**
- Important help should show outside of a field, not as placeholder, as the information will disappear as soon as users start typing.
- Use it for input examples.
- Exception: in search and filter bars, use it to guide users on what they can search for or filter.
- Defaults are different from placeholders and shouldn't look like placeholders. They should pre-populate the field.

**Additional information**

Add a tooltip or popover next to the label of a field to provide additional context on the concept or to provide usage guidance. For example, "When should I use this?".

<FigmaAsset
  url="https://www.figma.com/file/1ryJM0lhbUopALKHwPUhFC/Help-content?type=design&node-id=617-386&mode=design&t=gMQHqaXMvQB3A4BX-0"
  src={figmaHelpContentAdditionalInformation}
  title="Additional information"
/>


## Syntax references
Providing reference docs directly in the product can help users stay focused on filling any field requiring functions or advanced syntax.

<FigmaAsset
  url="https://www.figma.com/file/1ryJM0lhbUopALKHwPUhFC/Help-content?type=design&node-id=65-56594&mode=design&t=o9mXncfMtIGAHvEG-0"
  src={figmaHelpContentSyntaxReferences}
  title="Syntax reference best practices"
/>

**Interaction**
- Use the <Icon type="documentation" title="book icon" /> icon with the `primary` color to indicate a reference. When possible, add an explicit link text.
- Locate the interaction for opening the reference right next to or under the field, depending on the UI layout.
- On click, a [Flyout](../components/containers/flyout/index.mdx) in `push` mode or a [popover](../components/containers/popover.mdx) opens.
- For popovers, clicking outside closes the help.
- For flyouts, add an explicit Close button to the footer.


**Reference content**
- Header
  - Make the scope of the reference content clear to users.
- Body
  - Structure content to help users scan. Use sections or pages depending on the size of the reference.
  - Format the content so that code samples and input text are easy to identify and copy.
  - Sentence case.
  - Full punctuation.
- Functionality
  - For large sets of functions, make it possible to browse using navigation and a search or nav filter.


## Legends for graphs and tables
Elastic visualizations often show acronyms or depths of details that require legends.

<FigmaAsset
  url="https://www.figma.com/file/1ryJM0lhbUopALKHwPUhFC/Help-content?type=design&node-id=121-56743&mode=design&t=o9mXncfMtIGAHvEG-0"
  src={figmaHelpContentLegendsForGraphsAndTables}
  title="Legend and definitions for visualizations"
/>

**Interaction**
- Use an explicit text link with the <Icon type="listBullet" title="list icon" /> icon with the `primary` color to indicate a list of definitions.
- This link must be within the context of what it applies to, generally near the upper right corner of the visualization or UI section.
- On click, a [popover](../components/containers/popover.mdx) appears.

**Legend content**
- Header
  - Use the same word as the link text used to open the popover.
- Body
  - Format the content of the popover in a way that helps users scan. It can be a simple definition list, or a table with one icon and definition per row, etc.
  - For acronyms, make sure to repeat them as they appear on the visualization, accompanied by their full form.

## Other forms of in-product help
More forms of indirect ways to help users exist in the product experience and have their own dedicated patterns. Related patterns:
* [Error messages](./error-messages/index.mdx)

---

### Packages Website Docs Patterns Save Buttons (`packages/website/docs/patterns/save-buttons.mdx`)

---
sidebar_position: 5
---

import figmaSaveButtonsWhenShouldIUseASaveButton from '!url-loader!./assets/save-buttons_when-should-i-use-a-save-button.svg';
import figmaSaveButtonsHowDoIStyleIt from '!url-loader!./assets/save-buttons_how-do-i-style-it.svg';
import figmaSaveButtonsAvoidUsingTheDefaultFillForTheButton from '!url-loader!./assets/save-buttons_avoid-using-the-default-fill-for-the-button.svg';
import figmaSaveButtonsAvoidUsingTheSuccessColorVariant from '!url-loader!./assets/save-buttons_avoid-using-the-success-color-variant.svg';
import figmaSaveButtonsAvoidSizingTheButtonDifferentlyThanSurroundingButtonsOrFormFields from '!url-loader!./assets/save-buttons_avoid-sizing-the-button-differently-than-surrounding-buttons-or-form-fields.svg';
import figmaSaveButtonsConsiderIfAnIconIsNecessary from '!url-loader!./assets/save-buttons_consider-if-an-icon-is-necessary.svg';

# Save buttons

Guidance for how to select button type, what props to use (color and size), whether to include an icon or not, what labels to use (e.g. Create vs Save), and when

## When should I use a 'Save button'?

Save buttons are specific to CRUD operations.  As there are obviously many places in Kibana that require creating, editing/updating something, the following are recommendations to help drive consistency.

- Creating an object that can be edited / deleted
- Updating or modifying settings

Consider using **"Save"** rather than **"Update"**, **"Create"** or **"Apply"**. Try to reserve the use of “Apply" for actions that do not permanently save data but rather temporarily apply changes.

<FigmaAsset
  url="https://www.figma.com/file/rTQpimg0zLB8RP1TWngNTk/Save-Create-Buttons-%5B179%5D?type=design&node-id=738%3A183&mode=design&t=mG6gI94ediVlaPgh-1"
  src={figmaSaveButtonsWhenShouldIUseASaveButton}
  title="When should I use a 'Save button'?"
/>

## How do I style it?


The save button should be the most dominant action and should be consistent in any context.  It is recommended to follow the recommended styling to maintain a recognizable save action.

* Use the `fill` prop
* Match the sizing of form fields, but use the `medium` size where possible.
* Use the `primary` color variant
* Include the noun in the label.
* Avoid using icons where possible

<FigmaAsset
  url="https://www.figma.com/file/rTQpimg0zLB8RP1TWngNTk/Save-Create-Buttons-%5B179%5D?type=design&node-id=562%3A3874&mode=design&t=CLKS3D49G3Au83kb-1"
  src={figmaSaveButtonsHowDoIStyleIt}
  title="How do I style it?"
/>


### Avoid using the default fill for the button
Saving should be the primary action in the user's context, so this button should be the most dominant. If multiple buttons or options, make sure the 'Save' button uses the `fill` prop.

<FigmaAsset
  url="https://www.figma.com/file/rTQpimg0zLB8RP1TWngNTk/Save-Create-Buttons-%5B179%5D?type=design&node-id=562%3A3964&mode=design&t=CLKS3D49G3Au83kb-1"
  src={figmaSaveButtonsAvoidUsingTheDefaultFillForTheButton}
  title="Avoid using the default fill for the button"
/>


### Avoid using the `success` color variant

The save button should be the most dominant action in the view. By using our primary color and `fill` prop, it insures we keep these consistent wherever it is placed.

<FigmaAsset
  url="https://www.figma.com/file/rTQpimg0zLB8RP1TWngNTk/Save-Create-Buttons-%5B179%5D?type=design&node-id=562%3A3994&mode=design&t=CLKS3D49G3Au83kb-1"
  src={figmaSaveButtonsAvoidUsingTheSuccessColorVariant}
  title="Avoid using the success color variant"
/>


### Avoid sizing the button differently than surrounding buttons or form fields

We should use the `medium` size button by default. However, use the same size button as other buttons in the group and the associated form inputs (`m` for default size form inputs, `s` for compressed forms).

<FigmaAsset
  url="https://www.figma.com/file/rTQpimg0zLB8RP1TWngNTk/Save-Create-Buttons-%5B179%5D?type=design&node-id=562%3A3892&mode=design&t=CLKS3D49G3Au83kb-1"
  src={figmaSaveButtonsAvoidSizingTheButtonDifferentlyThanSurroundingButtonsOrFormFields}
  title="Avoid sizing the button differently than surrounding buttons or form fields"
/>


### Consider if an icon is necessary

While icons can provide context and additional visual cues to buttons, a Save button by principle should be styled so it is visually dominant. Therefore, it is likely less necessary to use an icon for these buttons compared to other actions within the page that can have similar weight to nearby buttons/actions.

The choice of the icon can also be difficult here.  We have used a `disk` icon and a `check` icon with Save buttons within our UIs, but the meaning of these icons can be confusing.  So our recommendation is to avoid the inconsistency here and rely solely on the label.

**Exceptions to the rule:**
As with anything, there will be exceptions to these recommendations.  One example is the `EuiInlineEdit` component which provides a save action without a label.

<FigmaAsset
  url="https://www.figma.com/file/rTQpimg0zLB8RP1TWngNTk/Save-Create-Buttons-%5B179%5D?type=design&node-id=562%3A4023&mode=design&t=CLKS3D49G3Au83kb-1"
  src={figmaSaveButtonsConsiderIfAnIconIsNecessary}
  title="Consider if an icon is necessary"
/>

---

### Packages Website Docs Utilities Auto Sizer (`packages/website/docs/utilities/auto-sizer.mdx`)

---
keywords: [EuiAutoSizer]
---

# Auto sizer

`EuiAutoSizer` helps components that use virtualized rendering and/or require explicit dimensions to fill all available space in the parent container. See the [react-virtualized AutoSizer](https://github.com/bvaughn/react-virtualized/blob/master/docs/AutoSizer.md) documentation as `EuiAutoSizer` is a passthrough component for `AutoSizer`.

<Demo>
  ```tsx
  import React from 'react';
  import { css } from '@emotion/react';

  import {
  EuiAutoSizer,
  EuiAutoSize,
  EuiCode,
  EuiPanel,
  logicalSizeCSS,
  } from '@elastic/eui';

  export default () => {
    const containerStyles = css`
      ${logicalSizeCSS('100%', '200px')}
    `;

    const panelStyles = css`
      position: absolute;
      display: flex;
      align-items: center;
      justify-content: center;
    `;

    return (
      <div css={containerStyles}>
        <EuiAutoSizer>
          {({ height, width }: EuiAutoSize) => (
            <EuiPanel css={[panelStyles, { height, width }]}>
              <EuiCode>
                height: {height}, width: {width}
              </EuiCode>
            </EuiPanel>
          )}
        </EuiAutoSizer>
      </div>
    );
  };
  ```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/auto_sizer';

<PropTable definition={docgen.EuiAutoSizer} />

---

### Packages Website Docs Utilities Container Queries (`packages/website/docs/utilities/container-queries.mdx`)

---
title: Container queries
---

import { EuiBetaBadge } from '@elastic/eui';

# Container queries <EuiBetaBadge label="Beta" color="accent" />

Container queries allow you to create styles that adapt based on the available
space within element's parent container, rather than the entire browser
viewport. This unlocks a new level of modularity, enabling designs that are
intrinsically responsive regardless of where they are placed in a layout,
and reactive to important layout changes, like expanding the page sidebar.

```tsx interactive
import React from 'react';
import { EuiText, EuiResizableContainer } from '@elastic/eui';
import { faker } from '@faker-js/faker';

const text = faker.lorem.paragraphs();

export default () => (
  <EuiResizableContainer style={{ height: '200px' }}>
    {(EuiResizablePanel, EuiResizableButton) => (
      <>
        <EuiResizablePanel initialSize={50} minSize="30%" tabIndex={0} css={euiContainerCSS('inline-size')}>
          <EuiText>{text}</EuiText>
        </EuiResizablePanel>

        <EuiResizableButton accountForScrollbars="before" />

        <EuiResizablePanel initialSize={50} minSize="200px" tabIndex={0} css={euiContainerCSS('inline-size')}>
          <EuiText css={css`${euiContainerQuery('(width < 300px)')} { ${useEuiFontSize('xs')} }`}>
            <strong>This text will become small when the panel width is lower than 300px</strong>
            <br />
            {text}
          </EuiText>
        </EuiResizablePanel>
      </>
    )}
  </EuiResizableContainer>
);
```

## Overview

For years, responsive web design relied heavily on media queries.
These allow us to adjust styles based on the global viewport size
(e.g., "if the screen is wider than 768px, do this").
While effective for page-level layouts, media queries often fall short
when building reusable components, or building component organisms.
An `EuiCard` or `EuiBasicTable`, for example, might need to look different
when placed in a narrow flyout versus a wide main content area,
even if the viewport size remains the same.

Container queries solve this by moving the context from the screen
to the element:

* **Media Queries**: "How wide is the user's screen?"
* **Container Queries**: "How much space do I have in this specific container?"

By querying the container, you can build self-contained components that "own"
their responsiveness. This reduces the need for complex grid classes
or layout-specific overrides.

## Usage

EUI ships with container query utilities that make the process of defining
containers and creating container queries seamless.

### 1. Define the container

To use container queries, you must first establish a **containment context**
on a parent element to tell the browser which element should act
as the reference point for size calculations.

We provide two utility functions to help with that:

* `euiContainer(type: ContainerType, name?: string, scrollState?: boolean)` - to be used within Emotion template tags
* `euiContainerCSS(type: ContainerType, name?: string, scrollState?: boolean)` - to be passed directly to the `css` prop

### 2. Query the container

Once a container is established, you can use the `euiContainerQuery` utility
to define container queries and apply styles to its children.
The approach is very similar to media queries and the breakpoint EUI utilities
like `euiMinBreakpoint()`:

```tsx
const styles = css`
  ${useEuiFontSize('s')}
  ${euiContainerQuery('(width > 400px)')} {
    useEuiFontSize('m')
  }
`;
```

`euiContainerQuery` accepts two arguments:

* `conditions: string`: one or many conditions to query the container with.
  Similarly to media queries, you can use size queries (e.g., `(width > 300px)`),
  scroll state queries (e.g., `(scroll-state(scrollable: top))`)
  or even style queries.
  You can use the `and`, `or` and `not` logical keywords to define container conditions.
  Note that all conditions must be wrapped in parentheses.

* `containerName?: string`: When provided, it will be used to target
  the containment context and run queries against it. Otherwise, the nearest
  ancestor with containment will be queried instead.

## Querying containers using JS

:::warning
For performance reasons, using container queries in JS is not recommended.
:::
All layout transforms related to container query changes should be handled
directly in CSS (or CSS-in-JS) whenever possible.
This ensures good performance and omits React tree rerenders caused
by viewport or container resizes, which are the major cause of the application
feeling sluggish.

That being said, we're aware that sometimes it is necessary to access
container queries from JS land, and we provide a (relatively) performant
way to do so - the `useEuiContainerQuery()` hook.

What's important to point out is that using the hook requires passing
a special `ref` prop provided by it to the element you want to query,
so that the calculation can be done on the right element.

<Demo isSourceOpen>
  ```tsx
  import React from 'react';
  import { useEuiContainerQuery, euiContainerCSS, EuiCodeBlock } from '@elastic/eui';

  export default () => {
    const { ref, matches } = useEuiContainerQuery('(width > 300px)');

    return (
      <EuiResizableContainer>
        {(EuiResizablePanel, EuiResizableButton) => (
          <>
            <EuiResizablePanel initialSize="50" css={euiContainerCSS('inline-size')}>
              <div ref={ref}>
                <EuiCodeBlock language="jsx" fontSize="m" paddingSize="m" whiteSpace="pre">
                  {`/* true when width > 300px */\nmatches = ${matches ? 'true' : 'false'}`}
                </EuiCodeBlock>
              </div>
            </EuiResizablePanel>
            <EuiResizableButton accountForScrollbars="before" />
            <EuiResizablePanel initialSize="50">
              Resize the resizable panel to see the left side content changing.
            </EuiResizablePanel>
          </>
        )}
      </EuiResizableContainer>
    );
  };
```
</Demo>

---

### Packages Website Docs Utilities Copy (`packages/website/docs/utilities/copy.mdx`)

---
keywords: [EuiCopy]
---

# Copy

The **EuiCopy** component is a utility for copying text to clipboard. Wrap a function that returns a component. The first argument will be a `copy` function.

<Demo>
```tsx interactive
import React, { useState } from 'react';

import {
  EuiCopy,
  EuiButton,
  EuiFieldText,
  EuiSpacer,
  EuiFormRow,
} from '@elastic/eui';

export default () => {
  const [copyText, setCopyText] = useState('I am the text that will be copied');

  const onChange = (e) => {
    setCopyText(e.target.value);
  };

  return (
    <div>
      <EuiFormRow label="Enter text that will be copied to clipboard">
        <EuiFieldText value={copyText} onChange={onChange} />
      </EuiFormRow>

      <EuiSpacer size="m" />

      <EuiCopy textToCopy={copyText}>
        {(copy) => (
          <EuiButton onClick={copy}>Click to copy input text</EuiButton>
        )}
      </EuiCopy>
    </div>
  );
};
```
</Demo>

## Copy to clipboard function

The function `copyToClipboard` allows you to copy text to the clipboard. It receives an argument of type `string`.

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/copy';

<PropTable definition={docgen.EuiCopy} />

---

### Packages Website Docs Utilities Css Utility Classes (`packages/website/docs/utilities/css-utility-classes.mdx`)

# CSS utility classes

import { Example } from '@site/src/components';
import { css } from '@emotion/react';

import { EuiIcon, EuiMark } from '@elastic/eui';

The following CSS-only classes are provided as helper utilities. They are useful for making micro-adjustments to existing React components.

:::info Scroll utilities have moved

For overflow and scrolling specific utilities, go to [the Scroll documentation page](./scroll/index.mdx).
:::

:::info Text utilities have moved

For text and typography specific utilities, go to [the Text documentation page](../getting-started/theming/utilities/typography.mdx).
:::

:::info Responsive utilities have moved

For responsive specific utilities, go to [the Breakpoint utilities page](../getting-started/theming/utilities/breakpoints.mdx).
:::

## Display

<Example>
  <Example.Description>
    ### `eui-displayBlock` <Badge color="hollow">className</Badge>

    Changes the element's display property to `display: block;`
  </Example.Description>
  <Example.Preview>
    <EuiMark css={css`background: 'rgba(254, 228, 181, 0.25)';`} className="eui-displayBlock">Displaying block</EuiMark>
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <span className="eui-displayBlock">
    /* Your content */
    </span>
    ```
  </Example.Snippet>
</Example>
<Example>
  <Example.Description>
    ### `eui-displayInline` <Badge color="hollow">className</Badge>

    Changes the element's display property to `display: inline;`
  </Example.Description>
  <Example.Preview>
    <EuiMark css={css`background: 'rgba(254, 228, 181, 0.25)';`} className="eui-displayInline">Displaying inline</EuiMark>
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <div className="eui-displayInline">
    /* Your content */
    </div>
    ```
  </Example.Snippet>
</Example>
<Example>
  <Example.Description>
    ### `eui-displayInlineBlock` <Badge color="hollow">className</Badge>

    Changes the element's display property to `display: inline-block;`
  </Example.Description>
  <Example.Preview>
    <EuiMark css={css`background: 'rgba(254, 228, 181, 0.25)';`}className="eui-displayInlineBlock">Displaying inline block</EuiMark>
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <span className="eui-displayInlineBlock">
    /* Your content */
    </span>
    ```
  </Example.Snippet>
</Example>
<Example>
  <Example.Description>
    ### `eui-fullWidth` <Badge color="hollow">className</Badge>

    Changes the element's display property to `display: inline-block;` and adds `width: 100%;`
  </Example.Description>
  <Example.Preview>
    <EuiMark css={css`background: 'rgba(254, 228, 181, 0.25)';`} className="eui-fullWidth">Displaying full width</EuiMark>
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <span className="eui-fullWidth">
    /* Your content */
    </span>
    ```
  </Example.Snippet>
</Example>

## Vertical alignment

<Example>
  <Example.Description>
    ### `eui-alignTop` <Badge color="hollow">className</Badge>

    Changes the element's vertical alignment property to `vertical-align: top;`
  </Example.Description>
  <Example.Preview>
    <p>
      <EuiIcon
        type="logoElasticStack"
        size="xxl"
        className="eui-alignTop"
      /> Icon is aligned to the top of the text
    </p>
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <EuiIcon className="eui-alignTop" type="logoElasticStack" />
    ```
  </Example.Snippet>
</Example>
<Example>
  <Example.Description>
    ### `eui-alignMiddle` <Badge color="hollow">className</Badge>

    Changes the element's vertical alignment property to `vertical-align: middle;`
  </Example.Description>
  <Example.Preview>
    <p>
      <EuiIcon
        type="logoElasticStack"
        size="xxl"
        className="eui-alignMiddle"
      /> Icon is aligned to the middle of the text
    </p>
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <EuiIcon className="eui-alignMiddle" type="logoElasticStack" />
    ```
  </Example.Snippet>
</Example>
<Example>
  <Example.Description>
    ### `eui-alignBottom` <Badge color="hollow">className</Badge>

    Changes the element's vertical alignment property to `vertical-align: bottom;`
  </Example.Description>
  <Example.Preview>
    <p>
      <EuiIcon
        type="logoElasticStack"
        size="xxl"
        className="eui-alignBottom"
      /> Icon is aligned to the bottom of the text
    </p>
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <EuiIcon className="eui-alignBottom" type="logoElasticStack" />
    ```
  </Example.Snippet>
</Example>
<Example>
  <Example.Description>
    ### `eui-alignBaseline` <Badge color="hollow">className</Badge>

    Changes the element's vertical alignment property to `vertical-align: baseline;`
  </Example.Description>
  <Example.Preview>
    <p>
      <EuiIcon
        type="logoElasticStack"
        size="xxl"
        className="eui-alignBaseline"
      /> Icon is aligned to the baseline of the text
    </p>
  </Example.Preview>
  <Example.Snippet>
    ```tsx
    <EuiIcon className="eui-alignBaseline" type="logoElasticStack" />
    ```
  </Example.Snippet>
</Example>

---

### Packages Website Docs Utilities Delay (`packages/website/docs/utilities/delay.mdx`)

---
keywords: [EuiDelayRender]
---

# Delay

## Delay render

**EuiDelayRender** is a component for conditionally toggling the visibility of a child component. It will ensure that the child is hidden for at least 500ms (default). This allows delay UI rendering. That is helpful when you need to update aria live region(s) repeatedly.

<Demo>
```tsx interactive
import React, { useState, Fragment } from 'react';

import {
  EuiDelayRender,
  EuiFlexItem,
  EuiCheckbox,
  EuiFormRow,
  EuiFieldNumber,
  EuiLoadingSpinner,
} from '@elastic/eui';

export default () => {
  const [minimumDelay, setDelay] = useState(3000);
  const [render, setRender] = useState(false);

  const onChangeMinimumDelay = (event) => {
    setDelay(parseInt(event.target.value, 10));
  };

  const onChangeHide = (event) => {
    setRender(event.target.checked);
  };

  const status = render ? 'showing' : 'hidden';
  const label = `Child (${status})`;

  return (
    <Fragment>
      <EuiFlexItem>
        <EuiFormRow>
          <EuiCheckbox
            id="dummy-id"
            checked={render}
            onChange={onChangeHide}
            label="Show child"
          />
        </EuiFormRow>
        <EuiFormRow label="Minimum delay">
          <EuiFieldNumber
            value={minimumDelay}
            onChange={onChangeMinimumDelay}
          />
        </EuiFormRow>
        <EuiFormRow label={label}>
          {render ? (
            <EuiDelayRender delay={minimumDelay}>
              <EuiLoadingSpinner size="m" />
            </EuiDelayRender>
          ) : (
            <Fragment />
          )}
        </EuiFormRow>
      </EuiFlexItem>
    </Fragment>
  );
};
```
</Demo>

## Delay hide

**EuiDelayHide** is a component for conditionally toggling the visibility of a child component. It will ensure that the child is visible for at least 1000ms (default). This avoids UI glitches that are common with loading spinners and other elements that are rendered conditionally and potentially for a short amount of time.

<Demo>
```tsx interactive
import React, { useState, Fragment } from 'react';

import {
  EuiDelayHide,
  EuiFlexItem,
  EuiCheckbox,
  EuiFormRow,
  EuiFieldNumber,
  EuiLoadingSpinner,
} from '@elastic/eui';

export default () => {
  const [minimumDuration, setDuration] = useState(3000);
  const [hide, setHide] = useState(false);

  const onChangeMinimumDuration = (event) => {
    setDuration(parseInt(event.target.value, 10));
  };

  const onChangeHide = (event) => {
    setHide(event.target.checked);
  };

  return (
    <Fragment>
      <EuiFlexItem>
        <EuiFormRow>
          <EuiCheckbox
            id="dummy-id"
            checked={hide}
            onChange={onChangeHide}
            label="Hide child"
          />
        </EuiFormRow>
        <EuiFormRow label="Minimum duration">
          <EuiFieldNumber
            value={minimumDuration}
            onChange={onChangeMinimumDuration}
          />
        </EuiFormRow>
        <EuiFormRow label="Child to render">
          <EuiDelayHide
            hide={hide}
            minimumDuration={minimumDuration}
            render={() => <EuiLoadingSpinner size="m" />}
          />
        </EuiFormRow>
      </EuiFlexItem>
    </Fragment>
  );
};
```
</Demo>

## Props

import delayRenderDocgen from '@elastic/eui-docgen/dist/components/delay_render';
import delayHideDocgen from '@elastic/eui-docgen/dist/components/delay_hide';

<PropTable definition={delayRenderDocgen.EuiDelayRender} />
<PropTable definition={delayHideDocgen.EuiDelayHide} />

---

### Packages Website Docs Utilities Error Boundary (`packages/website/docs/utilities/error-boundary.mdx`)

---
keywords: [EuiErrorBoundary]
---

# Error boundary

Use **EuiErrorBoundary** to prevent errors from taking down the entire app.

Ideally end-users should never see an actual error boundary rendered. If a React component can throw errors during rendering, those should be caught internally and the component should render specific error messages that help the user understand what happened and how to correct it. See the [Error messages](docs/patterns/error-messages/index.mdx) pattern for more guidance.

**EuiErrorBoundary** should only be used to surround components at a high level, where we don't know how lower-level code works and we don't trust it to catch all of its own errors. Wrapping lazy-loaded components in boundaries is a good practice.

In Kibana, we try to preserve the integrity of server-side data by not allowing the user to make state changes using a UI with an active error state; for this reason, the error boundary should cover up UI controls that trigger updates to server-side data. Or the controls should be hidden some other way, like having the component be aware of when it's in an error state.

:::note Kibana engineers

All error boundaries should have the same look and feel in Kibana, and for that reason it's not recommended to use **EuiErrorBoundary** at all. Use **KibanaErrorBoundary** instead

:::

<Demo>
```tsx interactive
import React from 'react';

import { EuiErrorBoundary } from '@elastic/eui';

const BadComponent = () => {
  throw new Error(
    "I'm here to kick butt and chew bubblegum. And I'm all out of gum."
  );
};

export default () => (
  <EuiErrorBoundary>
    <BadComponent />
  </EuiErrorBoundary>
);
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/error_boundary';

<PropTable definition={docgen.EuiErrorBoundary} />

---

### Packages Website Docs Utilities Highlight And Mark (`packages/website/docs/utilities/highlight-and-mark.mdx`)

---
keywords: [EuiHighlight, EuiMark]
---

# Highlight and mark

## Highlight

Use **EuiHighlight** to highlight substrings within a string, typically in response to user input.

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Mark

Use **EuiMark** to wrap a string in a `mark` element.

<Demo>
```tsx interactive
import React from 'react';

import { EuiMark } from '@elastic/eui';

export default () => {
  return (
    <>
      The quick brown fox <EuiMark>jumped over</EuiMark> the lazy dog
    </>
  );
};
```
</Demo>

## Props

import highlightDocgen from '@elastic/eui-docgen/dist/components/highlight';
import markDocgen from '@elastic/eui-docgen/dist/components/mark';

<PropTable definition={highlightDocgen.EuiHighlight} />
<PropTable definition={markDocgen.EuiMark} />

---

### Packages Website Docs Utilities Html Id Generator (`packages/website/docs/utilities/html-id-generator.mdx`)

---
keywords: [htmlIdGenerator]
---

# HTML ID generator

Use `htmlIdGenerator()()` to generate unique IDs for elements with an optional `prefix` and/or `suffix`. The first call to `htmlIdGenerator` accepts the prefix as an optional argument and returns a second function which accepts an optional suffix and returns the generated ID.

<Demo>
```tsx interactive
import React, { useState, Fragment } from 'react';

import {
  EuiFlexGroup,
  EuiFlexItem,
  EuiButton,
  EuiCode,
  htmlIdGenerator,
} from '@elastic/eui';

export default () => {
  const [value, setValue] = useState(htmlIdGenerator()());

  const reGenerate = () => {
    setValue(htmlIdGenerator()());
  };

  return (
    <Fragment>
      <EuiFlexGroup
        justifyContent="flexStart"
        gutterSize="m"
        alignItems="center"
      >
        <EuiFlexItem grow={false}>
          <EuiCode>{value}</EuiCode>
        </EuiFlexItem>
        <EuiFlexItem grow={false}>
          <EuiButton onClick={reGenerate}>Regenerate</EuiButton>
        </EuiFlexItem>
      </EuiFlexGroup>
    </Fragment>
  );
};
```
</Demo>

## ID generator with prefix

Provide a `prefix` to the generator to get an ID that starts with the specified prefix.

<Demo>
```tsx interactive
import React, { useState, Fragment } from 'react';

import {
  EuiFieldText,
  EuiFlexGroup,
  EuiFlexItem,
  EuiSpacer,
  EuiCode,
  EuiFormRow,
  htmlIdGenerator,
} from '@elastic/eui';

export default () => {
  const [prefix, setPrefix] = useState('Id');
  const [customId, setCustomId] = useState(htmlIdGenerator('Id')());

  const onSearchChange = (e) => {
    const prefix = e.target.value;
    setPrefix(prefix);
    setCustomId(htmlIdGenerator(prefix)());
  };

  return (
    <Fragment>
      <EuiFlexGroup
        justifyContent="flexStart"
        gutterSize="m"
        alignItems="center"
      >
        <EuiFlexItem grow={false}>
          <EuiFormRow label="Prefix">
            <EuiFieldText
              value={prefix}
              onChange={onSearchChange}
              placeholder="Enter prefix"
            />
          </EuiFormRow>
        </EuiFlexItem>
      </EuiFlexGroup>
      <EuiSpacer size="xl" />
      <EuiCode>{customId} </EuiCode>
    </Fragment>
  );
};
```
</Demo>

## ID generator with suffix

Provide a `suffix` to the generator to get an ID that starts with the specified suffix.

<Demo>
```tsx interactive
import React, { useState, Fragment } from 'react';

import {
  EuiFieldText,
  EuiFlexGroup,
  EuiFlexItem,
  EuiSpacer,
  EuiCode,
  EuiFormRow,
  htmlIdGenerator,
} from '@elastic/eui';

export default () => {
  const [suffix, setSuffix] = useState('Id');
  const [customId, setCustomId] = useState(htmlIdGenerator()('Id'));

  const onSuffixChange = (e) => {
    const suffix = e.target.value;
    setSuffix(suffix);
    setCustomId(htmlIdGenerator()(suffix));
  };

  return (
    <Fragment>
      <EuiFlexGroup
        justifyContent="flexStart"
        gutterSize="m"
        alignItems="center"
      >
        <EuiFlexItem grow={false}>
          <EuiFormRow label="Suffix">
            <EuiFieldText
              value={suffix}
              onChange={onSuffixChange}
              placeholder="Enter suffix"
            />
          </EuiFormRow>
        </EuiFlexItem>
      </EuiFlexGroup>
      <EuiSpacer size="xl" />
      <EuiCode>{customId} </EuiCode>
    </Fragment>
  );
};
```
</Demo>

## ID generator with both prefix and suffix

The `htmlIdGenerator` is capable of generating an ID with both a specified prefix **and** suffix.

<Demo>
```tsx interactive
import React, { useState, Fragment } from 'react';

import {
  EuiFieldText,
  EuiFlexGroup,
  EuiFlexItem,
  EuiSpacer,
  EuiCode,
  EuiFormRow,
  htmlIdGenerator,
} from '@elastic/eui';

export default () => {
  const [prefix, setPrefix] = useState('Some');
  const [suffix, setSuffix] = useState('Id');
  const [customId, setCustomId] = useState(htmlIdGenerator('Some')('Id'));

  const onPrefixChange = (e) => {
    const prefix = e.target.value;
    setPrefix(prefix);
    setCustomId(htmlIdGenerator(prefix)(suffix));
  };

  const onSuffixChange = (e) => {
    const suffix = e.target.value;
    setSuffix(suffix);
    setCustomId(htmlIdGenerator(prefix)(suffix));
  };

  return (
    <Fragment>
      <EuiFlexGroup
        justifyContent="flexStart"
        gutterSize="m"
        alignItems="center"
      >
        <EuiFlexItem grow={false}>
          <EuiFormRow label="Prefix">
            <EuiFieldText
              value={prefix}
              onChange={onPrefixChange}
              placeholder="Enter prefix"
            />
          </EuiFormRow>
        </EuiFlexItem>
        <EuiFlexItem grow={false}>
          <EuiFormRow label="Suffix">
            <EuiFieldText
              value={suffix}
              onChange={onSuffixChange}
              placeholder="Enter suffix"
            />
          </EuiFormRow>
        </EuiFlexItem>
      </EuiFlexGroup>
      <EuiSpacer size="xl" />
      <EuiCode>{customId} </EuiCode>
    </Fragment>
  );
};
```
</Demo>

## Reusing the generator for multiple IDs

As you may have noticed, `htmlIdGenerator` is a curried function. This means you can reuse the original `htmlIdGenerator()` call to generate multiple IDs. Additionally, if you pass in suffixes to your second call, the generated ID(s) will share the same unique ID.

<Demo>
```tsx interactive
import React from 'react';

import { EuiCode, htmlIdGenerator } from '@elastic/eui';

const generateId = htmlIdGenerator('test');

export default () => {
  return (
    <>
      <EuiCode>{generateId()}</EuiCode>
      <br />
      <EuiCode>{generateId()}</EuiCode>
      <br />
      <EuiCode>{generateId()}</EuiCode>
      <br />
      <EuiCode>{generateId('hello')}</EuiCode>
      <br />
      <EuiCode>{generateId('world')}</EuiCode>
    </>
  );
};
```
</Demo>

## Memoized hook for component use

`useGeneratedHtmlId` is a custom React hook that automatically memoizes a randomly generated ID, preventing the ID from regenerating on every component rerender. The ID will only change if the component fully unmounts/mounts, or if you dynamically pass in new hook arguments.

Please note that unlike `htmlIdGenerator`, `useGeneratedHtmlId` is a single function and does not support generating multiple IDs that share the same unique ID. It is instead best used for simple one-off IDs, rather than groups of them.

<Demo>
```tsx interactive
import React, { useState, Fragment } from 'react';

import { EuiSwitch, EuiSpacer, EuiCode, useGeneratedHtmlId } from '@elastic/eui';

export default () => {
  const generatedId = useGeneratedHtmlId({ prefix: 'Some', suffix: 'id' });

  const [isChecked, setIsChecked] = useState(false);

  const onChange = (e) => setIsChecked(e.target.checked);

  return (
    <Fragment>
      <EuiSwitch
        label="Clicking me changes component state"
        checked={isChecked}
        onChange={onChange}
      />
      <EuiSpacer size="xl" />
      <EuiCode>{generatedId} </EuiCode>
    </Fragment>
  );
};
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/services/accessibility';

<PropTable definition={docgen.useGeneratedHtmlId} />

---

### Packages Website Docs Utilities I18n (`packages/website/docs/utilities/i18n.mdx`)

---
keywords: [EuiI18n, useEuiI18n]
---

# I18n

Translations for EUI components can be provided globally in an application via [EuiContext, documented below](#context). All available `tokens` —also usually called ids— can be found in [this automatically generated JSON file](https://github.com/elastic/eui/blob/main/packages/eui/i18ntokens.json).

While developing an EUI component, any text that is included by default must be translatable. [EuiI18n](#internalization) is the proper way to do this. Examples of such text are the `aria-label` in the clear button of [EuiComboBox](#TODO), or the visible text in [EuiPagination](#TODO) compressed e.g. "1 of 24".

:::warning These utilities are mostly internal
The purpose of these utilities is to allow internationalizing EUI components. This is not a full-fledged solution for internationalizing your app.
:::

## Internalization

**useEuiI18n** and **EuiI18n** allows localizing string and numeric values for internationalization. There are two provided ways to use this: a React hook and a render prop component. In their simplest form, these take a `token` and a `default` value. `token` provides a reference to use when mapping to a localized value and `default` provides the untranslated value when no mapping is available.

<Demo>
```tsx interactive
import React from 'react';

import { EuiI18n, EuiTitle, EuiSpacer, useEuiI18n } from '@elastic/eui';

export default () => {
  return (
    <>
      <EuiTitle size="xs">
        <h3>Basic useEuiI18n usage</h3>
      </EuiTitle>
      <p>
        {useEuiI18n(
          'euiI18nBasic.basicexample',
          'This is the English copy that would be replaced by a translation defined by the i18n.basicexample token.'
        )}
      </p>
      <EuiSpacer size="l" />
      <EuiTitle size="xs">
        <h3>Basic EuiI18n usage</h3>
      </EuiTitle>
      <p>
        <EuiI18n
          token="euiI18nBasic.basicexample"
          default="This is the English copy that would be replaced by a translation defined by the i18n.basicexample token."
        />
      </p>
    </>
  );
};
```
</Demo>

## Interpolation

**useEuiI18n** and **EuiI18n** support variable interpolation. In a translation like `Signed in as {name} ({email})`, two values can be interpolated (`name` and `email`). These values can be specified by passing a `values` prop to **EuiI18n**, or by passing an object of values as the third argument to **useEuiI18n**. Interpolation values can be passed as a string, number, or a React Component.

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Using localized values in attributes

Some times a localized value is needed for a prop instead of rendering directly to the DOM. In these cases **useEuiI18n** can be called inline, or **EuiI18n** can be used as a render prop child which is called with the localized value.

<Demo>
```tsx interactive
import React from 'react';

import {
  EuiCode,
  EuiFieldText,
  EuiI18n,
  EuiFormRow,
  EuiTitle,
  useEuiI18n,
  EuiSpacer,
} from '@elastic/eui';

export default () => {
  return (
    <>
      <EuiTitle size="xs">
        <h3>useEuiI18n used in an attribute</h3>
      </EuiTitle>
      <EuiSpacer />
      <EuiFormRow
        label={
          <>
            This text field&apos;s placeholder reads from{' '}
            <EuiCode>euiI18nAttribute.placeholderName</EuiCode>
          </>
        }
      >
        <EuiFieldText
          placeholder={useEuiI18n(
            'euiI18nAttribute.placeholderName',
            'John Doe'
          )}
        />
      </EuiFormRow>
      <EuiSpacer size="xl" />
      <EuiTitle size="xs">
        <h3>EuiI18n used as a render prop</h3>
      </EuiTitle>
      <EuiSpacer />
      <EuiI18n token="euiI18nAttribute.placeholderName" default="John Doe">
        {(placeholderName) => (
          <EuiFormRow
            label={
              <>
                This text field&apos;s placeholder reads from{' '}
                <EuiCode>euiI18nAttribute.placeholderName</EuiCode>
              </>
            }
          >
            <EuiFieldText placeholder={placeholderName} />
          </EuiFormRow>
        )}
      </EuiI18n>
    </>
  );
};
```
</Demo>

## Multi-value lookup

If many localized values are needed in a small area, multiple tokens can be retrieved from the hook or via a single render prop. In this case the `token`/`default` props are replaced by the pluralized `tokens`/`defaults`. Value injection is not supported when processing more than one token.

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Number localization

**EuiI18nNumber** can be used to format one or more numbers. Similarly to **EuiI18n**, it takes `value` or `values` and can render directly to the DOM or call a render prop.

<Demo>
```tsx interactive
import React from 'react';

import { EuiI18nNumber } from '@elastic/eui';

export default () => {
  return (
    <p>
      Formatted count of users: <EuiI18nNumber value={5000000} />
    </p>
  );
};
```
</Demo>

## Context

`EuiContext` allows setting global internationalization copy for EUI components. Any components used within this context will lookup their display values from this mapping.

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components';

<PropTable definition={docgen.EuiI18n} />
<PropTable definition={docgen.EuiContext} />

---

### Packages Website Docs Utilities Inner Text (`packages/website/docs/utilities/inner-text.mdx`)

---
keywords: [EuiInnerText, useInnerText]
---

# Inner text

For instances where accessing the text content of a component that may be wrapped or interspersed with other components, two utilities are available:

* `useInnerText` - A custom React hook, usable in function components
* `<EuiInnerText />` - A higher order `useInnerText` component for use in class components

Both utilities make available a `ref` reference to add to the target DOM element, and the resulting `innerText` value to use as needed.

## Rendered

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/inner_text';

<PropTable definition={docgen.EuiInnerText} />

---

### Packages Website Docs Utilities Mutation Observer (`packages/website/docs/utilities/mutation-observer.mdx`)

---
keywords: [EuiMutationObserver]
---

# Mutation observer

**EuiMutationObserver** is a wrapper around the <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver" target="_blank" rel="noopener noreferrer">Mutation Observer API</a> which allows watching for DOM changes to elements and their children. **EuiMutationObserver** takes the same configuration object as the browser API to describe what to watch for, and fires the callback when that mutation happens.

This is a render prop component, **EuiMutationObserver** will pass a `ref` callback which you must put on the element you wish to observe the mutations.

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/observer/mutation_observer';

<PropTable definition={docgen.EuiMutationObserver} />

---

### Packages Website Docs Utilities Outside Click Detector (`packages/website/docs/utilities/outside-click-detector.mdx`)

---
keywords: [EuiOutsideClickDetector]
---

# Outside click detector

Use **EuiOutsideClickDetector** to trigger a handler when the user clicks outside of the child element.

:::warning
**EuiSelect** normalizes browser event inconsistencies with `<select />` elements and as a result may not trigger **EuiOutsideClickDetector** when targeted with mouse events.
:::

<Demo>
```tsx interactive
import React, { useState } from 'react';

import { EuiButton, EuiOutsideClickDetector, EuiSpacer } from '@elastic/eui';

export default () => {
  const [isDisabled, setIsDisabled] = useState(false);

  const toggleDisabled = () => {
    setIsDisabled(!isDisabled);
  };

  return (
    <div>
      <EuiOutsideClickDetector
        onOutsideClick={() => {
          window.alert('Clicked outside');
        }}
        isDisabled={isDisabled}
      >
        <p>
          {isDisabled
            ? 'This detector is disabled, so clicking outside will do nothing.'
            : 'Clicking inside here will do nothing, but clicking outside will trigger an alert.'}
        </p>
      </EuiOutsideClickDetector>
      <EuiSpacer size="l" />
      <EuiButton onClick={toggleDisabled}>
        {isDisabled ? 'Enable' : 'Disable'} the detector
      </EuiButton>
    </div>
  );
};
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/outside_click_detector';

<PropTable definition={docgen.EuiOutsideClickDetector} />

---

### Packages Website Docs Utilities Overlay Mask (`packages/website/docs/utilities/overlay-mask.mdx`)

---
keywords: [EuiOverlayMask]
---

# Overlay mask

**EuiOverlayMask** is simply a display component used to obscure the main content to bring attention to its children or other content. It is best used in conjunction with hyper-focus content areas like [modals](../components/containers/modal/index.mdx) and [flyouts](../components/containers/flyout/index.mdx).

There are <a href="https://www.nngroup.com/articles/overuse-of-overlays/" target="_blank" rel="noopener noreferrer">many considerations</a> to make before choosing to use an overlay. At the very least, you must provide a visible button to close the overlay. You can also nest an [EuiFocusTrap](./focus-trap/index.mdx) to handle closing the overlay.

<Demo>
```tsx interactive
import React, { useState } from 'react';

import {
  EuiOverlayMask,
  EuiButton,
  EuiSpacer,
  EuiTitle,
  EuiFocusTrap,
} from '@elastic/eui';

export default () => {
  const [maskOpen, changeMask] = useState(false);
  const [maskWithClickOpen, changeMaskWithClick] = useState(false);

  const modal = (
    <>
      <EuiOverlayMask>
        <EuiFocusTrap onClickOutside={() => changeMask(false)}>
          <EuiTitle>
            <h2> Click anywhere to close overlay. </h2>
          </EuiTitle>
        </EuiFocusTrap>
      </EuiOverlayMask>
    </>
  );

  const maskWithClick = (
    <EuiOverlayMask data-test-subj="yolo">
      <EuiButton onClick={() => changeMaskWithClick(false)}>
        Click this button to close
      </EuiButton>
    </EuiOverlayMask>
  );

  return (
    <>
      <EuiButton onClick={() => changeMaskWithClick(true)}>
        Overlay with button
      </EuiButton>
      <EuiSpacer size="xxl" />
      <EuiButton onClick={() => changeMask(true)}>
        Overlay with EuiFocusTrap click-to-close
      </EuiButton>
      {maskOpen ? modal : undefined}
      {maskWithClickOpen ? maskWithClick : undefined}
    </>
  );
};
```
</Demo>

## Masks with header

Managing z-index levels of multiple portal-positioned components and their different contexts is complicated from within the library. **EuiOverlayMask** gives you control over whether it should appear below or above an [EuiHeader](../components/layout/header.mdx) by providing the `headerZindexLocation` prop. By default this is set to `"above"` for common cases like with [EuiModal](../components/containers/modal/index.mdx) where the header should be obscured. However, a component like [EuiFlyout](../components/containers/flyout/index.mdx) which utilizes the overlay mask but should keep the header visible should use `"below"` (which is its default value).

## Props

import docgen from '@elastic/eui-docgen/dist/components/overlay_mask';

export const euiOverlayMaskOwnProps = [
  'children',
  'headerZindexLocation',
  'maskRef',
  'hasAnimation',
].reduce(
  (props, propName) => ({
    ...props,
    [propName]: docgen.EuiOverlayMask.props[propName],
  }),
  {}
);

<PropTable
  definition={{
    ...docgen.EuiOverlayMask,
    extends: [],
    props: euiOverlayMaskOwnProps,
  }}
/>

---

### Packages Website Docs Utilities Portal (`packages/website/docs/utilities/portal.mdx`)

---
keywords: [EuiPortal]
---

# Portal

**EuiPortal** allows you to append its contained children onto the document body. It is useful for moving fixed elements like modals, tooltips or toasts when you are worried about a z-index or overflow conflict.

<Demo>
```tsx interactive
import React, { useState } from 'react';

import { EuiPortal, EuiButton, EuiBottomBar } from '@elastic/eui';

export default () => {
  const [isPortalVisible, setIsPortalVisible] = useState(false);

  const togglePortal = () => {
    setIsPortalVisible(!isPortalVisible);
  };

  let portal;

  if (isPortalVisible) {
    portal = (
      <EuiPortal>
        <EuiBottomBar>
          <p>This element is appended to the body in the DOM if you inspect</p>
        </EuiBottomBar>
      </EuiPortal>
    );
  }

  return (
    <div>
      <EuiButton onClick={togglePortal}>Toggle portal</EuiButton>
      {portal}
    </div>
  );
};
```
</Demo>

## Inserting portals

There is an optional `insert` prop that can specify the portal's location in the DOM. When used, it is important to consider how the location relates to the component lifecycle, as it could be removed from the DOM by another component update.

`insert` is an object with two key-value pairs: `sibling` and `position`. `sibling` is the React node or HTMLElement to insert the portal next to, and `position` specifies the portal's relative position, either `before` or `after`.

<Demo>
```tsx interactive
import React, { useState } from 'react';

import { EuiPortal, EuiButton, EuiSpacer } from '@elastic/eui';

let buttonRef = null;

export default () => {
  const [isPortalVisible, setIsPortalVisible] = useState(false);

  const setButtonRef = (node) => (buttonRef = node);

  const togglePortal = () => {
    setIsPortalVisible(!isPortalVisible);
  };

  let portal;

  if (isPortalVisible) {
    portal = (
      <EuiPortal insert={{ sibling: buttonRef, position: 'after' }}>
        <EuiSpacer />
        <p>This element is appended immediately after the button.</p>
      </EuiPortal>
    );
  }

  return (
    <div>
      <EuiButton onClick={togglePortal} buttonRef={setButtonRef}>
        Toggle portal
      </EuiButton>
      {portal}
    </div>
  );
};
```
</Demo>

## A custom flyout

Custom flyouts should only be implemented if your design diverges a lot from [EuiFlyout](../components/containers/flyout/index.mdx). You need to implement accessibility features, which can be challenging.

**Here are some accessibility considerations you should keep in mind when implementing a custom flyout.**

* Use [EuiFocusTrap](./focus-trap/index.mdx) to prevent keyboard-initiated focus from leaving the flyout.
* If you use a [EuiOverlayMask](./overlay-mask.mdx), it should be dismissed when clicked outside. For that you can pass to your [EuiFocusTrap](./focus-trap/index.mdx) `onClickOutside` prop a method to close the flyout.
* When pressing the ESC key your flyout should close. Use a [EuiWindowEvent](./window-events/index.mdx) to listen for the key down event.
* Pass an ID to the first heading in the flyout `id={headingId}`.
* Pass to your [EuiPanel](../components/containers/panel/index.mdx) `aria-labelledby={headingId}` to announce the flyout to screen readers.

You should also take into account some design considerations:

* Use a [EuiPanel](../components/containers/panel/index.mdx) for the background.
* A flyout should always have a close button on the right top corner. This gives a visual clue that the flyout can be closed.
* For writing CSS consider using our theme tokens.

In the following demo, you can see how to create your own flyout with all the recommended accessibility and design features:

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/portal';

<PropTable definition={docgen.EuiPortal} />

---

### Packages Website Docs Utilities Pretty Duration (`packages/website/docs/utilities/pretty-duration.mdx`)

---
keywords: [usePrettyDuration]
---

# Pretty duration

Use the `<PrettyDuration />` component (for JSX display) or `usePrettyDuration()` hook (for attribute strings) to convert a start and end date string to a human-friendly format. Both utilities take the following props:

* `timeFrom` and `timeTo` accept start and end date values for the duration. These can be timestamps (`2018-01-17T18:57:57.149Z`) or relative times (`now-15m`).

* `dateFormat` specifies the output date/time format.

* `quickRanges` optionally accepts an array of quick range values that are used to pretty format custom ranges. If no custom quick ranges are passed, EUI will default to a set of common duration ranges defined below.

<details style={{ marginTop: 16 }}>
<summary>Show default common duration ranges</summary>
```json
[
  {
    "start": "now/d",
    "end": "now/d",
    "label": "Today"
  },
  {
    "start": "now/w",
    "end": "now/w",
    "label": "This week"
  },
  {
    "start": "now/M",
    "end": "now/M",
    "label": "This month"
  },
  {
    "start": "now/y",
    "end": "now/y",
    "label": "This year"
  },
  {
    "start": "now-1d/d",
    "end": "now-1d/d",
    "label": "Yesterday"
  },
  {
    "start": "now/w",
    "end": "now",
    "label": "Week to date"
  },
  {
    "start": "now/M",
    "end": "now",
    "label": "Month to date"
  },
  {
    "start": "now/y",
    "end": "now",
    "label": "Year to date"
  }
]
```
</details>

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/date_picker';

<PropTable definition={docgen.usePrettyDuration} />

---

### Packages Website Docs Utilities Resize Observer (`packages/website/docs/utilities/resize-observer.mdx`)

---
keywords: [EuiResizeObserver]
---

# Resize observer

**EuiResizeObserver** is a wrapper around the <a href="https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver" target="_blank" rel="noopener noreferrer">**Resizer Observer API**</a> which allows watching for changes to the content rectangle of DOM elements. Unlike [EuiMutationObserver](./mutation-observer.mdx), **EuiResizeObserver** does not take parameters, but it does fire a more efficient and informative callback when resize events occur.

This is a render prop component, **EuiResizeObserver** will pass a `ref` callback which you must put on the element you wish to observe.

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## useResizeObserver hook

There is also a React hook, `useResizeObserver`, which provides the same observation functionality.

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/observer/resize_observer';

<PropTable definition={docgen.EuiResizeObserver} />

---

### Packages Website Docs Utilities Text Diff (`packages/website/docs/utilities/text-diff.mdx`)

---
keywords: [useEuiTextDiff]
---

# Text diff

The hook, useEuiTextDiff, generates a set of changes between two strings. It returns both React elements for displaying the diff and an object representing the identified changes. The timeout prop is used to set how many seconds any diff's exploration phase may take. The default value is 0.1, a value of 0 disables the timeout and lets diff run until completion. The higher the timeout, the more detailed the comparison.

`const [rendered, textDiffObject] = useEuiTextDiff({ beforeText, afterText });`

<Demo>
```tsx interactive
import React, { useState, useEffect } from 'react';

import {
  useEuiTextDiff,
  EuiCode,
  EuiSpacer,
  EuiTextColor,
  EuiText,
} from '@elastic/eui';

export default () => {
  const [del, setDel] = useState(0);
  const [ins, setIns] = useState(0);

  const beforeText =
    'Orbiting this at a distance of roughly ninety-two million miles is an utterly insignificant little blue green planet whose ape- descended life forms are so amazingly primitive that they still think digital watches are a pretty neat idea.';
  const afterText =
    'Orbiting those at a distance of roughly ninety-nine billion yards is not insignificant dwarf red green planet whose ape- ascended life forms are so amazingly primitive that they still think digital clocks are a pretty neat idea.';

  const [rendered, textDiffObject] = useEuiTextDiff({
    beforeText,
    afterText,
  });

  useEffect(() => {
    textDiffObject.forEach((el) => {
      if (el[0] === 1) {
        setIns((add) => add + 1);
      } else if (el[0] === -1) {
        setDel((sub) => sub + 1);
      }
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <>
      <EuiText>
        <p>{rendered}</p>
      </EuiText>
      <EuiSpacer />
      <EuiCode>
        <EuiTextColor color="success"> {ins} </EuiTextColor> Insertions,
        <EuiTextColor color="danger"> {del} </EuiTextColor>
        Deletions
      </EuiCode>
    </>
  );
};
```
</Demo>

## Custom rendered elements

By default, the hook will wrap deletions with `<del>` and insertions with `<ins>` elements. You can replace these elements with the `deleteComponent` and `insertComponent` props respectively.

Also, since `rendered` is simple html string, you can wrap it in any contextual element like [EuiText](../components/display/text.mdx) or [EuiCodeBlock](../components/display/code.mdx#code-block).

<Demo>
```tsx interactive
import React from 'react';

import { useEuiTextDiff, EuiCodeBlock } from '@elastic/eui';

export default () => {
  const beforeText =
    'Orbiting this at a distance of roughly ninety-two million miles is an utterly insignificant little blue green planet whose ape- descended life forms are so amazingly primitive that they still think digital watches are a pretty neat idea.';
  const afterText =
    'Orbiting those at a distance of roughly ninety-nine billion yards is not insignificant dwarf red green planet whose ape- ascended life forms are so amazingly primitive that they still think digital clocks are a pretty neat idea.';

  const [rendered] = useEuiTextDiff({
    beforeText,
    afterText,
    insertComponent: 'strong',
    deleteComponent: 's',
  });

  return (
    <EuiCodeBlock fontSize="m" paddingSize="m">
      {rendered}
    </EuiCodeBlock>
  );
};
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/text_diff';

<PropTable definition={docgen.useEuiTextDiff} />

---

### Packages Website Docs Utilities Text Truncation (`packages/website/docs/utilities/text-truncation.mdx`)

---
keywords: [EuiTextTruncate]
---

# Text truncation

import { throttle } from 'lodash';
import { faker } from '@faker-js/faker';
import { FixedSizeList } from 'react-window';

## Single line

**EuiTextTruncate** provides customizable and size-aware single line text truncation.

The four truncation styles supported are `start`, `end`, `startEnd`, and `middle`. Resize the below demo to see how different truncation styles respond to dynamic width changes.

<Demo>
```tsx interactive
import React from 'react';
import { css } from '@emotion/react';

import { EuiPanel, EuiText, EuiTextTruncate } from '@elastic/eui';

export default () => {
  return (
    <EuiText>
      <EuiPanel
        css={css`
          overflow: auto;
          resize: horizontal; /* Not all browsers support resize logical properties yet */
          resize: inline;
          inline-size: 35ch;
          max-inline-size: 100%;
        `}
      >
        <EuiTextTruncate
          text="The quick brown fox jumps over the lazy dog."
          truncation="start"
        />
        <EuiTextTruncate
          text="But the dog wasn’t lazy, it was just practicing mindfulness, so it had a greater sense of life-satisfaction than that fox with all its silly jumping."
          truncation="end"
        />
        <EuiTextTruncate
          text="And from the fox’s perspective, life was full of hoops to jump through, low-hanging fruit to jump for, and dead car batteries to jump-start."
          truncation="startEnd"
        />
        <EuiTextTruncate
          text="So it thought the dog was making a poor life choice by focusing so much on mindfulness. What if its car broke down?"
          truncation="middle"
        />
      </EuiPanel>
    </EuiText>
  );
};
```
</Demo>

:::info Accessibility and comparison to text-overflow

**EuiTextTruncate** attempts to mimic the behavior of `text-overflow: ellipsis` as closely as possible, although there may be edge cases and cross-browser issues, as this is essentially <a href="https://github.com/w3c/csswg-drafts/issues/3937" target="_blank" rel="noopener noreferrer">**a browser implementation**</a> we are trying to polyfill.

* Screen readers should ignore the truncated text and only read out the full text.

* Sighted mouse users will be able to briefly hover over the truncated text and read the full text in a tooltip. Use `toolTipProps` to control where it opens, e.g. its `position`.

* For mouse users, double clicking to select the truncated line should allow copying the full untruncated text.
:::

### Custom ellipsis

By default, **EuiTextTruncate** uses the unicode character for horizontal ellipsis. It can be customized via the `ellipsis` prop as necessary (e.g. for specific languages, extra punctuation, etc).

<Demo>
```tsx interactive
import React from 'react';

import { EuiPanel, EuiText, EuiTextTruncate } from '@elastic/eui';

export default () => {
  return (
    <EuiText>
      <EuiPanel css={{ inlineSize: '40ch', maxInlineSize: '100%' }}>
        <EuiTextTruncate
          text="Opinions differ as to how to render ellipses in printed material. According to The Chicago Manual of Style, it should consist of three periods, each separated from its neighbor by a non-breaking space. According to the AP Stylebook, the periods should be rendered with no space between them."
          ellipsis=". . ."
        />
        <EuiTextTruncate
          text="In some legal writing, an ellipsis is written as three asterisks, to make it obvious that text has been omitted or to signal that the omitted text extends beyond the end of the paragraph."
          ellipsis=" ***"
        />
        <EuiTextTruncate
          text="Brackets are often used to indicate that a quotation has been condensed for space, brevity or relevance."
          truncation="middle"
          ellipsis="[...]"
        />
      </EuiPanel>
    </EuiText>
  );
};
```
</Demo>

### Truncation offset

The `start` and `end` truncation types support a `truncationOffset` property that allows preserving a specified number of characters at either the start or end of the text. Increase or decrease the number control below to see the prop in action.

<Demo>
```tsx interactive
import React, { useState } from 'react';

import {
  EuiPanel,
  EuiFormRow,
  EuiFieldNumber,
  EuiSpacer,
  EuiText,
  EuiTextTruncate,
} from '@elastic/eui';

export default () => {
  const [truncationOffset, setTruncationOffset] = useState(3);

  return (
    <EuiText>
      <EuiFormRow label="Truncation offset">
        <EuiFieldNumber
          compressed
          value={truncationOffset}
          onChange={(e) => setTruncationOffset(Number(e.target.value))}
          max={30}
        />
      </EuiFormRow>
      <EuiSpacer />
      <EuiPanel css={{ inlineSize: '40ch', maxInlineSize: '100%' }}>
        <EuiTextTruncate
          text="But the dog wasn’t lazy, it was just practicing mindfulness, so it had a greater sense of life-satisfaction than that fox with all its silly jumping."
          truncation="start"
          truncationOffset={truncationOffset}
        />
        <EuiTextTruncate
          text="And from the fox’s perspective, life was full of hoops to jump through, low-hanging fruit to jump for, and dead car batteries to jump-start."
          truncation="end"
          truncationOffset={truncationOffset}
        />
      </EuiPanel>
    </EuiText>
  );
};
```
</Demo>

### Truncation position

The `startEnd` truncation type supports a `truncationPosition` property. By default, `startEnd` anchors the displayed text to the middle of the string. However, you may prefer to display a specific subsection of the full text closer to the start or end, which this prop allows.

This behavior will intelligently detect when positions are near enough to the start or end of the text to omit leading or trailing ellipses when necessary.

Increase or decrease the number control below to see the prop in action.

<Demo>
```tsx interactive
import React, { useState } from 'react';

import {
  EuiPanel,
  EuiFormRow,
  EuiFieldNumber,
  EuiSpacer,
  EuiText,
  EuiTextTruncate,
} from '@elastic/eui';

export default () => {
  const [truncationPosition, setTruncationPosition] = useState(45);

  return (
    <EuiText>
      <EuiFormRow label="Truncation position">
        <EuiFieldNumber
          compressed
          value={truncationPosition}
          onChange={(e) => setTruncationPosition(Number(e.target.value))}
        />
      </EuiFormRow>
      <EuiSpacer />
      <EuiPanel css={{ inlineSize: '40ch', maxInlineSize: '100%' }}>
        <EuiTextTruncate
          text="But the dog wasn’t lazy, it was just practicing mindfulness, so it had a greater sense of life-satisfaction than that fox with all its silly jumping."
          truncation="startEnd"
          truncationPosition={truncationPosition}
        />
      </EuiPanel>
    </EuiText>
  );
};
```
</Demo>

### Render prop

By default, **EuiTextTruncate** will automatically output the calculated truncated string. You can optionally override this by passing a render prop function to `children`, which allows for more flexible text rendering.

The below example demonstrates a primary use case for the render prop and the `truncationPosition` prop. If a user is searching for a specific word in truncated text, you can use [EuiHighlight](./highlight-and-mark.mdx#highlight) or [EuiMark](./highlight-and-mark.mdx#mark) to highlight the search term, and passing the index of the found word to `truncationPosition` ensures the search term is always visible to the user.

:::warning
Do not render excessive extra content alongside the text. The sizing logic will not account for it, and the truncation calculations will be off.
:::

<Demo>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

### Performance

**EuiTextTruncate** uses a canvas element under the hood to manipulate text and calculate whether the text width fits within the available width. Additionally, by default, the component will include its own resize observer in order to react to width changes.

These functionalities can cause performance issues if the component is rendered over hundreds of times per page, and we would strongly recommend using caution when doing so. Several escape hatches are available for performance improvements:

1. Pass a `width` prop to skip initializing a resize observer for each component instance. For text within a container of the same width, we would strongly recommend applying a single resize observer to the parent container and passing that width to all child **EuiTextTruncates**. Additionally, you may want to consider <a href="https://lodash.com/docs/#throttle" target="_blank" rel="noopener noreferrer">**throttling**</a> any resize observers or width-based logic.

2. Use <a href="https://github.com/bvaughn/react-window" target="_blank" rel="noopener noreferrer">**virtualization**</a> to reduce the number of rendered elements visible at any given time. For over hundreds of instances, this will generally be the most effective solution for performance or rerender issues.

3. If necessary, consider pulling out the underlying `TruncationUtils` and re-using the same canvas context, as opposed to repeatedly creating new ones.

<Demo scope={{ FixedSizeList, faker, throttle }}>
```
/* Detailed source-code truncated for AI context efficiency. */
```
</Demo>

## Multi line

**EuiTextBlockTruncate** allows truncating text after a set number of wrapping `lines`.

Please note: This component is currently a quick shortcut for <a href="https://css-tricks.com/line-clampin/" target="_blank" rel="noopener noreferrer">**the CSS `line-clamp`**</a> property. This means that truncating at the end of the text is the default, and there are currently no plans to add JavaScript customization for this behavior.

<Demo>
```tsx interactive
import React from 'react';
import { css } from '@emotion/react';
import { faker } from '@faker-js/faker';

import { EuiPanel, EuiText, EuiTextBlockTruncate } from '@elastic/eui';

export default () => {
  return (
    <EuiText>
      <EuiPanel
        css={css`
          overflow: auto;
          resize: horizontal; /* Not all browsers support resize logical properties yet */
          resize: inline;
          inline-size: 50ch;
          max-inline-size: 100%;
        `}
      >
        <EuiTextBlockTruncate lines={3}>
          {faker.lorem.lines(10)}
        </EuiTextBlockTruncate>
      </EuiPanel>
    </EuiText>
  );
};
```
</Demo>

## Props

import docgen from '@elastic/eui-docgen/dist/components/text_truncate';

<PropTable definition={docgen.EuiTextTruncate} />
<PropTable definition={docgen.EuiTextBlockTruncate} />

---

### Packages Website Docs Components Containers Accordion (`packages/website/docs/components/containers/accordion.mdx`)

---
keywords: [EuiAccordion]
---

# Accordion

**EuiAccordion** has been purposely designed with minimal styles, allowing you to visually enhance it as needed (see the accordion form example). The only styling enforced by EUI is the caret icon, which indicates to users that the item can be opened.

A `buttonContent` prop defines the content of the clickable area. On click it will expose the children and animate based on the height of those children.

For styling needs, classes can be individually applied with `className` (for the entire accordion), and `buttonClassName` (for the clickable area).

## Component

```tsx interactive
import React from 'react';
import { EuiAccordion, EuiPanel, useGeneratedHtmlId } from '@elastic/eui';

export default () => {
  const simpleAccordionId = useGeneratedHtmlId({ prefix: 'simpleAccordion' });

  return (
    <div>
      <EuiAccordion id={simpleAccordionId} buttonContent="Click me to toggle">
        <EuiPanel color="subdued">
          Any content inside of <strong>EuiAccordion</strong> will appear here.
        </EuiPanel>
      </EuiAccordion>
    </div>
  );
};
```

## Usage

### Arrow display

The arrow helps indicate the current state of the accordion (open or not) and points to the main triggering button text. If you must hide or change the side in which the arrow appears, use `arrowDisplay: 'right'` or `'none'`

```tsx interactive
import React from 'react';
import { EuiAccordion, EuiPanel, useGeneratedHtmlId } from '@elastic/eui';

export default () => {
  const rightArrowAccordionId = useGeneratedHtmlId({
    prefix: 'rightArrowAccordion',
  });

  return (
    <EuiAccordion
      id={rightArrowAccordionId}
      arrowDisplay="right"
      buttonContent="This accordion has the arrow on the right"
    >
      <EuiPanel color="subdued">
        Any content inside of <strong>EuiAccordion</strong> will appear here.
      </EuiPanel>
    </EuiAccordion>
  );
};
```

```tsx interactive
import React from 'react';
import { EuiAccordion, EuiPanel, useGeneratedHtmlId } from '@elastic/eui';

export default () => {
  const noArrowAccordionId = useGeneratedHtmlId({ prefix: 'noArrowAccordion' });

  return (
    <EuiAccordion
      id={noArrowAccordionId}
      arrowDisplay="none"
      buttonContent="This one has it removed entirely"
    >
      <EuiPanel color="subdued">
        Any content inside of <strong>EuiAccordion</strong> will appear here.
      </EuiPanel>
    </EuiAccordion>
  );
};
```

### Multiple accordions

Use any number of **EuiAccordion** elements to visually display them as a group.

Due to the previously mentioned bare styles, it is recommended to place an [EuiSpacer](../layout/spacer/index.mdx) between accordion items. Padding within each accordion item can be applied via the `paddingSize` prop.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Extra actions

Use the `extraAction` prop to pass an extra action displayed on the right of any accordion. Usually this is a delete or button, but can be anything. Note that this action is separate from the click state that expands the accordion. This is needed to make it accessible.

```tsx interactive
import React from 'react';
import { EuiAccordion, EuiButton, useGeneratedHtmlId } from '@elastic/eui';

export default () => {
  const extraActionAccordionId = useGeneratedHtmlId({
    prefix: 'extraActionAccordion',
  });

  return (
    <EuiAccordion
      id={extraActionAccordionId}
      buttonContent="Click to open"
      extraAction={<EuiButton size="s">Extra action!</EuiButton>}
      paddingSize="l"
    >
      <strong>Opened content.</strong>
    </EuiAccordion>
  );
};
```

### Opened on initial render

Use the `initialIsOpen` prop to open the accordion when first rendered.

```tsx interactive
import React from 'react';
import { EuiAccordion, EuiPanel, useGeneratedHtmlId } from '@elastic/eui';

export default () => {
  const openAccordionId = useGeneratedHtmlId({ prefix: 'openAccordion' });

  return (
    <div>
      <EuiAccordion
        id={openAccordionId}
        buttonContent="I am opened by default. Click me to toggle close / open"
        initialIsOpen={true}
      >
        <EuiPanel color="subdued">
          Any content inside of <strong>EuiAccordion</strong> will appear here.
        </EuiPanel>
      </EuiAccordion>
    </div>
  );
};
```

### Controlling toggled state

Typically, the open and closed state of **EuiAccordion** is maintained by the component's internal state. Though, you can manually control it with:

*   `forceState`: Accepts either `'open'` or `'closed'`.
*   `onToggle`: A callback function returning `true` if the accordion is open

```tsx interactive
import React, { useState } from 'react';
import {
  EuiAccordion,
  EuiPanel,
  EuiButtonGroup,
  EuiSpacer,
  htmlIdGenerator,
  useGeneratedHtmlId,
} from '@elastic/eui';

const idPrefix = htmlIdGenerator()();

export default () => {
  const forcedStateAccordionId = useGeneratedHtmlId({
    prefix: 'forcedStateAccordion',
  });
  const [trigger, setTrigger] = useState('closed');
  const [toggleIdSelected, setID] = useState(`${idPrefix}--closed`);
  const toggleButtons = [
    {
      id: `${idPrefix}--open`,
      label: 'Open',
    },
    {
      id: `${idPrefix}--closed`,
      label: 'Closed',
    },
  ];

  const onChange = (id) => {
    setTrigger(id === toggleButtons[0].id ? 'open' : 'closed');
    setID(id);
  };

  const onToggle = (isOpen) => {
    const newState = isOpen ? 'open' : 'closed';
    setTrigger(newState);
    setID(`${idPrefix}--${newState}`);
  };

  return (
    <div>
      <EuiButtonGroup
        legend="This is a basic group"
        options={toggleButtons}
        idSelected={toggleIdSelected}
        onChange={onChange}
      />
      <EuiSpacer />
      <EuiAccordion
        id={forcedStateAccordionId}
        forceState={trigger}
        onToggle={onToggle}
        buttonContent="I am a controlled accordion"
        padding="l"
      >
        <EuiPanel color="subdued">
          Any content inside of <strong>EuiAccordion</strong> will appear here.
        </EuiPanel>
      </EuiAccordion>
    </div>
  );
};

```

### Loading state

Use the `isLoading` prop when not all of the accordion's content is ready yet. When using `isLoading`, the content of `extraAction` is replaced with a loading spinner.

Manage the content of the accordion using `isLoadingMessage`. By default, it is set to `false` and the content will remain unaltered. Set it to `true` to show a default loading message or pass a node to show a custom loading message.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Disabled state

In some cases you might want to prevent the user from closing the **EuiAccordion**. For example, if a form field is displaying an error, opening the accordion and preventing its closure until the error has been addressed will help the user find and fix the error.

The `isDisabled` prop will disable interaction on the button and the arrow. Use it in conjunction with `initialIsOpen` to achieve the desired effect.

:::accessibility Accessibility recommendation
When disabling the interaction of accordions based on user input, it's advisable to ensure there is further explanation through the use of help or error text.
:::

```tsx interactive
import React, { useState } from 'react';
import {
  EuiAccordion,
  EuiFieldPassword,
  EuiFormRow,
  EuiPanel,
  useGeneratedHtmlId,
} from '@elastic/eui';

export default () => {
  const [passwordValue, setPasswordValue] = useState('');
  const disabledAccordionId = useGeneratedHtmlId({
    prefix: 'disabledAccordion',
  });

  const isInvalid = passwordValue === '';

  return (
    <EuiAccordion
      id={disabledAccordionId}
      buttonContent="Security settings"
      isDisabled={isInvalid}
      initialIsOpen={true}
    >
      <EuiPanel color="subdued">
        <EuiFormRow
          label="Password"
          isInvalid={isInvalid}
          error={['You must enter your password to save these changes.']}
        >
          <EuiFieldPassword
            isInvalid={isInvalid}
            defaultValue={passwordValue}
            onChange={(v) => setPasswordValue(v.currentTarget.value)}
          />
        </EuiFormRow>
      </EuiPanel>
    </EuiAccordion>
  );
};
```

### When content changes dynamically

If an accordion’s content changes height while the accordion is open, it will resize dynamically.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Interactive content in the trigger

Passing interactive content like links, buttons, or form elements as the `buttonContent`, will cause issues with the wrapping button element. To fix this, you can change this wrapping element to a div using `buttonElement="div"`.

If you don't want the interactive content to trigger the accordion expansion, you will have to apply `e.stopPropagation()` to your element manually.

:::accessibility Accessibility requirement
Accordions need a focusable button for accessibility, so changing the element to anything other than a button will enforce the display of the arrow.
:::

```tsx interactive
import React from 'react';
import {
  EuiAccordion,
  EuiLink,
  EuiPanel,
  useGeneratedHtmlId,
} from '@elastic/eui';

export default () => {
  const buttonElementAccordionId = useGeneratedHtmlId({
    prefix: 'buttonElementAccordion',
  });

  return (
    <EuiAccordion
      id={buttonElementAccordionId}
      buttonElement="div"
      buttonContent={
        <EuiLink
          onClick={(e) => e.stopPropagation()}
          href="#/layout/accordion#interactive-content-in-the-trigger"
        >
          This is a nested link
        </EuiLink>
      }
    >
      <EuiPanel color="subdued">
        Any content inside of <strong>EuiAccordion</strong> will appear here.
      </EuiPanel>
    </EuiAccordion>
  );
};
```

### Styled for forms

Accordions are unstyled by default, but **EuiAccordion** supports several props around padding sizes and borders, as well as letting you pass in your own custom CSS styles. See the snippet tab below for a quick preview of said props, and the and the demo code tab below for custom hover and focus CSS overrides.

We also recommend creating a fieldset/legend combination for better accessibility and DOM structure by passing `element="fieldset"`. This will set the entire accordion as a `<fieldset>` and automatically change the `buttonElement` to a `<legend>`.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Props

import docgen from '@elastic/eui-docgen/dist/components/accordion';

<PropTable definition={docgen.EuiAccordion} />

---

### Packages Website Docs Components Containers Bottom Bar (`packages/website/docs/components/containers/bottom-bar.mdx`)

---
keywords: [EuiBottomBar]
---

# Bottom bar

:::tip
**EuiPageTemplate** offers a quick way to [apply a bottom bar to your page layouts](../templates/page-template/index.mdx#showing-a-bottom-bar).
:::

**EuiBottomBar** is a simple wrapper component that does nothing but affix a dark bar (usually filled with buttons) to the bottom of the page. Use it when you have really long pages or complicated, multi-page forms. In the case of forms, only invoke it if a form is in a savable state.

## Component

Like many of our other wrapper components, **EuiBottomBar** accepts a `paddingSize` prop, which can be set to `s | m (default) | l | none`.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Usage

### Positions

Bottom bars default to a fixed position, in a portal at the bottom of the browser window. Alternatively, you can change the `position` to `sticky` where it will render in place but stick to the window only as the window edge nears. The `static` position reverts back to default DOM behavior.

You can also apply a different set of positioning locations just by adjusting them in with the `top | right | bottom | left` props.

```tsx interactive
import React from 'react';
import { EuiBottomBar, EuiText } from '@elastic/eui';

export default () => {
  return (
    <div css={{ overflow: 'auto', blockSize: 200 }}>
      <EuiText>
        <p>
          When scrolling within this example, the <strong>EuiBottomBar</strong>{' '}
          will stick to the bottom of scrollable container (with a 10px offset),
          but will not scroll with the page itself.
        </p>
      </EuiText>
      <div css={{ blockSize: 400 }} />
      <EuiBottomBar position="sticky" bottom={10}>
        <EuiText textAlign="center">
          <p>Scroll to see!</p>
        </EuiText>
      </EuiBottomBar>
    </div>
  );
};
```

### Displacement

There is an `affordForDisplacement` prop (defaulting to `true`), which determines whether the component makes room for itself by adding bottom padding equivalent to its own height on the document `<body>` element. Setting this to `false` can be useful to minimize scrollbar visibility but will cause the bottom bar to overlap body content.

```tsx interactive
import React, { useState } from 'react';
import {
  EuiBottomBar,
  EuiButtonGroup,
  EuiButton,
  EuiFlexGroup,
  EuiFlexItem,
} from '@elastic/eui';

export default () => {
  const [toggleIdSelected, setToggleIdSelected] = useState(null);

  const toggleButtons = [
    {
      id: 'bottomBarStandard',
      label: 'Show bottom bar',
    },
    {
      id: 'bottomBarWithoutAffordForDisplacement',
      label: 'Show bottom bar (without affordForDisplacement behavior)',
    },
  ];

  const onChange = (optionId) => {
    setToggleIdSelected(optionId);
  };

  return (
    <div>
      <EuiButtonGroup
        legend="Bottom Bar demo toggle buttons group"
        type="single"
        buttonSize="m"
        color="primary"
        options={toggleButtons}
        idSelected={toggleIdSelected}
        onChange={(id) => onChange(id)}
      />

      {toggleIdSelected && (
        <EuiBottomBar
          affordForDisplacement={toggleIdSelected === 'bottomBarStandard'}
        >
          <EuiFlexGroup justifyContent="flexEnd">
            <EuiFlexItem grow={false}>
              <EuiButton
                onClick={() => setToggleIdSelected(null)}
                color="text"
                size="s"
                iconType="cross"
              >
                close
              </EuiButton>
            </EuiFlexItem>
          </EuiFlexGroup>
        </EuiBottomBar>
      )}
    </div>
  );
};
```

### Relative positioning

When `affordForDisplacement` is enabled and the bottom bar is positioned as `fixed`, **EuiBottomBar** automatically sets a global CSS variable that you can use to position other fixed elements in your application relative to the bottom bar's height:

- `--euiBottomBarOffset` (Set when `affordForDisplacement={true}` and `position="fixed"`)

This variable is automatically updated when the bottom bar resizes and is removed when the bottom bar is closed.

```css
.custom-fixed-footer {
  /* Adjust footer position when bottom bar is visible */
  padding-bottom: var(--euiBottomBarOffset, 0);
}
```

## Props

import docgen from '@elastic/eui-docgen/dist/components/bottom_bar';

<PropTable definition={docgen.EuiBottomBar} />

---

### Packages Website Docs Components Containers Card (`packages/website/docs/components/containers/card.mdx`)

---
keywords: [EuiCard, EuiCheckableCard]
---

# Card

**EuiCard** is a content-oriented component built on top of [EuiPanel](../containers/panel/index.mdx). Be sure to check out the [guidelines for properly nesting panels](../containers/panel/index.mdx#nesting-panels).

## Component

At its core an **EuiCard** should contain a `title`,`description`, and an `icon`. You can make the whole card clickable by giving it an `onClick` handler or `href`.

For accessibility and heading hierarchy, a card's title element is a `span` by default. However, this can be changed via the `titleElement` prop without altering the visual size.

```tsx interactive
import React from 'react';
import { EuiCard, EuiIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';

const icons = ['Beats', 'Cloud', 'Kibana'];

const cardNodes = icons.map(function (item, index) {
  return (
    <EuiFlexItem key={index}>
      <EuiCard
        icon={<EuiIcon size="xxl" type={`logo${item}`} />}
        title={`Elastic ${item}`}
        isDisabled={item === 'Kibana' ? true : false}
        description="Example of a card's description. Stick to one or two sentences."
        onClick={() => {}}
      />
    </EuiFlexItem>
  );
});

export default () => <EuiFlexGroup gutterSize="l">{cardNodes}</EuiFlexGroup>;

```

## Usage

### Images

Images can be added in place of, or in conjunction with, icons. Just pass a url into the `image` prop and it will expand to the edges of the card.

:::tip Make sure that all images are the **same proportions** when used in a singular row.

Also, when passing an **element** to the `image` prop that consists solely of inline elements or does not contain an`<img />` element, each element will require a style of `width: 100%`.

:::

```tsx interactive
import React from 'react';
import {
  EuiButton,
  EuiCard,
  EuiFlexGroup,
  EuiFlexItem,
  EuiIcon,
} from '@elastic/eui';

export default () => (
  <EuiFlexGroup gutterSize="l">
    <EuiFlexItem>
      <EuiCard
        textAlign="left"
        image={
          <div>
            <img src="https://picsum.photos/id/13/400/200" alt="Nature" />
          </div>
        }
        title="Elastic in Nature"
        description="Example of a card's description. Stick to one or two sentences."
        footer={
          <EuiFlexGroup justifyContent="flexEnd">
            <EuiFlexItem grow={false}>
              <EuiButton>Go for it</EuiButton>
            </EuiFlexItem>
          </EuiFlexGroup>
        }
      />
    </EuiFlexItem>
    <EuiFlexItem>
      <EuiCard
        textAlign="left"
        image="https://picsum.photos/400/200"
        title="Elastic in Water"
        description="Example of a card's description. Stick to one or two sentences."
        isDisabled
      />
    </EuiFlexItem>
    <EuiFlexItem>
      <EuiCard
        textAlign="left"
        href="https://elastic.github.io/eui/"
        image="https://picsum.photos/id/57/400/200"
        icon={<EuiIcon size="xxl" type="logoBeats" />}
        title={'Beats in the City'}
        description="This card has an href and should be a link."
      />
    </EuiFlexItem>
  </EuiFlexGroup>
);
```

### Footer

Footers can contain any number of elements and will always align to the bottom of the card. However, if you supply a footer containing a **EuiButton** you **must not** also give it an `onClick`.

:::accessibility Accessibility requirement
When using footers to display generic "Go" buttons, you must provide an `aria-label` to the button itself that refers back to the title of the card.
:::

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Beta badge

If the card links to or references a module that is not GA (beta, lab, etc), you can add a `betaBadgeProps.label` and `betaBadgeProps.tooltipContent` to the card and it will properly create and position an **EuiBetaBadge**. If you want to change the title of the tooltip, supply a `betaBadgeProps.title` prop.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Selectable

When you have a list of cards that can be selected but **do not navigate anywhere**, you can add the `selectable` prop. The prop is an object that extends **EuiButtonEmpty**. It will apply the button as seen below, and passing `selectable.isSelected=true` will alter the styles of the card and button to look selected.

:::tip
When providing an extra link to more details or such, be sure to stop event propagation from also selecting the card.
:::

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Checkable

**EuiCheckableCard** wraps an **EuiRadio** or **EuiCheckbox** with a more-prominent panel, allowing for children to be displayed.

```tsx interactive
import React, { useState } from 'react';
import { EuiCheckableCard, useGeneratedHtmlId } from '@elastic/eui';

export default () => {
  const [checkbox, setCheckbox] = useState(false);
  const checkboxCardId = useGeneratedHtmlId({ prefix: 'checkboxCard' });

  return (
    <EuiCheckableCard
      id={checkboxCardId}
      label="I am a checkbox"
      checkableType="checkbox"
      value="checkbox1"
      checked={checkbox}
      onChange={() => setCheckbox(checked => !checked)}
    />
  );
};
```

:::accessibility Accessibility requirement
When used as a radio group, you must provide a `fieldset` with a `legend` for accessibility.
:::

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Custom children

In the event that you need **more than** just paragraph text for the `description`, you can supplement with anything you need as the `children` of the component. You can also completely replace the description with custom children, but **EuiCard** at least one of these.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Plain and other colors

If you need a card with no borders or shadows pass `display="plain"`. This is a good option to avoid nested panels. Adding an interaction to the card will provide the clickable styling on hover. The `display` prop also accepts all other **EuiPanel** colors like `'transparent'`.

For non-interactive cards, reduce or eliminate the padding as needed to suit your layout with the prop `paddingSize`.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Props

import docgen from '@elastic/eui-docgen/dist/components/card';

<PropTable definition={docgen.EuiCard} />
<PropTable definition={docgen.EuiCheckableCard} />

---

--- METRICS ---
- Files Extracted: 100
- Estimated Token Budget: ~138799 tokens
- Canonical Reference: https://codewiki.google/github.com/elastic/eui
