Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docs] Final polish on Base docs - formatting and style consistency #33156

Merged
merged 58 commits into from Jul 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
b25aac5
fixes seo descriptions
samuelsycamore Jun 14, 2022
60c7b09
better badge page
samuelsycamore Jun 14, 2022
f78c1f7
better select page, minor tweaks to badge
samuelsycamore Jun 14, 2022
faa5479
better modal doc
samuelsycamore Jun 14, 2022
f0e814e
fix overview title, popper wip
samuelsycamore Jun 14, 2022
8907b17
better popper
samuelsycamore Jun 14, 2022
3bfbee7
better nossr
samuelsycamore Jun 14, 2022
1cf8a39
better input doc
samuelsycamore Jun 14, 2022
1a37b54
form control wip
samuelsycamore Jun 14, 2022
92ab404
prettier
samuelsycamore Jun 14, 2022
0a43be4
better form control doc
samuelsycamore Jun 15, 2022
e3e73f5
better trap focus doc
samuelsycamore Jun 15, 2022
b33f538
better switch
samuelsycamore Jun 15, 2022
33a8f84
better slider
samuelsycamore Jun 15, 2022
0962d4b
portal update
samuelsycamore Jun 15, 2022
b972bfa
updated button
samuelsycamore Jun 15, 2022
3306811
tablepag update
samuelsycamore Jun 15, 2022
e9f972a
update clickaway
samuelsycamore Jun 15, 2022
4f65b04
updated tabs
samuelsycamore Jun 15, 2022
2d9af7b
tweak so prettier will play nice
samuelsycamore Jun 15, 2022
d69cf1b
update textarea
samuelsycamore Jun 15, 2022
9b749ed
tabs fix
samuelsycamore Jun 15, 2022
36b20c6
prettier, markdownlint, i18n
samuelsycamore Jun 15, 2022
99ab8dd
merge master
samuelsycamore Jun 15, 2022
6c157fe
componentlinkheader
samuelsycamore Jun 15, 2022
ee9f893
componentlinkheader again
samuelsycamore Jun 15, 2022
baeb70d
Update docs/data/base/components/badge/badge.md
samuelsycamore Jun 15, 2022
694fabb
Update docs/data/base/components/badge/badge.md
samuelsycamore Jun 15, 2022
dc0aa94
fix overview title
samuelsycamore Jun 20, 2022
e08fe8e
better anatomy sections
samuelsycamore Jun 22, 2022
8434af2
badge slot docs
samuelsycamore Jun 22, 2022
3e59932
best badge page
samuelsycamore Jun 22, 2022
0ff49f1
more structural badge adjustments
samuelsycamore Jun 22, 2022
d946d65
badge hook content revision, trap focus wip
samuelsycamore Jun 22, 2022
ea9be13
trapfocus, formcontrol
samuelsycamore Jun 22, 2022
ab316e4
copypasta
samuelsycamore Jun 22, 2022
fbbe9fe
button
samuelsycamore Jun 23, 2022
77cb8de
textarea
samuelsycamore Jun 23, 2022
270264d
fix badge class name
samuelsycamore Jun 23, 2022
b08d157
switch wip
samuelsycamore Jun 23, 2022
076ab43
small tweaks to pages updated so far:
samuelsycamore Jun 23, 2022
504d75c
clickaway
samuelsycamore Jun 23, 2022
103e518
utilities and switch
samuelsycamore Jun 23, 2022
d201ba3
table pagination
samuelsycamore Jun 23, 2022
02f961a
menu
samuelsycamore Jun 23, 2022
5b637a5
progress
samuelsycamore Jun 23, 2022
a062cb6
select
samuelsycamore Jun 25, 2022
58effd5
slider
samuelsycamore Jun 25, 2022
03bf91f
merge master
samuelsycamore Jun 25, 2022
7bbaf7e
fix usage links
samuelsycamore Jul 11, 2022
387e9e6
merge master
samuelsycamore Jul 11, 2022
bdd7cf7
merge master
samuelsycamore Jul 18, 2022
2cd1227
rearrange usage and anatomy headers
samuelsycamore Jul 18, 2022
0a71943
merge master
samuelsycamore Jul 20, 2022
c519089
slider revisions
samuelsycamore Jul 20, 2022
0d4b0d1
markdownlint
samuelsycamore Jul 20, 2022
38cfeea
table pagination action buttons
samuelsycamore Jul 20, 2022
8f485ec
three to several
samuelsycamore Jul 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
134 changes: 120 additions & 14 deletions docs/data/base/components/badge/badge.md
@@ -1,43 +1,149 @@
---
product: base
title: Unstyled React Badge component
title: Unstyled React Badge component and hook
components: BadgeUnstyled
githubLabel: 'component: badge'
packageName: '@mui/base'
---

# Unstyled badge

<p class="description">The `BadgeUnstyled` component generates a small label that is attached to its children elements.</p>
<p class="description">The BadgeUnstyled component generates a small label that is attached to its child element.</p>

```js
## Introduction

A badge is a small descriptor for UI elements.
It typically sits on or near an element and indicates the status of that element by displaying a number, icon, or other short set of characters.

The `BadgeUnstyled` component creates a badge that is applied to its child element.

{{"component": "modules/components/ComponentLinkHeader.js", "design": false}}

## Component

### Usage

After [installation](/base/getting-started/installation/), you can start building with this component using the following basic elements:

```jsx
import BadgeUnstyled from '@mui/base/BadgeUnstyled';

export default function MyApp() {
return (
<BadgeUnstyled>{/* the element that the badge is attached to */}</BadgeUnstyled>
);
}
```

{{"component": "modules/components/ComponentLinkHeader.js", "design": false}}
### Basics
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When landing on https://deploy-preview-33156--material-ui.netlify.app/base/react-badge you need to scroll a lot before you can find an actual demo of the component or one that you can copy and paste into your project. It contrasts with what we had before https://mui.com/base/react-badge/ or https://www.radix-ui.com/docs/primitives/components/tooltip. So I conclude that we miss an introduction demo, maybe under ### Basics?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good point. We could definitely use a basic intro demo here, and probably for some other Base components as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will raise this discussion at the next team meeting, seeing

it feels nice to see a full demo first before everything else. It can even then turn into an SEO hack https://www.notion.so/mui-org/Page-image-generator-75bc177fefe64c0b899a42a6f919a907.


`BadgeUnstyled` wraps around the UI element that it's attached to.
For instance, if the badge indicates the number of emails in an inbox, then the component will be structured like this:

```jsx
<BadgeUnstyled>
<MailIcon />
</BadgeUnstyled>
```

### Anatomy

The `BadgeUnstyled` component is composed of a root `<span>` that houses the element that the badge is attached to, followed by a `<span>` slot to represent the badge itself:

```html
<span class="BaseBadge-root">
<!-- the element the badge is attached to is nested here -->
<span class="BaseBadge-badge">badge content</span>
</span>
```

### Slot props

:::info
The following props are available on all non-utility Base components.
See [Usage](/base/getting-started/usage/) for full details.
:::

Use the `component` prop to override the root slot with a custom element:

```jsx
<BadgeUnstyled component="div" />
```

Use the `components` prop to override any interior slots in addition to the root:

```jsx
<BadgeUnstyled components={{ Root: 'div', Badge: 'div' }} />
```

:::warning
If the root element is customized with both the `component` and `components` props, then `component` will take precedence.
:::

Use the `componentsProps` prop to pass custom props to internal slots.
The following code snippet applies a CSS class called `my-badge` to the badge slot:

```jsx
<BadgeUnstyled componentsProps={{ badge: { className: 'my-badge' } }} />
```

:::warning
Note that `componentsProps` slot names are written in lowercase (`root`) while `components` slot names are capitalized (`Root`).
:::

## Hook

```jsx
import { useBadge } from '@mui/base/BadgeUnstyled';
```

The `useBadge` hook lets you apply the functionality of `BadgeUnstyled` to a fully custom component.
It returns props to be placed on the custom component, along with fields representing the component's internal state.

Hooks _do not_ support [slot props](#slot-props), but they do support [customization props](#customization).

:::info
Hooks give you the most room for customization, but require more work to implement.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recently realized another use case for hooks - if you're building a component library that can be customized further by developers (e.g. using the componentsProps prop), use hooks. Unstyled components are better suited to build "closed" libraries (that's why we use hooks to build Joy components, for example).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think this is worth mentioning on all pages? Or maybe it would be better suited for the Usage page?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose having it just on the Usage page should be enough.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. I'll add it to #33272

With hooks, you can take full control over how your component is rendered, and define all the custom props and CSS classes you need.

You may not need to use hooks unless you find that you're limited by the customization options of their component counterparts鈥攆or instance, if your component requires significantly different [structure](#component-slots).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be better?

Suggested change
You may not need to use hooks unless you find that you're limited by the customization options of their component counterparts鈥攆or instance, if your component requires significantly different [structure](#component-slots).
You may not need to use hooks unless you find that you're limited by the customization options of their component counterparts鈥攆or instance, if your component requires a significantly different [structure](#component-slots).

:::

## Customization

:::info
The following features can be used with both components and hooks.
For the sake of simplicity, demos and code snippets primarily feature components.
:::

### Badge content

The `badgeContent` prop defines the content that's displayed inside the badge.
When this content is a number, there are additional props you can use for further customization鈥攕ee the [Numerical badges section](#numerical-badges) below.

## Basic usage
The following demo shows how to create and style a typical numerical badge that's attached to a generic box element:

{{"demo": "UnstyledBadge.js", "defaultCodeOpen": false}}

## Badge visibility
### Badge visibility

You can control the visibility of a `BadgeUnstyled` by using the `invisible` prop.
Setting a badge to `invisible` does not actually hide it鈥攊nstead, this prop adds the `MuiBadge-invisible` class to the badge, which you can target with styles to hide however you prefer:
You can control the visibility of a badge by using the `invisible` prop.
Setting a badge to `invisible` does not actually hide it鈥攊nstead, this prop adds the `BaseBadge-invisible` class to the badge, which you can target with styles to hide however you prefer:

{{"demo": "BadgeVisibility.js"}}

## Numerical badges
### Numerical badges
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not have it as a h2? As far as I understand, this section makes sense regardless of the component or hook API chosen.

Suggested change
### Numerical badges
## Numerical badges

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that does present a unique challenge for organizing the pages that cover components + hooks. We might have to rethink how those pages are structured.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, agree, it's not an obvious decision. I provided a bit more context for this feedback in #33156 (review).


The following props are useful when `badgeContent` is a number.

### The showZero prop
#### The showZero prop

By default, badges automatically hide when `badgeContent={0}`. You can override this behavior with the `showZero` prop:
By default, badges automatically hide when `badgeContent={0}`.
You can override this behavior with the `showZero` prop:

{{"demo": "ShowZeroBadge.js"}}

### The max prop
#### The max prop

You can use the `max` prop to set a maximum value for `badgeContent`.
The default is 99.
Expand All @@ -47,6 +153,6 @@ The default is 99.
## Accessibility

Screen readers may not provide users with enough information about a badge's contents.
To make your `BadgeUnstyled` accessible, you must provide a full description with `aria-label`:
To make your badge accessible, you must provide a full description with `aria-label`, as shown in the demo below:

{{"demo": "AccessibleBadges.js", "defaultCodeOpen": false}}
{{"demo": "AccessibleBadges.js"}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we could keep the preview disabled. It doesn't explain how the feature works, so I feel noise for developers

Suggested change
{{"demo": "AccessibleBadges.js"}}
{{"demo": "AccessibleBadges.js", "defaultCodeOpen": false}}

135 changes: 106 additions & 29 deletions docs/data/base/components/button/button.md
Expand Up @@ -8,37 +8,131 @@ waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/button/

# Unstyled button

<p class="description">Buttons allow users to take actions and make choices with a single tap.</p>
<p class="description">Buttons let users take actions and make choices with a single tap.</p>

## Basic button
## Introduction

```js
`ButtonUnstyled` replaces the native HTML `<button>` element.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be interesting to explain why (The value proposition for a developer to replace a native button) Or maybe it's better to say "extends" it.


{{"component": "modules/components/ComponentLinkHeader.js", "design": false}}

## Component

### Usage

After [installation](/base/getting-started/installation/), you can start building with this component using the following basic elements:

```jsx
import ButtonUnstyled from '@mui/base/ButtonUnstyled';

<ButtonUnstyled>Button</ButtonUnstyled>;
export default function MyApp() {
return <ButtonUnstyled>{/* button text */}</ButtonUnstyled>;
}
```

### Basics

`ButtonUnstyled` behaves similarly to the native HTML `<button>`, so it wraps around the text that will be displayed on its surface.

The following demo shows how to create and style two basic buttons.
Notice that the second button cannot be clicked due to the `disabled` prop:

{{"demo": "UnstyledButtonsSimple.js", "defaultCodeOpen": true}}

## Customizing the root element
### Anatomy

The `ButtonUnstyled` component is composed of a root `<button>` slot with no interior slots:

```html
<button class="BaseButton-root">
<!-- button text goes here -->
</button>
```

By default, the `ButtonUnstyled` component renders a native `button` HTML element.
You can override this by setting the `component` or `components.Root` prop.
### Slot props

:::info
The following props are available on all non-utility Base components.
See [Usage](/base/getting-started/usage/) for full details.
:::

Use the `component` prop to override the root slot with a custom element:

```jsx
<ButtonUnstyled component="div" />
```

If you provide a non-interactive element such as a `<span>`, the `ButtonUnstyled` component will automatically add the necessary accessibility attributes.

Use the `components` prop to override any interior slots in addition to the root:

```jsx
<ButtonUnstyled components={{ Root: 'div' }} />
```

:::warning
If the root element is customized with both the `component` and `components` props, then `component` will take precedence.
:::

Use the `componentsProps` prop to pass custom props to internal slots.
The following code snippet applies a CSS class called `my-button` to the root slot:

```jsx
<ButtonUnstyled componentsProps={{ root: { className: 'my-button' } }} />
```

:::warning
Note that `componentsProps` slot names are written in lowercase (`root`) while `components` slot names are capitalized (`Root`).
:::

Compare the attributes on the `<span>` in this demo with the `ButtonUnstyled` from the previous demo:

{{"demo": "UnstyledButtonsSpan.js"}}

### Complex customization
:::warning
If a `ButtonUnstyled` is customized with a non-button element (i.e. `<ButtonUnstyled component="span" />`), it will not submit the form it's in when clicked.
Similarly, `<ButtonUnstyled component="span" type="reset">` will not reset its parent form.
:::

## Hook

```js
import { useButton } from '@mui/base/ButtonUnstyled';
```

The `useButton` hook lets you apply the functionality of `ButtonUnstyled` to a fully custom component.
It returns props to be placed on the custom component, along with fields representing the component's internal state.

Hooks _do not_ support [slot props](#slot-props), but they do support [customization props](#customization).

:::info
Hooks give you the most room for customization, but require more work to implement.
With hooks, you can take full control over how your component is rendered, and define all the custom props and CSS classes you need.

You may not need to use hooks unless you find that you're limited by the customization options of their component counterparts鈥攆or instance, if your component requires significantly different [structure](#component-slots).
:::

The `useButton` hook requires the `ref` of the element it's used on.

The following demo shows how to build the same buttons as those found in the [Basic usage section](#basic-usage), but with the `useButton` hook:

{{"demo": "UseButton.js", "defaultCodeOpen": true}}

## Customization

:::info
The following features can be used with both components and hooks.
For the sake of simplicity, demos and code snippets primarily feature components.
:::

### Custom elements

`ButtonUnstyled` accepts a wide range of custom elements beyond HTML elements.
You can even use SVGs, as the following demo illustrates:

{{"demo": "UnstyledButtonCustom.js", "defaultCodeOpen": false}}

## Focus on disabled buttons
### Focus on disabled buttons

Similarly to the native HTML `<button>` element, the `ButtonUnstyled` component can't receive focus when it's disabled.
This may reduce its accessibility, as screen readers won't be able to announce the existence and state of the button.
Expand All @@ -51,28 +145,11 @@ This should be used whenever the disabled button needs to be read by screen read

MUI Base uses this prop internally in [menu items](/base/react-menu/), making it possible to use the keyboard to navigate to disabled items (in compliance with [ARIA guidelines](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#x6-7-focusability-of-disabled-controls)).

The following demo shows how the `focusableWhenDisabled` prop works鈥攗se the <kbd class="key">Tab</kbd> key to navigate within this document to see that only the second button accepts the focus:

{{"demo": "UnstyledButtonsDisabledFocus.js"}}

The `focusWhenDisabled` prop works the same when the root slot is customized, except that the `aria-disabled` attribute is used no regardless of the prop's state.
The `focusableWhenDisabled` prop works the same when the root slot is customized, except that the `aria-disabled` attribute is used no regardless of the prop's state.
The ability to receive focus is controlled internally by the `tabindex` attribute.

{{"demo": "UnstyledButtonsDisabledFocusCustom.js"}}

## The useButton hook

```js
import { useButton } from '@mui/base/ButtonUnstyled';
```

The `useButton` hook lets you use the functionality of `ButtonUnstyled` in other components.
It returns props to be placed on a custom button element, along with fields representing the internal state of the button.

The `useButton` hook requires the `ref` of the element it's used on.
Additionally, you need to provide the `component` prop (unless you intend to use the native HTML `<button>`).

{{"demo": "UseButton.js", "defaultCodeOpen": true}}

## Limitations

If a `ButtonUnstyled` is customized with a non-button element (i.e. `<ButtonUnstyled component="span" />`), it will not submit the form it's in when clicked.
Similarly, `<ButtonUnstyled component="span" type="reset">` will not reset its parent form.