Overflow
View .mdLow-level utility that moves items that don't fit into an overflow menu. Subcomponents: OverflowItem.
Default
Loading interactive example. Full source is available below.
View example source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
export const Default = () => {
const itemIds = new Array(8).fill(0).map((_, index) => index.toString());
const OverflowMenuItem = ({ id }: {
id: string;
}) => {
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu = ({ ids }: {
ids: string[];
}) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{ids.map((id) => (<OverflowMenuItem key={id} id={id}/>))}
</MenuList>
</MenuPopover>
</Menu>);
};
const styles = /* css */ `
.overflow-default-example {
display: flex;
flex-wrap: nowrap;
min-width: 200px;
max-width: 800px;
overflow: hidden;
border: 2px solid var(--colorBrandBackground);
padding: var(--spacingVerticalXXL) 10px 10px;
position: relative;
resize: horizontal;
}
.overflow-default-example::after {
content: 'Resizable Area';
position: absolute;
padding: 1px var(--spacingHorizontalXS) 1px;
top: -2px;
left: -2px;
font-family: monospace;
font-size: 15px;
font-weight: 900;
line-height: 1;
letter-spacing: 1px;
color: var(--colorNeutralForegroundOnBrand);
background-color: var(--colorBrandBackground);
}
`;
return (<>
<style>{styles}</style>
<Overflow>
<div className="overflow-default-example">
{itemIds.map((id) => (<OverflowItem key={id} id={id}>
<Button>Item {id}</Button>
</OverflowItem>))}
<OverflowMenu ids={itemIds}/>
</div>
</Overflow>
</>);
};
export default Default;
API referenceGenerated CoreAI prop and type summaries
API
Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. ? means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.
Overflow API
Provides an OverflowContext for OverflowItem descendants.
interface OverflowProps {
children: ReactElement<any, string | JSXElementConstructor<any>>;
/**
* When true, reserve space as if the overflow menu were visible even with no overflowing items.
* @default false
*/
hasHiddenItems?: boolean;
/**
* Minimum number of items that must remain visible.
*/
minimumVisible?: number;
onOverflowChange?: ((ev: null, data: OverflowState) => void);
/**
* Overflow axis used for size measurement.
* @default horizontal
*/
overflowAxis?: "horizontal" | "vertical";
/**
* Direction where items are removed when overflow occurs.
* @default end
*/
overflowDirection?: "start" | "end";
/**
* Padding in pixels reserved at the end of the container before overflow occurs.
* Useful for accounting for extra elements (for example an overflow menu button)
* or margins between items that are difficult to measure in JavaScript.
* @default 10
*/
padding?: number;
/**
* Allows getting a ref to the component instance.
* Once the component unmounts, React will set `ref.current` to `null`
* (or call the ref with `null` if you passed a callback ref).
*/
ref?: LegacyRef<unknown>;
}
OverflowItem API
Attaches overflow item behavior to its child registered with the OverflowContext. It does not render an element of its own.
Behaves similarly to other *Trigger components in Fluent UI React.
interface OverflowItemProps {
/**
* The single child that has overflow item behavior attached.
*/
children: ReactElement<any, string | JSXElementConstructor<any>>;
/**
* Assigns the item to a group, group visibility can be watched.
*/
groupId?: string;
/**
* The unique identifier for the item used by the overflow manager.
*/
id: string;
/**
* If true, the item will never overflow and will always be visible.
* Mutually exclusive with `priority`.
*/
pinned?: boolean;
/**
* A higher priority means the item overflows later.
* Mutually exclusive with `pinned`.
*/
priority?: number;
/**
* Allows getting a ref to the component instance.
* Once the component unmounts, React will set `ref.current` to `null`
* (or call the ref with `null` if you passed a callback ref).
*/
ref?: LegacyRef<unknown>;
}
Implementation
CoreAI 0.12.0; Fluent 9.74.9.
Import components from @coreai-ds/react-components. CoreAI guidance above takes precedence over API demonstration examples.
Custom Component
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import type { ForwardRefComponent } from "@coreai-ds/react-components";
import * as React from 'react';
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const ItemVisibleCustomComponent: ForwardRefComponent<{
appId: string;
}> = React.forwardRef((props, ref) => {
const isVisible = useIsOverflowItemVisible(props.appId);
console.log(`Item ${props.appId} is ${isVisible ? '' : 'not '}visible'`);
return <Button ref={ref}>Item {props.appId}</Button>;
});
export const CustomComponent = (): JSXElement => {
const styles = useStyles();
const itemIds = new Array(8).fill(0).map((_, i) => i.toString());
return (<Overflow>
<div className={mergeClasses(styles.container, styles.resizableArea)}>
{itemIds.map(i => (<OverflowItem key={i} id={i}>
<ItemVisibleCustomComponent appId={i}/>
</OverflowItem>))}
</div>
</Overflow>);
};
export default CustomComponent;
Dividers
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
import { useIsOverflowGroupVisible } from "@coreai-ds/react-components";
import { Divider } from "@coreai-ds/react-components";
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { MenuDivider } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const OverflowGroupDivider: React.FC<{
groupId: string;
}> = props => {
const isGroupVisible = useIsOverflowGroupVisible(props.groupId);
if (isGroupVisible === 'hidden') {
return null;
}
return <Divider vertical appearance="brand" style={{ flexGrow: 0, paddingRight: '4px', paddingLeft: '4px' }}/>;
};
const OverflowMenuDivider: React.FC<{
id: string;
}> = props => {
const isGroupVisible = useIsOverflowGroupVisible(props.id);
if (isGroupVisible === 'visible') {
return null;
}
return <MenuDivider />;
};
const OverflowMenuItem: React.FC<{
id: string;
}> = props => {
const { id } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
}> = ({ itemIds }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(i => {
// This is purely a simplified convention for documentation examples
// Could be done in other ways too
if (typeof i === 'string' && i.startsWith('divider')) {
const groupId = i.split('-')[1];
return <OverflowMenuDivider key={i} id={groupId}/>;
}
return <OverflowMenuItem key={i} id={i}/>;
})}
</MenuList>
</MenuPopover>
</Menu>);
};
export const Dividers = (): JSXElement => {
const styles = useStyles();
return (<Overflow padding={40}>
<div className={mergeClasses(styles.container, styles.resizableArea)}>
<OverflowItem id={'1'} groupId={'1'}>
<Button>Item 1</Button>
</OverflowItem>
<OverflowGroupDivider groupId={'1'}/>
<OverflowItem id={'2'} groupId={'2'}>
<Button>Item 2</Button>
</OverflowItem>
<OverflowGroupDivider groupId={'2'}/>
<OverflowItem id={'3'} groupId={'3'}>
<Button>Item 3</Button>
</OverflowItem>
<OverflowItem id={'4'} groupId={'3'}>
<Button>Item 4</Button>
</OverflowItem>
<OverflowGroupDivider groupId={'3'}/>
<OverflowItem id={'5'} groupId={'4'}>
<Button>Item 5</Button>
</OverflowItem>
<OverflowItem id={'6'} groupId={'4'}>
<Button>Item 6</Button>
</OverflowItem>
<OverflowItem id={'7'} groupId={'4'}>
<Button>Item 7</Button>
</OverflowItem>
<OverflowGroupDivider groupId={'4'}/>
<OverflowItem id={'8'} groupId={'5'}>
<Button>Item 8</Button>
</OverflowItem>
<OverflowMenu itemIds={['1', 'divider-1', '2', 'divider-2', '3', '4', 'divider-3', '5', '6', '7', 'divider-4', '8']}/>
</div>
</Overflow>);
};
export default Dividers;
Larger Dividers
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
import { OverflowDivider } from "@coreai-ds/react-components";
import { ChevronRight20Regular } from "@fluentui/react-icons";
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { useIsOverflowGroupVisible } from "@coreai-ds/react-components";
import { MenuDivider } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const OverflowGroupDivider: React.FC<{
groupId: string;
}> = props => {
return (<OverflowDivider groupId={props.groupId}>
<div>
<ChevronRight20Regular />
</div>
</OverflowDivider>);
};
const OverflowMenuDivider: React.FC<{
id: string;
}> = props => {
const isGroupVisible = useIsOverflowGroupVisible(props.id);
if (isGroupVisible === 'visible') {
return null;
}
return <MenuDivider />;
};
const OverflowMenuItem: React.FC<{
id: string;
}> = props => {
const { id } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
}> = ({ itemIds }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(i => {
// This is purely a simplified convention for documentation examples
// Could be done in other ways too
if (typeof i === 'string' && i.startsWith('divider')) {
const groupId = i.split('-')[1];
return <OverflowMenuDivider key={i} id={groupId}/>;
}
return <OverflowMenuItem key={i} id={i}/>;
})}
</MenuList>
</MenuPopover>
</Menu>);
};
export const LargerDividers = (): JSXElement => {
const styles = useStyles();
return (<Overflow>
<div className={mergeClasses(styles.container, styles.resizableArea)}>
<OverflowItem id={'1'} groupId={'1'}>
<Button>Item 1</Button>
</OverflowItem>
<OverflowGroupDivider groupId={'1'}/>
<OverflowItem id={'2'} groupId={'2'}>
<Button>Item 2</Button>
</OverflowItem>
<OverflowGroupDivider groupId={'2'}/>
<OverflowItem id={'3'} groupId={'3'}>
<Button>Item 3</Button>
</OverflowItem>
<OverflowItem id={'4'} groupId={'3'}>
<Button>Item 4</Button>
</OverflowItem>
<OverflowGroupDivider groupId={'3'}/>
<OverflowItem id={'5'} groupId={'4'}>
<Button>Item 5</Button>
</OverflowItem>
<OverflowItem id={'6'} groupId={'4'}>
<Button>Item 6</Button>
</OverflowItem>
<OverflowItem id={'7'} groupId={'4'}>
<Button>Item 7</Button>
</OverflowItem>
<OverflowGroupDivider groupId={'4'}/>
<OverflowItem id={'8'} groupId={'5'}>
<Button>Item 8</Button>
</OverflowItem>
<OverflowMenu itemIds={['1', 'divider-1', '2', 'divider-2', '3', '4', 'divider-3', '5', '6', '7', 'divider-4', '8']}/>
</div>
</Overflow>);
};
export default LargerDividers;
Listen To Changes
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { OverflowItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const OverflowMenuItem: React.FC<Pick<OverflowItemProps, 'id'>> = props => {
const { id } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
// As an union between button props and div props may be conflicting, casting is required
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
}> = ({ itemIds }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(i => {
return <OverflowMenuItem key={i} id={i}/>;
})}
</MenuList>
</MenuPopover>
</Menu>);
};
export const ListenToChanges = (): JSXElement => {
const styles = useStyles();
const itemIds = new Array(8).fill(0).map((_, i) => i.toString());
const [overflowState, setOverflowState] = React.useState<object>({});
return (<>
<Overflow onOverflowChange={(e, data) => setOverflowState(data)}>
<div className={mergeClasses(styles.container, styles.resizableArea)}>
{itemIds.map(i => (<OverflowItem key={i} id={i}>
<Button>Item {i}</Button>
</OverflowItem>))}
<OverflowMenu itemIds={itemIds}/>
</div>
</Overflow>
<pre>{JSON.stringify(overflowState, null, 2)}</pre>
</>);
};
export default ListenToChanges;
Minimum Visible
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { OverflowItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const OverflowMenuItem: React.FC<Pick<OverflowItemProps, 'id'>> = props => {
const { id } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
// As an union between button props and div props may be conflicting, casting is required
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
}> = ({ itemIds }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(i => {
return <OverflowMenuItem key={i} id={i}/>;
})}
</MenuList>
</MenuPopover>
</Menu>);
};
export const MinimumVisible = (): JSXElement => {
const styles = useStyles();
const itemIds = new Array(8).fill(0).map((_, i) => i.toString());
return (<Overflow minimumVisible={4}>
<div className={mergeClasses(styles.container, styles.resizableArea)}>
{itemIds.map(i => (<OverflowItem key={i} id={i}>
<Button style={{ paddingLeft: 2, paddingRight: 2 }}>Item {i}</Button>
</OverflowItem>))}
<OverflowMenu itemIds={itemIds}/>
</div>
</Overflow>);
};
export default MinimumVisible;
Overflow By Priority
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { OverflowItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const OverflowMenuItem: React.FC<Pick<OverflowItemProps, 'id'>> = props => {
const { id } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
// As an union between button props and div props may be conflicting, casting is required
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
}> = ({ itemIds }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(i => {
return <OverflowMenuItem key={i} id={i}/>;
})}
</MenuList>
</MenuPopover>
</Menu>);
};
export const OverflowByPriority = (): JSXElement => {
const styles = useStyles();
const priorities = [2, 3, 6, 1, 4, 5, 0, 7];
return (<Overflow>
<div className={mergeClasses(styles.container, styles.resizableArea)}>
{priorities.map(i => (<OverflowItem key={i} id={i.toString()} priority={i}>
<Button>Priority {i}</Button>
</OverflowItem>))}
<OverflowMenu itemIds={priorities.map(x => x.toString())}/>
</div>
</Overflow>);
};
export default OverflowByPriority;
Pinned
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { OverflowItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const OverflowSelectionItem: React.FC<{
onSelectItem?: (item: string) => void;
selected?: boolean;
id: string;
}> = props => {
const onClick = () => {
props.onSelectItem?.(props.id);
};
return (<OverflowItem id={props.id} pinned={props.selected}>
<Button aria-pressed={props.selected ? 'true' : 'false'} appearance={props.selected ? 'primary' : 'secondary'} onClick={onClick}>
Item {props.id}
</Button>
</OverflowItem>);
};
const OverflowMenuItem: React.FC<Pick<OverflowItemProps, 'id'> & {
onClick: () => void;
}> = props => {
const { id, onClick } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
return <MenuItem onClick={onClick}>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
onSelect: (itemId: string) => void;
}> = ({ itemIds, onSelect }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(i => (<OverflowMenuItem onClick={() => onSelect(i)} key={i} id={i}/>))}
</MenuList>
</MenuPopover>
</Menu>);
};
export const Pinned = (): JSXElement => {
const styles = useStyles();
const [selected, setSelected] = React.useState<Set<string>>(() => new Set(['6']));
const onSelect = (itemId: string) => {
setSelected(prev => {
const next = new Set(prev);
if (next.has(itemId)) {
next.delete(itemId);
}
else {
next.add(itemId);
}
return next;
});
};
const itemIds = new Array(8).fill(0).map((_, i) => i.toString());
return (<Overflow>
<div className={mergeClasses(styles.container, styles.resizableArea)}>
{itemIds.map(i => (<OverflowSelectionItem onSelectItem={onSelect} key={i} id={i} selected={selected.has(i)}/>))}
<OverflowMenu itemIds={itemIds} onSelect={onSelect}/>
</div>
</Overflow>);
};
export default Pinned;
Priority With Dividers
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
import { useIsOverflowGroupVisible } from "@coreai-ds/react-components";
import { Divider } from "@coreai-ds/react-components";
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { MenuDivider } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const GROUPS = {
ONE: 1,
TWO: 2,
THREE: 3,
FOUR: 4,
FIVE: 5,
};
const OverflowGroupDivider: React.FC<{
groupId: number;
}> = props => {
const groupVisibility = useIsOverflowGroupVisible(props.groupId.toString());
if (groupVisibility === 'hidden') {
return null;
}
return (<Divider data-group={props.groupId} vertical appearance="brand" style={{ flexGrow: 0, paddingRight: '4px', paddingLeft: '4px' }}/>);
};
const OverflowMenuDivider: React.FC<{
groupId: number;
}> = props => {
const { groupId } = props;
// ⚠️⚠️ This is important
// When collapsing based on custom priority, it's necessary to know
// about other overflow groups because dividers can be rendered both
// in the overflow container and the overflow menu.
// The below code sorts the overflow groups and determines
// if a divider should be rendered.
const groupVisibilities = Object.values(GROUPS).map(group => {
// eslint-disable-next-line react-hooks/rules-of-hooks
return { group, visibility: useIsOverflowGroupVisible(group.toString()) };
});
const currentGroupPosition = groupVisibilities.findIndex(x => x.group === groupId);
const precedesOverflowingGroup = groupVisibilities
.slice(currentGroupPosition + 1)
// If there is a overflowing/hidden group after the current group
// render the menu divider.
.some(groupVisibility => groupVisibility.visibility !== 'visible');
if (groupVisibilities[currentGroupPosition].visibility === 'visible' || !precedesOverflowingGroup) {
return null;
}
return <MenuDivider />;
};
const OverflowMenuItem: React.FC<{
id: string;
}> = props => {
const { id } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
}> = ({ itemIds }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(itemId => {
// This is purely a simplified convention for documentation examples
// Could be done in other ways too
if (itemId.startsWith('divider')) {
const groupId = itemId.split('-')[1];
return <OverflowMenuDivider key={itemId} groupId={Number(groupId)}/>;
}
return <OverflowMenuItem key={itemId} id={itemId}/>;
})}
</MenuList>
</MenuPopover>
</Menu>);
};
export const PriorityWithDividers = (): JSXElement => {
const styles = useStyles();
return (<Overflow overflowDirection="start" padding={40}>
<div className={mergeClasses(styles.container, styles.resizableArea)}>
<OverflowItem id={'6'} priority={6} groupId={GROUPS.ONE.toString()}>
<Button>Priority 6</Button>
</OverflowItem>
<OverflowGroupDivider groupId={GROUPS.ONE}/>
<OverflowItem id={'7'} priority={7} groupId={GROUPS.TWO.toString()}>
<Button>Priority 7</Button>
</OverflowItem>
<OverflowGroupDivider groupId={GROUPS.TWO}/>
<OverflowItem id={'4'} priority={4} groupId={GROUPS.THREE.toString()}>
<Button>Priority 4</Button>
</OverflowItem>
<OverflowItem id={'5'} priority={5} groupId={GROUPS.THREE.toString()}>
<Button>Priority 5</Button>
</OverflowItem>
<OverflowGroupDivider groupId={GROUPS.THREE}/>
<OverflowItem id={'1'} priority={1} groupId={GROUPS.FOUR.toString()}>
<Button>Priority 1</Button>
</OverflowItem>
<OverflowItem id={'2'} priority={2} groupId={GROUPS.FOUR.toString()}>
<Button>Priority 2</Button>
</OverflowItem>
<OverflowItem id={'3'} priority={3} groupId={GROUPS.FOUR.toString()}>
<Button>Priority 3</Button>
</OverflowItem>
<OverflowGroupDivider groupId={GROUPS.FOUR}/>
<OverflowItem id={'8'} priority={8} groupId={GROUPS.FIVE.toString()}>
<Button>Priority 8</Button>
</OverflowItem>
<OverflowMenu itemIds={['6', 'divider-1', '7', 'divider-2', '4', '5', 'divider-3', '1', '2', '3', 'divider-4', '8']}/>
</div>
</Overflow>);
};
export default PriorityWithDividers;
Reorder Observer
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { OverflowReorderObserver } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { OverflowItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
controls: {
display: 'flex',
gap: '8px',
marginTop: '12px',
},
});
const INITIAL_IDS = new Array(8).fill(0).map((_, i) => i.toString());
const OverflowMenuItem: React.FC<Pick<OverflowItemProps, 'id'>> = props => {
const { id } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
}> = ({ itemIds }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(id => (<OverflowMenuItem key={id} id={id}/>))}
</MenuList>
</MenuPopover>
</Menu>);
};
export const ReorderObserver = (): JSXElement => {
const styles = useStyles();
const [itemIds, setItemIds] = React.useState(INITIAL_IDS);
return (<>
<Overflow>
<div className={mergeClasses(styles.container, styles.resizableArea)}>
<OverflowReorderObserver />
{itemIds.map(id => (<OverflowItem key={id} id={id}>
<Button>Item {id}</Button>
</OverflowItem>))}
<OverflowMenu itemIds={itemIds}/>
</div>
</Overflow>
<div className={styles.controls}>
<Button onClick={() => setItemIds(prev => [...prev].reverse())}>Reverse order</Button>
<Button onClick={() => setItemIds(INITIAL_IDS)}>Reset</Button>
</div>
</>);
};
export default ReorderObserver;
Reverse Dom Order
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import * as React from 'react';
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { OverflowItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const OverflowMenuItem: React.FC<Pick<OverflowItemProps, 'id'>> = props => {
const { id } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
// As an union between button props and div props may be conflicting, casting is required
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
}> = ({ itemIds }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(i => {
return <OverflowMenuItem key={i} id={i}/>;
})}
</MenuList>
</MenuPopover>
</Menu>);
};
export const ReverseDomOrder = (): JSXElement => {
const styles = useStyles();
const itemIds = new Array(8).fill(0).map((_, i) => i.toString());
return (<Overflow overflowDirection="start">
<div className={mergeClasses(styles.container, styles.resizableArea)}>
<OverflowMenu itemIds={itemIds}/>
{itemIds.map(i => (<OverflowItem key={i} id={i}>
<Button>Item {i}</Button>
</OverflowItem>))}
</div>
</Overflow>);
};
export default ReverseDomOrder;
Vertical
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { OverflowItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
minWidth: 0,
overflow: 'hidden',
},
overflowItem: {
display: 'block',
},
resizableArea: {
minWidth: '200px',
maxWidth: '800px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
position: 'relative',
resize: 'vertical',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const OverflowMenuItem: React.FC<Pick<OverflowItemProps, 'id'>> = props => {
const { id } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
}> = ({ itemIds }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(i => {
return <OverflowMenuItem key={i} id={i}/>;
})}
</MenuList>
</MenuPopover>
</Menu>);
};
export const Vertical = (): JSXElement => {
const styles = useStyles();
const itemIds = new Array(8).fill(0).map((_, i) => i.toString());
return (<Overflow overflowAxis="vertical">
<div className={mergeClasses(styles.container, styles.resizableArea)}>
{itemIds.map(i => (<OverflowItem key={i} id={i}>
<Button className={styles.overflowItem}>Item {i}</Button>
</OverflowItem>))}
<OverflowMenu itemIds={itemIds}/>
</div>
</Overflow>);
};
export default Vertical;
Wrapped
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { OverflowItem } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MenuButton } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { OverflowItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const useStyles = makeStyles({
container: {
display: 'flex',
flexGrow: 1,
flexWrap: 'nowrap',
minWidth: 0,
overflow: 'hidden',
},
farItems: {
display: 'flex',
gap: '4px',
flexWrap: 'nowrap',
marginRight: '10px', //to allow the resize handle to be grabbed
},
resizableArea: {
display: 'flex',
flexWrap: 'nowrap',
minWidth: '200px',
maxWidth: '1000px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '20px 10px 10px 10px',
overflow: 'hidden',
position: 'relative',
resize: 'horizontal',
'::after': {
content: `'Resizable Area'`,
position: 'absolute',
padding: '1px 4px 1px',
top: '-2px',
left: '-2px',
fontFamily: 'monospace',
fontSize: '15px',
fontWeight: 900,
lineHeight: 1,
letterSpacing: '1px',
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
},
},
});
const OverflowMenuItem: React.FC<Pick<OverflowItemProps, 'id'>> = props => {
const { id } = props;
const isVisible = useIsOverflowItemVisible(id);
if (isVisible) {
return null;
}
// As an union between button props and div props may be conflicting, casting is required
return <MenuItem>Item {id}</MenuItem>;
};
const OverflowMenu: React.FC<{
itemIds: string[];
}> = ({ itemIds }) => {
const { ref, overflowCount, isOverflowing } = useOverflowMenu<HTMLButtonElement>();
if (!isOverflowing) {
return null;
}
return (<Menu>
<MenuTrigger disableButtonEnhancement>
<MenuButton ref={ref}>+{overflowCount} items</MenuButton>
</MenuTrigger>
<MenuPopover>
<MenuList>
{itemIds.map(i => {
return <OverflowMenuItem key={i} id={i}/>;
})}
</MenuList>
</MenuPopover>
</Menu>);
};
export const Wrapped = (): JSXElement => {
const itemIds = new Array(8).fill(0).map((_, i) => i.toString());
const styles = useStyles();
return (<div className={styles.resizableArea}>
<Overflow>
<div className={styles.container}>
{itemIds.map(i => (<OverflowItem key={i} id={i.toString()}>
<Button>Item{i}</Button>
</OverflowItem>))}
<OverflowMenu itemIds={itemIds}/>
</div>
</Overflow>
<div className={styles.farItems}>
<Button>Foo</Button>
<Button>Bar</Button>
</div>
</div>);
};
export default Wrapped;