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
55 changes: 43 additions & 12 deletions packages/core/addon/components/eui-bottom-bar/index.hbs
Original file line number Diff line number Diff line change
@@ -1,29 +1,60 @@
{{!-- TODO: Add landmarkSupport after having an <EuiI18n> component support --}}
<EuiPortal>
{{! TODO: Add landmarkSupport after having an <EuiI18n> component support }}
{{#if this.usePortal}}
<EuiPortal>
<section
style={{this.bottomBarStyles}}
{{resize-observer onResize=(set this "dimensions")}}
class={{class-names
componentName="EuiBottomBar"
paddingSize=(arg-or-default @paddingSize "m")
positionType=(arg-or-default this.position "fixed")
}}
{{this.updateDisplacementModifier
affordForDisplacement=this.affordForDisplacement
usePortal=this.usePortal
dimensions=this.dimensions
bodyClassName=@bodyClassName
}}
...attributes
{{yield}}
</section>
</EuiPortal>
{{else}}
<section
style={{this.bottomBarStyles}}
{{resize-observer onResize=(set this "dimensions")}}
class={{class-names
componentName="EuiBottomBar"
paddingSize=(arg-or-default @paddingSize "m")
positionType=(arg-or-default this.position "fixed")
}}
aria-label={{if @landmarkHeading @landmarkHeading "Page level controls"}}
{{this.updateDisplacementModifier
affordForDisplacement=this.affordForDisplacement
usePortal=this.usePortal
dimensions=this.dimensions
bodyClassName=@bodyClassName
}}
{{!-- aria-label={{if @landmarkHeading @landmarkHeading "Page level controls"}} --}}
{{did-insert this.didInsert}}
{{did-update this.updateDisplacement this.affordForDisplacement}}
...attributes
>
{{!-- <div {{screen-reader-only}}>
<div {{screen-reader-only}}>
<h2>
{{if @landmarkHeading @landmarkHeading "Page level controls"}}
</h2>
</div> --}}
</div>
{{yield}}
</section>
{{!-- <div {{screen-reader-only}}>
<div {{screen-reader-only}}>
<p aria-live="assertive">
{{#if @landmarkHeading}}
There is a new region landmark called {{@landmarkHeading}} with page level controls at the end of the document.
There is a new region landmark called
{{@landmarkHeading}}
with page level controls at the end of the document.
{{else}}
There is a new region landmark with page level controls at the end of the document.
There is a new region landmark with page level controls at the end of
the document.
{{/if}}
</p>
</div> --}}
</EuiPortal>
</div>
{{/if}}
105 changes: 74 additions & 31 deletions packages/core/addon/components/eui-bottom-bar/index.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,94 @@
import GlimmerComponent from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { modifier } from 'ember-modifier';

interface EuiButtomBarArgs {
affordForDisplacement: boolean;
bodyClassName: string;
position?: 'fixed' | 'static' | 'sticky';
usePortal: boolean;
paddingSize?: 'none' | 's' | 'm' | 'l';
landmarkHeading?: string;
top: number;
right: number;
left: number;
bottom: number;
}
export default class EuiBottomBarComponent extends GlimmerComponent<EuiButtomBarArgs> {
get affordForDisplacement(): boolean {
return this.args.affordForDisplacement ?? true;

const updateDisplacementModifier = modifier(function (
element: Element,
_pos: unknown[],
{
affordForDisplacement,
usePortal,
bodyClassName,
dimensions
}: {
affordForDisplacement: boolean;
usePortal: boolean;
bodyClassName: string;
dimensions: { height: number };
}
) {
if (affordForDisplacement && usePortal) {
document.body.style.paddingBottom = `${dimensions.height}px`;
}

if (bodyClassName) {
document.body.classList.add(bodyClassName);
}

@action
didInsert(element: HTMLElement): void {
if (this.affordForDisplacement) {
const height = element.clientHeight;
document.body.style.paddingBottom = `${height}px`;
return () => {
if (affordForDisplacement && usePortal) {
document.body.style.paddingBottom = '';
}

if (this.args.bodyClassName) {
document.body.classList.add(this.args.bodyClassName);
if (bodyClassName) {
document.body.classList.remove(bodyClassName);
}
};
});

export default class EuiBottomBarComponent extends GlimmerComponent<EuiButtomBarArgs> {
updateDisplacementModifier = updateDisplacementModifier;

@tracked dimensions: { height: number; width: number } | undefined;

get affordForDisplacement(): boolean {
return this.position !== 'fixed'
? false
: this.args.affordForDisplacement ?? true;
}

@action
updateDisplacement(element: HTMLElement): void {
const prevAffordForDisplacement = document.body.style.paddingBottom !== '';
if (prevAffordForDisplacement !== this.affordForDisplacement) {
if (this.affordForDisplacement) {
// start affording for displacement
const height = element.clientHeight;
document.body.style.paddingBottom = `${height}px`;
} else {
// stop affording for displacement
document.body.style.paddingBottom = '';
}
}
get usePortal(): boolean {
return this.position !== 'fixed' ? false : true;
}

//TODO: Add/Remove bodyClassName prop from body classes when updated
get position(): string {
return this.args.position || 'fixed';
}

willDestroy(): void {
if (this.affordForDisplacement) {
document.body.style.paddingBottom = '';
}
get top(): number {
return this.args.top ? this.args.top : 0;
}

get right(): number {
return this.args.right ? this.args.right : 0;
}

get left(): number {
return this.args.left ? this.args.left : 0;
}

get bottom(): number {
return this.args.bottom ? this.args.bottom : 0;
}

if (this.args.bodyClassName) {
document.body.classList.remove(this.args.bodyClassName);
get bottomBarStyles(): string {
if (this.position === 'fixed') {
return `left:${this.left}px;right:${this.right}px;bottom:${this.bottom}px`;
} else {
return `top:${this.top}px;left:${this.left}px;right:${this.right}px;bottom:${this.bottom}px`;
}
}
}
10 changes: 9 additions & 1 deletion packages/core/addon/utils/css-mappings/eui-bottom-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,18 @@ const paddingSizeMapping = {
l: `${baseClass}--paddingLarge`
};

const positionMapping = {
none: '',
fixed: `${baseClass}--fixed`,
static: `${baseClass}--static`,
sticky: `${baseClass}--sticky`
};

const mapping: ComponentMapping = {
base: baseClass,
properties: {
paddingSize: paddingSizeMapping
paddingSize: paddingSizeMapping,
positionType: positionMapping
}
};

Expand Down
81 changes: 32 additions & 49 deletions packages/core/docs/layout/bottom-bar-demo/demo1.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,60 @@
```hbs template
---
order: 1
---

# Basic

<EuiText>
<b>EuiBottomBar</b> is a simple wrapper component that does nothing but fix a bottom bar (usually filled with buttons) to the bottom of the page. Use it when you have really long pages or complicated, multi-page forms. In the case of forms, only invoke it if a form is in a savable state.
<p>
<strong>EuiBottomBar</strong> is a simple wrapper component that does nothing but affix a dark bar (usually filled with buttons) to the bottom of the page. Use it when you have really long pages or complicated, multi-page forms. In the case of forms, only invoke it if a form is in a savable state.
</p>
<p>
Like many of our other wrapper components, <strong>EuiBottomBar</strong> accepts a <EuiCode>paddingSize</EuiCode> prop, which can be set to <EuiCode>s | m (default) | l | none</EuiCode>.
</p>
</EuiText>
<EuiSpacer/>

<EuiButton @color="primary" {{on "click" (set this "basicBottomBarActive" (not this.basicBottomBarActive))}}>
```hbs template
<EuiButton
@color='primary'
{{on
'click'
(set this 'basicBottomBarActive' (not this.basicBottomBarActive))
}}
>
Toggle appearance of the bottom bar
</EuiButton>

{{#if this.basicBottomBarActive}}
<EuiBottomBar>
<EuiFlexGroup @justifyContent="spaceBetween">
<EuiFlexGroup @justifyContent='spaceBetween'>
<EuiFlexItem @grow={{false}}>
<EuiFlexGroup @gutterSize="s">
<EuiFlexGroup @gutterSize='s'>
<EuiFlexItem @grow={{false}}>
<EuiButton @color="ghost" @size="s" @iconType="help">
<EuiButton @color='ghost' @size='s' @iconType='help'>
Help
</EuiButton>
</EuiFlexItem>
<EuiFlexItem @grow={{false}}>
<EuiButton @color="ghost" @size="s" @iconType="user">
<EuiButton @color='ghost' @size='s' @iconType='user'>
Add user
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem @grow={{false}}>
<EuiFlexGroup @gutterSize="s">
<EuiFlexGroup @gutterSize='s'>
<EuiFlexItem @grow={{false}}>
<EuiButtonEmpty @color="ghost" @size="s" @iconType="cross">
<EuiButtonEmpty @color='ghost' @size='s' @iconType='cross'>
Discard
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem @grow={{false}}>
<EuiButton @color="primary" @fill={{true}} @size="s" @iconType="check">
<EuiButton
@color='primary'
@fill={{true}}
@size='s'
@iconType='check'
>
Save
</EuiButton>
</EuiFlexItem>
Expand All @@ -42,44 +63,6 @@
</EuiFlexGroup>
</EuiBottomBar>
{{/if}}

<EuiSpacer/>

<EuiTitle>
Displacement
</EuiTitle>
<EuiText>
There is an affordForDisplacement prop (defaulting to true), which determines whether the component makes room for itself by adding bottom padding equivalent to its own height on the document body element. Setting this to false can be useful to minimize scrollbar visibility but will cause the bottom bar to overlap body content.
</EuiText>
<EuiSpacer/>
<EuiButton @color="primary" {{on "click" (queue
(set this "affordForDisplacement" true)
(set this "displacedBottomBarActive" true)
)}}>
Show bottom bar
</EuiButton>
<EuiButton @color="primary" {{on "click" (queue
(set this "affordForDisplacement" false)
(set this "displacedBottomBarActive" true)
)}}>
Show bottom bar (without affordForDisplacement behavior)
</EuiButton>
{{#if this.displacedBottomBarActive}}
<EuiBottomBar @affordForDisplacement={{this.affordForDisplacement}}>
<EuiFlexGroup @justifyContent="flexEnd">
<EuiFlexItem @grow={{false}}>
<EuiButtonEmpty
@color="ghost"
@size="s"
@iconType="cross"
{{on "click" (set this "displacedBottomBarActive" false)}}
>
close
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
</EuiBottomBar>
{{/if}}
```

```js component
Expand Down
54 changes: 54 additions & 0 deletions packages/core/docs/layout/bottom-bar-demo/demo2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
order: 2
---

# Positions

<EuiText>
<p>
Bottom bars default to a fixed position, in a portal at the bottom of the
browser window. Alternatively, you can change the <EuiCode>position</EuiCode> to <EuiCode>sticky</EuiCode> where
it will render in place but stick to the window only as the window edge
nears. The <EuiCode>static</EuiCode> position reverts back to default DOM behavior.
</p>
<p>
You can
also apply a different set of positioning locations just by adjusting them
in with the <EuiCode>top | right | bottom | left</EuiCode> props.
</p>
</EuiText>

```hbs template
<div>
<EuiText>
<p>
When scrolling past this example block, the
<strong>EuiBottomBar</strong>
will stick to the bottom of the browser window (with a 10px offset), but
keeps it within the bounds of its parent.
</p>
</EuiText>
<EuiSpacer @size='xl' />
<EuiSpacer @size='xl' />
<EuiBottomBar
@landmarkHeading='Page level controls'
@position='sticky'
@bottom={{10}}
>
<EuiText color='ghost' textAlign='center'>
<p>Scroll to see!</p>
</EuiText>
</EuiBottomBar>
</div>
```

```js component
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

export default class BottomBarDemo1Component extends Component {
@tracked basicBottomBarActive = false;
@tracked displacedBottomBarActive = false;
@tracked affordForDisplacement = true;
}
```
Loading