Back to Fluentui

Toolbar Migration

apps/public-docsite-v9/src/Concepts/Migration/FromV0/Components/Toolbar.mdx

4.40.2-hotfix213.6 KB
Original Source

import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="Concepts/Migration/from v0/Components/Toolbar Migration" />

Toolbar Migration

Overview:

Before:

tsx
import { Toolbar } from '@fluentui/react-northstar';
const Component = () => (
  <Toolbar
    aria-label="Default"
    items={[
      {
        icon: (
          <BoldIcon
            {...{
              outline: true,
            }}
          />
        ),
        key: 'bold',
        kind: 'toggle',
        active: state.bold,
        title: 'Toggle bold',
      },
      {
        icon: (
          <ItalicIcon
            {...{
              outline: true,
            }}
          />
        ),
        key: 'italic',
        kind: 'toggle',
        active: state.italic,
        title: 'Toggle italic',
      },
      {
        icon: (
          <UnderlineIcon
            {...{
              outline: true,
            }}
          />
        ),
        key: 'underline',
        kind: 'toggle',
        active: state.underline,
        title: 'Toggle underline',
      },
      {
        key: 'divider-1',
        kind: 'divider',
      },
      {
        icon: (
          <FontSizeIcon
            {...{
              outline: true,
            }}
          />
        ),
        key: 'font-size',
        title: 'Font size',
      },
      {
        icon: (
          <RemoveFormatIcon
            {...{
              outline: true,
            }}
          />
        ),
        key: 'remove-format',
        title: 'Remove formatting',
      },
      {
        key: 'divider-2',
        kind: 'divider',
      },
      {
        icon: (
          <OutdentIcon
            {...{
              outline: true,
            }}
          />
        ),
        key: 'outdent',
        title: 'Outdent',
      },
      {
        icon: (
          <IndentIcon
            {...{
              outline: true,
            }}
          />
        ),
        key: 'indent',
        title: 'Indent',
      },
      {
        key: 'divider-3',
        kind: 'divider',
      },
      {
        icon: (
          <MoreIcon
            {...{
              outline: true,
            }}
          />
        ),
        key: 'more',
        active: state.more,
        title: 'More',
        menu: [
          {
            key: 'quote',
            content: 'Quote',
            icon: <QuoteIcon />,
          },
          {
            key: 'link',
            content: 'Link',
            icon: <LinkIcon />,
            disabled: true,
          },
          {
            key: 'code',
            content: 'Code snippet',
            icon: <CodeSnippetIcon />,
          },
        ],
      },
    ]}
  />
);

After:

tsx
import { Toolbar, ToolbarToggleButton, ToolbarDivider, ToolbarButton } from '@fluentui/react-components';

export const Component = () => {
  <Toolbar>
    <ToolbarToggleButton name="text" value="bold" icon={<TextBoldRegular />} />
    <ToolbarToggleButton name="text" value="italic" icon={<TextItalicRegular />} />
    <ToolbarToggleButton name="text" value="underline" icon={<TextUnderlineRegular />} />
    <ToolbarDivider />
    <ToolbarButton icon={<FontIncreaseRegular />} />
    <ToolbarButton icon={<TextFontRegular />} />
    <ToolbarDivider />
    <ToolbarButton icon={<AlignLeftRegular />} />
    <ToolbarButton icon={<AlignCenterHorizontalRegular />} />
    <ToolbarDivider />
    <Menu>
      <MenuTrigger>
        <ToolbarButton aria-label="More" icon={<MoreHorizontalFilled />} />
      </MenuTrigger>

      <MenuPopover>
        <MenuList>
          <MenuItem>New </MenuItem>
          <MenuItem>New Window</MenuItem>
          <MenuItem disabled>Open File</MenuItem>
          <MenuItem>Open Folder</MenuItem>
        </MenuList>
      </MenuPopover>
    </Menu>
  </Toolbar>;
};

Controlled

V0 only allows to set an item active in a controlled way through active property in a toolbar item. V9 Toolbar doesn't need that by default by can also be controlled.

V9 Controlled:

javascript
import {
  Toolbar,
  ToolbarToggleButton,
  ToolbarDivider,
  ToolbarButton
} from '@fluentui/react-components';



const Component = () => {
  const [checkedValues, setCheckedValues] = React.useState<Record<string, string[]>>({
    textOptions: ['bold', 'italic'],
  });
  const onChange: ToolbarProps['onCheckedValueChange'] = (e, { name, checkedItems }) => {
    setCheckedValues(s => {
      return s ? { ...s, [name]: checkedItems } : { [name]: checkedItems };
    });
  };

  return (
    <Toolbar checkedValues={checkedValues} onCheckedValueChange={onChange}>
      <ToolbarToggleButton aria-label="Bold" icon={<TextBold24Regular />} name="textOptions" value="bold" />
      <ToolbarToggleButton aria-label="Italic" icon={<TextItalic24Regular />} name="textOptions" value="italic" />
      <ToolbarToggleButton
        aria-label="Underline"
        icon={<TextUnderline24Regular />}
        name="textOptions"
        value="underline"
      />
    </Toolbar>
  );
}

How to migrate props:

`Toolbar` propsmigrate guide
as, classNamekeep it as is
variables, styles, designsee [Migrate style overrides](#migrate-style-overrides) in this document
accessibilitysee [migrate-custom-accessibility.md](?path=/docs/concepts-migration-from-v0-custom-accessibility--docs)
contentsee [Migrate content prop](##migrate-content-prop) in this document
ref, keykeep it as is
getOverflowItemsREMOVED: Use @fluentui/react-overflow to render overflow items
itemsREMOVED: Only supports children API
onOverflowuse `isOverflowing` from `useOverflowMenu` from @fluentui/react-overflow. See [migrate overflow props](#migrate-%60overflow%60-props)
onOverflowOpenChangeREMOVED: handle the needed changes in the overflow component. See [migrate overflow props](#migrate-%60overflow%60-props)
overflowREMOVED: Use @fluentui/react-overflow
overflowItemREMOVED: Should be implemented in the Overflow component that is using `useOverflowMenu`. See [migrate overflow props](#migrate-%60overflow%60-props)
overflowOpenREMOVED: Should be handled by the component that will be using `useOverflowMenu`
overflowSentinelREMOVED: Can be set as `padding` in the `Overflow` component from @fluentui/react-overflow. See [migrate overflow props](#migrate-%60overflow%60-props)
`ToolbarItem` propsmigrate guide
as, classNamekeep it as is
contentsee [Migrate content prop](##migrate-content-prop) in this document
variables, stylessee [Migrate style overrides](#migrate-style-overrides) in this document
accessibilitysee [migrate-custom-accessibility.md](?path=/docs/concepts-migration-from-v0-custom-accessibility--docs)
circularreplace with `shape="circular"`
disabledkeep it as is
disabledFocusablekeep it as is
fluidreplace with `block`
iconkeep it as is.
menuREMOVED: use `@fluentui/react-menu`
menuOpenREMOVED: use `@fluentui/react-menu`
onMenuOpenChangeREMOVED: use `@fluentui/react-menu`
popupREMOVED: use `@fluentui/react-popover`, [see example](?path=/docs/preview-components-toolbar--default#with-popover)
wrapperREMOVED

ToolbarCustomItem in V9 is replaced by direct adding the content as Toolbar children.

V0

javascript
<Toolbar aria-label="Default">
  <ToolbarCustomItem content={<MyFacyButton>Click Here</MyFacyButton>} />
</Toolbar>

V9

javascript
<Toolbar aria-label="Default">
  <MyFacyButton>Click Here</MyFacyButton>
</Toolbar>

Here is comparison for both versions: Sandbox


Migrate style overrides

⚠️ If this is your first migration, please read the general guide on how to migrate styles.

Example for migrate boolean variables:

Before:

tsx
// in COMPONENT_NAME.tsx
import { Toolbar } from '@fluentui/react-components';

export const Component = () => <Toolbar variables={{ fluid: true }} items={[{ content: 'item 1' }]} />;

// in toolbar-button-styles.ts
export const toolbarStyles = {
  root: ({ variables: { fluid } }) => ({
    ...(fluid && {
      width: '100%',
    }),
  }),
};

After:

tsx
// in COMPONENT_NAME.tsx
import { useStyles } from './COMPONENT_NAME.styles.ts';
import { Toolbar, ToolbarButton } from '@fluentui/react-components';

export const Component = () => {
  const classes = useStyles();
  return (
    <Toolbar className={classes.breakoutRoomsAssignmentToolbar}>
      <ToolbarButton>Italic</ToolbarButton>
    </Toolbar>
  );
};

// in COMPONENT_NAME.styles.ts
import { makeStyles } from '@fluentui/react-components';

export const useStyles = makeStyles({
  breakoutRoomsAssignmentToolbar: {
    width: '100%',
  },
});

Example for migrate namespaced styles, with conditional styles via variableProps:

Before:

tsx
// in COMPONENT_NAME.tsx
import { Toolbar, useUIProviderContext } from '@fluentui/react-components';

export const Component = props => {
  const { vars } = useUIProviderContext();
  const { isLive } = props;
  return <Toolbar items={['1']} variables={{ isLive: true }} />;
};

// in toolbar-styles.ts
export default {
  root: ({ variables: { isLive } }) => ({
    ...(isLive && {
      height: '100%',
      alignItems: 'center',
      color: isLive ? colorSchemeSilver.foreground1 : 'inherit',
    }),
  }),
};

After:

tsx
// in COMPONENT_NAME.tsx
import { useStyles } from './COMPONENT_NAME.styles.ts';
import { Toolbar, Button, mergeClasses } from '@fluentui/react-components';

export const Component = props => {
  const classes = useStyles();
  const { isLive } = props;
  return (
    <Toolbar className={mergeClasses(classes.tabItemToolbar, isLive && classes.liveTabItemToolbar)}>
      <ToolbarButton>Italic</ToolbarButton>
    </Toolbar>
  );
};

// in COMPONENT_NAME.styles.ts
import { makeStyles, shorthands, tokens } from '@fluentui/react-components';

export const useStyles = makeStyles({
  tabItemToolbar: {
    height: '100%',
    display: 'inline-flex',
    alignItems: 'center',
    color: 'inherit',
  },
  liveTabItemToolbar: {
    color: tokens.colorPaletteSilverForeground1,
  },
});

Migrate overflow props

Before:

tsx
import { Toolbar } from '@fluentui/react-components';
const Component = () => (
  <Toolbar
    aria-label="Toolbar overflow menu"
    items={toolbarItems}
    overflow
    overflowOpen={overflowOpen}
    overflowItem={{
      title: 'More',
    }}
    onOverflowOpenChange={(e, { overflowOpen }) => {
      setOverflowOpen(overflowOpen);
    }}
    getOverflowItems={startIndex => itemData.slice(startIndex)}
  />
);

After:

See Toolbar Overflow Items example