Skip to content

Commit

Permalink
MenuRenderer: Ensure menu is visible in container with overflow hidden
Browse files Browse the repository at this point in the history
  • Loading branch information
felixhabib committed Dec 3, 2024
1 parent 6a118bc commit d32f6ae
Show file tree
Hide file tree
Showing 10 changed files with 350 additions and 197 deletions.
10 changes: 10 additions & 0 deletions .changeset/fair-horses-sneeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'braid-design-system': patch
---

---
updated:
- MenuRenderer
---

**MenuRenderer**: Ensure menu is visible, even when its trigger element is inside a container with overflow hidden.
12 changes: 12 additions & 0 deletions .changeset/four-cobras-suffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'braid-design-system': patch
---

---
updated:
- OverflowMenu
---

**OverflowMenu**: Simplify internal layout.

Refactor the internal layout of `OverflowMenu` to improve the alignment of the menu with the button.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const actionTypes = {
MENU_TRIGGER_TAB: 13,
MENU_TRIGGER_ESCAPE: 14,
BACKDROP_CLICK: 15,
WINDOW_RESIZE: 16,
} as const;

export type Action =
Expand Down Expand Up @@ -49,4 +50,5 @@ export type Action =
| { type: typeof actionTypes.MENU_TRIGGER_CLICK }
| { type: typeof actionTypes.MENU_TRIGGER_TAB }
| { type: typeof actionTypes.MENU_TRIGGER_ESCAPE }
| { type: typeof actionTypes.BACKDROP_CLICK };
| { type: typeof actionTypes.BACKDROP_CLICK }
| { type: typeof actionTypes.WINDOW_RESIZE };
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { createVar, style, styleVariants } from '@vanilla-extract/css';
import {
createVar,
keyframes,
style,
styleVariants,
} from '@vanilla-extract/css';
import { calc } from '@vanilla-extract/css-utils';
import { vars } from '../../themes/vars.css';

Expand All @@ -7,9 +12,28 @@ export const backdrop = style({
height: '100vh',
});

export const menuIsClosed = style({
transform: `translateY(${calc(vars.grid).negate().multiply(2)})`,
visibility: 'hidden',
export const triggerVars = {
top: createVar(),
left: createVar(),
bottom: createVar(),
right: createVar(),
};

// Top and bottom reversed to allow for a more natural API
export const menuPosition = style({
top: triggerVars.bottom,
bottom: triggerVars.top,
left: triggerVars.left,
right: triggerVars.right,
});

export const animation = style({
animation: `${keyframes({
from: {
transform: `translateY(${calc(vars.grid).negate().multiply(2)})`,
opacity: 0,
},
})} .125s ease forwards`,
});

const widthVar = createVar();
Expand All @@ -23,10 +47,6 @@ export const width = styleVariants({ small, medium, large }, (w) => [
{ vars: { [widthVar]: w } },
]);

export const placementBottom = style({
bottom: '100%',
});

export const menuYPadding = 'xxsmall';

export const menuHeightLimit = style({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ const defaultProps = {
placement: 'bottom',
} as const;

const triggerHeight = 44;

const triggerPosition = {
top: triggerHeight,
left: 0,
bottom: 0, // this value is ignored when placement is top
right: 0, // this value is ignored when align is left
};

export const screenshots: ComponentScreenshot = {
screenshotWidths: [320],
examples: [
Expand All @@ -39,7 +48,7 @@ export const screenshots: ComponentScreenshot = {
offsetSpace="small"
trigger={(triggerProps) => (
<Box userSelect="none" cursor="pointer" {...triggerProps}>
<Placeholder height={44} label="Menu trigger" />
<Placeholder height={triggerHeight} label="Menu trigger" />
</Box>
)}
>
Expand All @@ -58,7 +67,7 @@ export const screenshots: ComponentScreenshot = {
offsetSpace="small"
trigger={(triggerProps) => (
<Box userSelect="none" cursor="pointer" {...triggerProps}>
<Placeholder height={44} label="Menu trigger" />
<Placeholder height={triggerHeight} label="Menu trigger" />
</Box>
)}
>
Expand All @@ -76,7 +85,7 @@ export const screenshots: ComponentScreenshot = {
offsetSpace="small"
trigger={(triggerProps) => (
<Box userSelect="none" cursor="pointer" {...triggerProps}>
<Placeholder height={44} label="Menu trigger" />
<Placeholder height={triggerHeight} label="Menu trigger" />
</Box>
)}
>
Expand All @@ -90,7 +99,7 @@ export const screenshots: ComponentScreenshot = {
Example: () => (
<Box display="flex">
<Box position="relative">
<Placeholder height={44} label="Menu trigger" />
<Placeholder height={triggerHeight} label="Menu trigger" />
<Menu {...defaultProps} placement="bottom">
<MenuItem onClick={() => {}}>Item</MenuItem>
<MenuItem onClick={() => {}}>Item</MenuItem>
Expand All @@ -104,7 +113,7 @@ export const screenshots: ComponentScreenshot = {
Example: () => (
<Box display="flex">
<Box position="relative">
<Placeholder height={44} label="Menu trigger" />
<Placeholder height={triggerHeight} label="Menu trigger" />
<Menu {...defaultProps} placement="bottom" offsetSpace="small">
<MenuItem onClick={() => {}}>Item</MenuItem>
<MenuItem onClick={() => {}}>Item</MenuItem>
Expand All @@ -120,15 +129,16 @@ export const screenshots: ComponentScreenshot = {
display="flex"
style={{
paddingTop: calc(vars.touchableSize).multiply(2.5).toString(),
marginBottom: calc(vars.touchableSize)
.multiply(1.5)
.negate()
.toString(),
}}
>
<Box position="relative">
<Placeholder height={44} label="Menu trigger" />
<Menu {...defaultProps} placement="top">
<Placeholder height={triggerHeight} label="Menu trigger" />
<Menu
{...defaultProps}
placement="top"
triggerPosition={triggerPosition}
position="absolute"
>
<MenuItem onClick={() => {}}>Item</MenuItem>
<MenuItem onClick={() => {}}>Item</MenuItem>
</Menu>
Expand All @@ -143,15 +153,17 @@ export const screenshots: ComponentScreenshot = {
display="flex"
style={{
paddingTop: calc(vars.touchableSize).multiply(2.5).toString(),
marginBottom: calc(vars.touchableSize)
.multiply(1.5)
.negate()
.toString(),
}}
>
<Box position="relative">
<Placeholder height={44} label="Menu trigger" />
<Menu {...defaultProps} placement="top" offsetSpace="small">
<Menu
{...defaultProps}
placement="top"
offsetSpace="small"
triggerPosition={triggerPosition}
position="absolute"
>
<MenuItem onClick={() => {}}>Item</MenuItem>
<MenuItem onClick={() => {}}>Item</MenuItem>
</Menu>
Expand Down
Loading

0 comments on commit d32f6ae

Please sign in to comment.