Skip to content

Commit

Permalink
MenuRenderer, OverflowMenu: Provide improved scroll affordance
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeltaranto committed Dec 2, 2024
1 parent 6a118bc commit dd5b1a6
Show file tree
Hide file tree
Showing 11 changed files with 342 additions and 143 deletions.
13 changes: 13 additions & 0 deletions .changeset/curvy-stingrays-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'braid-design-system': patch
---

---
updated:
- Tabs
---

**Tabs:** Provide left and right scroll affordance

Previously a fade out was applied to the right to provide a visual cue that there were more tabs overflowing to the right.
This technique is now applied to the left as well, providing cues in both directions.
13 changes: 13 additions & 0 deletions .changeset/fast-hounds-kick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'braid-design-system': patch
---

---
updated:
- MenuRenderer
- OverflowMenu
---

**MenuRenderer, OverflowMenu:** Provide improved scroll affordance

Introduce scroll affordance to menus providing a visual cue that there are more items overflowing vertically.
2 changes: 2 additions & 0 deletions packages/braid-design-system/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@
"react-is": "^18.2.0",
"react-popper-tooltip": "^4.3.1",
"react-remove-scroll": "^2.5.3",
"throttle-debounce": "^5.0.2",
"utility-types": "^3.10.0",
"uuid": "^8.3.2"
},
Expand Down Expand Up @@ -234,6 +235,7 @@
"@types/react-router-dom": "^5.3.3",
"@types/sanitize-html": "^2.6.2",
"@types/testing-library__jest-dom": "^5.9.1",
"@types/throttle-debounce": "^5.0.2",
"@types/uuid": "^8.3.0",
"babel-plugin-macros": "^3.1.0",
"babel-plugin-transform-remove-imports": "^1.7.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,4 @@ export const menuHeightLimit = style({
.multiply(9.5)
.add(vars.space[menuYPadding])
.toString(),
overflowY: 'auto',
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { MenuItemDivider } from '../MenuItemDivider/MenuItemDivider';
import { normalizeKey } from '../private/normalizeKey';
import { getNextIndex } from '../private/getNextIndex';
import { Overlay } from '../private/Overlay/Overlay';
import { ScrollContainer } from '../private/ScrollContainer/ScrollContainer';
import { type Action, actionTypes } from './MenuRenderer.actions';
import { MenuRendererContext } from './MenuRendererContext';
import { MenuRendererItemContext } from './MenuRendererItemContext';
Expand Down Expand Up @@ -368,6 +369,7 @@ export function Menu({
boxShadow={placement === 'top' ? 'small' : 'medium'}
borderRadius={borderRadius}
background="surface"
paddingY={styles.menuYPadding}
marginTop={placement === 'bottom' ? offsetSpace : undefined}
marginBottom={placement === 'top' ? offsetSpace : undefined}
transition="fast"
Expand All @@ -380,30 +382,32 @@ export function Menu({
placement === 'top' && styles.placementBottom,
]}
>
<Box paddingY={styles.menuYPadding} className={styles.menuHeightLimit}>
{Children.map(children, (item, i) => {
if (isDivider(item)) {
dividerCount++;
return item;
}
<ScrollContainer direction="vertical">
<Box className={styles.menuHeightLimit}>
{Children.map(children, (item, i) => {
if (isDivider(item)) {
dividerCount++;
return item;
}

const menuItemIndex = i - dividerCount;
const menuItemIndex = i - dividerCount;

return (
<MenuRendererItemContext.Provider
key={menuItemIndex}
value={{
isHighlighted: menuItemIndex === highlightIndex,
index: menuItemIndex,
dispatch,
focusTrigger,
}}
>
{item}
</MenuRendererItemContext.Provider>
);
})}
</Box>
return (
<MenuRendererItemContext.Provider
key={menuItemIndex}
value={{
isHighlighted: menuItemIndex === highlightIndex,
index: menuItemIndex,
dispatch,
focusTrigger,
}}
>
{item}
</MenuRendererItemContext.Provider>
);
})}
</Box>
</ScrollContainer>
<Overlay
boxShadow="borderNeutralLight"
borderRadius={borderRadius}
Expand Down
24 changes: 3 additions & 21 deletions packages/braid-design-system/src/lib/components/Tabs/Tabs.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { colorModeStyle } from '../../css/colorModeStyle';
import { vars } from '../../themes/vars.css';

export const tab = style({
whiteSpace: 'nowrap',
selectors: {
'&::-moz-focus-inner': {
border: 0,
Expand All @@ -19,27 +20,8 @@ export const hoveredTab = style({
},
});

export const nowrap = style({
whiteSpace: 'nowrap',
});

export const scroll = style({
WebkitOverflowScrolling: 'touch',
overflowX: 'auto',
overflowY: 'hidden',
scrollbarWidth: 'none',
msOverflowStyle: 'none',
selectors: {
'&::-webkit-scrollbar': {
width: 0,
height: 0,
},
},
});

export const mask = style({
maskImage:
'linear-gradient(90deg, rgba(0,0,0,1) 0, rgba(0,0,0,1) calc(100% - 80px), rgba(0,0,0,0) 100%)',
export const tabsList = style({
width: 'fit-content',
});

export const marginAuto = style({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,51 @@ const docs: ComponentDocs = {
</Stack>,
),
},
{
label: 'Reserve hit area',
description: (
<>
<Text>
By default, a <Strong>Tab</Strong> will only occupy the vertical
space from the top of the label to the active underline. This means
the hit area will bleed out into the space above.
</Text>
<Text>
The bleed can be disabled by setting the{' '}
<Strong>reserveHitArea</Strong> prop to <Strong>true</Strong>.
</Text>
</>
),
Example: ({ id }) =>
source(
<TabsProvider id={id}>
<Stack space="medium">
<Tabs label="Reserve hit area tabs" reserveHitArea>
<Tab>The first tab</Tab>
<Tab>The second tab</Tab>
<Tab>The third tab</Tab>
<Tab badge={<Badge tone="positive">New</Badge>}>
The fourth tab
</Tab>
</Tabs>
<TabPanels>
<TabPanel>
<Placeholder height={200} label="Panel 1" />
</TabPanel>
<TabPanel>
<Placeholder height={200} label="Panel 2" />
</TabPanel>
<TabPanel>
<Placeholder height={200} label="Panel 3" />
</TabPanel>
<TabPanel>
<Placeholder height={200} label="Panel 4" />
</TabPanel>
</TabPanels>
</Stack>
</TabsProvider>,
),
},
{
label: 'State management',
description: (
Expand All @@ -398,7 +443,7 @@ const docs: ComponentDocs = {
onChange={(index, item) => setState('tab', item)}
>
<Stack space="medium">
<Tabs label="Test tabs" divider="none" reserveHitArea>
<Tabs label="Controlled state tabs">
<Tab item="first">The first tab</Tab>
<Tab item="second">The second tab</Tab>
<Tab item="third">The third tab</Tab>
Expand Down
Loading

0 comments on commit dd5b1a6

Please sign in to comment.