Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Using Slots with Fluent UI React v9
Paul Gildea
Paul Gildea

Posted on • Edited on

     

Using Slots with Fluent UI React v9

Fluent UI React v9 components have customizable parts called "slots." An example of this is theicon slot of aButton which lets you supply an icon to theButton component.

Each component has top-level prop(s) for each supported slot(s). For example,Button has aniconslot, whileInput has aroot,contentBefore, andcontentAfterslots.

Slots are an integral part of a component's design and we refer to it as the component's anatomy.

The following is a basic example of theButton anatomy:

Basic anatomy of a Button component

In the above example, you can see how there's a slot allocated for icon content that sits next to the textual content of theButton.

The slots API give you full control over the slot allowing you to:

  • Pass content like text, images, and JSX
  • Pass props for state, classes, and event handlers
  • Change the type of the slot
  • Change the slot entirely

The next set of examples will demonstrate how to customize theicon slot on theButtoncomponent, but the same patterns can be used on any of the slots across the component library.

Passing text, images, and JSX to slots

The easiest way to pass content to a slot is to do it directly.

Passing text/emoji to a Button icon slot

JSX:

<Button icon="🚀">Launch</Button>
Enter fullscreen modeExit fullscreen mode

HTML output:

<button type="button">  <span>🚀</span>Launch</button>
Enter fullscreen modeExit fullscreen mode

Passing image/svg to a Button icon slot

In this example we are using a wrapped SVG icons from@fluentui/react-icons
JSX:

<Button icon={<RocketRegular />}>Launch</Button>
Enter fullscreen modeExit fullscreen mode

HTML output:

<button type="button">  <span>    <svg>...</svg>  </span>Launch</button>
Enter fullscreen modeExit fullscreen mode

Passing JSX to a Button icon slot

JSX:

// Just a basic count down timerconst [countDown, updateCountDown] = React.useState(10);  setTimeout(() => {    if (countDown > 0) {      updateCountDown(countDown - 1);    } else {      updateCountDown(10);    }  }, 1000);<Button icon={<CounterBadge color="danger" count={countDown} />}>Launch</Button>
Enter fullscreen modeExit fullscreen mode

HTML output:

<button type="button">  <span>    <div>10</div>  </span>Launch</button>
Enter fullscreen modeExit fullscreen mode

You can find the combined example on CodeSandbox:

Passing props for state, CSS classes, and event handlers

When you need to pass more than just content to a slot, you can leverage the object notation to pass props. Those props are added to the slot itself, as opposed to the content that goes inside the slot.

For the content that gets passed in the slot you use thechildren prop that can accept primitive values, JSX, and a render function.

Passing data with the data props

JSX:

<Button  icon={{    children: "🚀",    "data-foo": "bar"  }}>    Launch</Button>
Enter fullscreen modeExit fullscreen mode

HTML output:

<button type="button">  <span data-foo="bar">🚀</span>Launch</button>
Enter fullscreen modeExit fullscreen mode

Passing CSS classes with className prop

Note: This example is usingGriffel a CSS-in-JS engine that's used with Fluent UI React v9.

JSX:

const useStyles = makeStyles({  slotBackground: {    backgroundColor: tokens.colorBrandBackground,    ...shorthands.borderRadius(tokens.borderRadiusCircular)  }});const App = () => {  const c = useStyles();  return <Button          icon={{            children: "🚀",            className: c.slotBackground          }}>          Launch         </Button>}
Enter fullscreen modeExit fullscreen mode

HTML output:
Note: Griffel will generate atomic CSS

<button type="button">  <span>🚀</span>Launch</button>
Enter fullscreen modeExit fullscreen mode

Passing event handlers

In this example the event handlers are attached to the slot itself and not the content. So the counter will start when the mouse enters the slot and will stop when the mouse leaves the slot.

JSX:

const [countDown, updateCountDown] = React.useState(10);const [count, setCount] = React.useState(false);setTimeout(() => {  if (count) {    if (countDown > 0) {       updateCountDown(countDown - 1);    } else {      updateCountDown(10);    }  }}, 1000);const onStartCounter = (ev: React.MouseEvent<HTMLButtonElement>) => {  setCount(true);};const onStopCounter = (ev: React.MouseEvent<HTMLButtonElement>) => {  setCount(false);};<Button  icon={{    children: <CounterBadge color="danger" count={countDown} />,    onMouseEnter: onStartCounter,    onMouseLeave: onStopCounter  }}>  Launch</Button>
Enter fullscreen modeExit fullscreen mode

HTML output:

<button type="button">  <span onMouseEnter="..." onMouseLeave="...">    <div>10</div>  </span>Launch</button>
Enter fullscreen modeExit fullscreen mode

You can find the combined example on CodeSandbox:

Change the type of the slot

In the case ofButton theicon slot is by default aspan element. If you need to change the type of the slot you can use the same object notation and specify the type with theas property.

JSX:

<Button  icon={{    as: "a",    href: "#launch",    children: "🚀"  }}>  Launch</Button>
Enter fullscreen modeExit fullscreen mode

HTML output:

<button type="button">  <a href="#launch">🚀</a>Launch</button>
Enter fullscreen modeExit fullscreen mode

However, in most cases you might find yourself wanting to change the type of the component itself. Which is achieved the same way leveraging the top levelas prop on the component - because the component is a slot itself. Common use cases are for changing aButton to ananchor for navigational purposes like withreact-router.

JSX

<Button as="a" icon="🚀">Launch</Button>
Enter fullscreen modeExit fullscreen mode

HTML output:

<a>  <span>🚀</span>Launch</a>
Enter fullscreen modeExit fullscreen mode

You can find the combined example on CodeSandbox:

Change the slot entirely

There are times where you many need to change the entire slot including its containing element.

This is an escape hatch in the slots API, so it's highly recommended to leverage techniques whenever possible.

Handing off the computed props that would have been applied to the slot is critical to being able to handle every slot override case conceivable. Without it, there are computed values locked in the component that the consumer cannot access when doing a replacement or augmentation, such as styles and states they may need to handle. An example of this is open state in an Accordion item, which is calculated by the Accordion parent and handed to the item.

So keep that in mind if you head down this path 😊.

JSX:

<Button  icon={{    children: (Icon, iconProps) => {      return "🚀";    }  }}>  Launch</Button>
Enter fullscreen modeExit fullscreen mode

HTML output:

<button type="button">  🚀Launch</button>
Enter fullscreen modeExit fullscreen mode

You can find the combined example on CodeSandbox:

So there you have it. A whirlwind of use cases for customization with slots.

Check out thedocumentation to learn more about slots.

If you want to learn more about Fluent UI React v9 reach out to us via:

Enjoy!

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Product Manager working on Fluent UI - pretending I know how to code...
  • Education
    Rochester Institute of Technology
  • Work
    Senior Product Manager at Microsoft
  • Joined

More fromPaul Gildea

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp