Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/eui/changelogs/upcoming/9211.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Added `--euiBottomBarOffset` CSS variable to `EuiBottomBar` for positioning other fixed elements relative to the bottom bar's height
73 changes: 73 additions & 0 deletions packages/eui/src/components/bottom_bar/bottom_bar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,77 @@ describe('EuiBottomBar', () => {
expect(baseElement).toMatchSnapshot();
});
});

describe('CSS variables', () => {
test('sets the correct css variable for the bottom bar', () => {
const { unmount } = render(
<EuiBottomBar affordForDisplacement={true} usePortal={true}>
Content
</EuiBottomBar>
);

// The CSS variable should be set on the document root
const cssVarValue = getComputedStyle(
document.documentElement
).getPropertyValue('--euiBottomBarOffset');
expect(cssVarValue).toBeTruthy();
expect(cssVarValue).toMatch(/\d+px/);

unmount();

// After unmounting, the CSS variable should be cleared
const clearedValue = getComputedStyle(
document.documentElement
).getPropertyValue('--euiBottomBarOffset');
expect(clearedValue.trim()).toBe('');
});

test('does not set css variable when affordForDisplacement is false', () => {
render(
<EuiBottomBar affordForDisplacement={false}>Content</EuiBottomBar>
);

const cssVarValue = getComputedStyle(
document.documentElement
).getPropertyValue('--euiBottomBarOffset');
expect(cssVarValue.trim()).toBe('');
});

test('does not set css variable when usePortal is false', () => {
render(
<EuiBottomBar affordForDisplacement={true} usePortal={false}>
Content
</EuiBottomBar>
);

const cssVarValue = getComputedStyle(
document.documentElement
).getPropertyValue('--euiBottomBarOffset');
expect(cssVarValue.trim()).toBe('');
});

test('does not set css variable for non-fixed positions', () => {
const { unmount: unmountSticky } = render(
<EuiBottomBar position="sticky">Content</EuiBottomBar>
);

let cssVarValue = getComputedStyle(
document.documentElement
).getPropertyValue('--euiBottomBarOffset');
expect(cssVarValue.trim()).toBe('');

unmountSticky();

const { unmount: unmountStatic } = render(
<EuiBottomBar position="static">Content</EuiBottomBar>
);

cssVarValue = getComputedStyle(document.documentElement).getPropertyValue(
'--euiBottomBarOffset'
);
expect(cssVarValue.trim()).toBe('');

unmountStatic();
});
});
});
18 changes: 17 additions & 1 deletion packages/eui/src/components/bottom_bar/bottom_bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import React, {
import {
useCombinedRefs,
useEuiMemoizedStyles,
useEuiThemeCSSVariables,
EuiThemeProvider,
} from '../../services';
import { EuiScreenReaderOnly } from '../accessibility';
Expand Down Expand Up @@ -120,6 +121,7 @@ const _EuiBottomBar = forwardRef<
ref
) => {
const styles = useEuiMemoizedStyles(euiBottomBarStyles);
const { setGlobalCSSVariables } = useEuiThemeCSSVariables();

// Force some props if `fixed` position, but not if the user has supplied these
affordForDisplacement =
Expand All @@ -134,6 +136,11 @@ const _EuiBottomBar = forwardRef<
useEffect(() => {
if (affordForDisplacement && usePortal) {
document.body.style.paddingBottom = `${dimensions.height}px`;

// EUI doesn't use this css variable, but it is useful for consumers
setGlobalCSSVariables({
'--euiBottomBarOffset': `${dimensions.height}px`,
});
}

if (bodyClassName) {
Expand All @@ -143,13 +150,22 @@ const _EuiBottomBar = forwardRef<
return () => {
if (affordForDisplacement && usePortal) {
document.body.style.paddingBottom = '';
setGlobalCSSVariables({
'--euiBottomBarOffset': null,
});
}

if (bodyClassName) {
document.body.classList.remove(bodyClassName);
}
};
}, [affordForDisplacement, usePortal, dimensions, bodyClassName]);
}, [
affordForDisplacement,
usePortal,
dimensions,
bodyClassName,
setGlobalCSSVariables,
]);

const classes = classNames(
'euiBottomBar',
Expand Down
15 changes: 15 additions & 0 deletions packages/website/docs/components/containers/bottom-bar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,21 @@ export default () => {
};
```

### Relative positioning

When `affordForDisplacement` is enabled and the bottom bar is positioned as `fixed`, **EuiBottomBar** automatically sets a global CSS variable that you can use to position other fixed elements in your application relative to the bottom bar's height:

- `--euiBottomBarOffset` (Set when `affordForDisplacement={true}` and `position="fixed"`)

This variable is automatically updated when the bottom bar resizes and is removed when the bottom bar is closed.

```css
.custom-fixed-footer {
/* Adjust footer position when bottom bar is visible */
padding-bottom: var(--euiBottomBarOffset, 0);
}
```

## Props

import docgen from '@elastic/eui-docgen/dist/components/bottom_bar';
Expand Down