mirror of
https://github.com/prymitive/karma
synced 2026-05-07 03:26:52 +00:00
fix(ui): better navbar hiding when idle
Don't destroy navbar since modals are mounted on it + update visibility after transition so animations work as expected
This commit is contained in:
@@ -22,10 +22,6 @@ import "./index.css";
|
||||
const DesktopIdleTimeout = 1000 * 60 * 3;
|
||||
const MobileIdleTimeout = 1000 * 5;
|
||||
|
||||
const NavbarOnResize = function(width, height) {
|
||||
document.body.style["padding-top"] = `${height + 4}px`;
|
||||
};
|
||||
|
||||
const NavBar = observer(
|
||||
class NavBar extends Component {
|
||||
static propTypes = {
|
||||
@@ -34,24 +30,63 @@ const NavBar = observer(
|
||||
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired
|
||||
};
|
||||
|
||||
elementSize = observable(
|
||||
{
|
||||
width: 0,
|
||||
height: 0,
|
||||
setSize(width, height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
},
|
||||
{ setSize: action }
|
||||
);
|
||||
|
||||
activityStatus = observable(
|
||||
{
|
||||
idle: false,
|
||||
className: "visible",
|
||||
setIdle() {
|
||||
this.idle = true;
|
||||
},
|
||||
setActive() {
|
||||
this.idle = false;
|
||||
},
|
||||
hide() {
|
||||
this.className = "invisible";
|
||||
},
|
||||
show() {
|
||||
this.className = "visible";
|
||||
}
|
||||
},
|
||||
{
|
||||
setIdle: action.bound,
|
||||
setActive: action.bound
|
||||
setActive: action.bound,
|
||||
hide: action.bound,
|
||||
show: action.bound
|
||||
}
|
||||
);
|
||||
|
||||
updateBodyPaddingTop = () => {
|
||||
const paddingTop = this.activityStatus.idle
|
||||
? 0
|
||||
: this.elementSize.height + 4;
|
||||
document.body.style["padding-top"] = `${paddingTop}px`;
|
||||
};
|
||||
|
||||
onHide = () => {
|
||||
NavbarOnResize(0, 0);
|
||||
this.activityStatus.hide();
|
||||
this.updateBodyPaddingTop();
|
||||
};
|
||||
|
||||
onShow = () => {
|
||||
this.updateBodyPaddingTop();
|
||||
this.activityStatus.show();
|
||||
};
|
||||
|
||||
onResize = (width, height) => {
|
||||
this.elementSize.setSize(width, height);
|
||||
this.updateBodyPaddingTop();
|
||||
};
|
||||
|
||||
render() {
|
||||
@@ -76,12 +111,12 @@ const NavBar = observer(
|
||||
<DropdownSlide
|
||||
in={!this.activityStatus.idle}
|
||||
appear={false}
|
||||
onEntered={this.onShow}
|
||||
onExited={this.onHide}
|
||||
unmountOnExit
|
||||
>
|
||||
<div className="container">
|
||||
<div className={`container ${this.activityStatus.className}`}>
|
||||
<nav className="navbar fixed-top navbar-expand navbar-dark p-1 bg-primary-transparent d-inline-block">
|
||||
<ReactResizeDetector handleHeight onResize={NavbarOnResize} />
|
||||
<ReactResizeDetector handleHeight onResize={this.onResize} />
|
||||
<span className="navbar-brand my-0 mx-2 h1 d-none d-sm-block float-left">
|
||||
{alertStore.info.totalAlerts}
|
||||
<FetchIndicator alertStore={alertStore} />
|
||||
@@ -110,4 +145,4 @@ const NavBar = observer(
|
||||
}
|
||||
);
|
||||
|
||||
export { NavBar, NavbarOnResize };
|
||||
export { NavBar };
|
||||
|
||||
@@ -7,7 +7,7 @@ import moment from "moment";
|
||||
import { AlertStore, NewUnappliedFilter } from "Stores/AlertStore";
|
||||
import { Settings } from "Stores/Settings";
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { NavBar, NavbarOnResize } from ".";
|
||||
import { NavBar } from ".";
|
||||
|
||||
let alertStore;
|
||||
let settingsStore;
|
||||
@@ -85,18 +85,17 @@ describe("<NavBar />", () => {
|
||||
it("navbar-nav includes 'flex-column' class with 3 filters", () => {
|
||||
ValidateNavClass(3, "flex-column");
|
||||
});
|
||||
});
|
||||
|
||||
describe("NavbarOnResize()", () => {
|
||||
it("body 'padding-top' style is updated after calling NavbarOnResize()", () => {
|
||||
NavbarOnResize(0, 10);
|
||||
const tree = MountedNavbar();
|
||||
tree.instance().onResize(0, 10);
|
||||
expect(
|
||||
window
|
||||
.getComputedStyle(document.body, null)
|
||||
.getPropertyValue("padding-top")
|
||||
).toBe("14px");
|
||||
|
||||
NavbarOnResize(0, 36);
|
||||
tree.instance().onResize(0, 36);
|
||||
expect(
|
||||
window
|
||||
.getComputedStyle(document.body, null)
|
||||
@@ -110,31 +109,42 @@ describe("<IdleTimer />", () => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
it("hides navbar after 4 minutes", () => {
|
||||
it("hides navbar after 5 seconds on mobile", () => {
|
||||
global.window.innerWidth = 500;
|
||||
const tree = MountedNavbar();
|
||||
expect(tree.find(".navbar")).toHaveLength(1);
|
||||
|
||||
jest.runTimersToTime(1000 * 60 * 4);
|
||||
jest.runTimersToTime(1000 * 6);
|
||||
tree.update();
|
||||
expect(tree.find(".navbar")).toHaveLength(0);
|
||||
expect(tree.find(".container").hasClass("visible")).toBe(false);
|
||||
expect(tree.find(".container").hasClass("invisible")).toBe(true);
|
||||
});
|
||||
|
||||
it("hides navbar after 3 minutes on desktop", () => {
|
||||
global.window.innerWidth = 769;
|
||||
const tree = MountedNavbar();
|
||||
jest.runTimersToTime(1000 * 60 * 3 + 1000);
|
||||
tree.update();
|
||||
expect(tree.find(".container").hasClass("visible")).toBe(false);
|
||||
expect(tree.find(".container").hasClass("invisible")).toBe(true);
|
||||
});
|
||||
|
||||
it("hidden navbar shows up again after activity", () => {
|
||||
const tree = MountedNavbar();
|
||||
const instance = tree.instance();
|
||||
|
||||
instance.activityStatus.idle = true;
|
||||
instance.activityStatus.setIdle();
|
||||
jest.runOnlyPendingTimers();
|
||||
tree.update();
|
||||
expect(tree.find(".navbar")).toHaveLength(0);
|
||||
expect(tree.find(".container").hasClass("visible")).toBe(false);
|
||||
expect(tree.find(".container").hasClass("invisible")).toBe(true);
|
||||
|
||||
instance.activityStatus.setActive();
|
||||
jest.runOnlyPendingTimers();
|
||||
tree.update();
|
||||
expect(tree.find(".navbar")).toHaveLength(1);
|
||||
expect(tree.find(".container").hasClass("visible")).toBe(true);
|
||||
expect(tree.find(".container").hasClass("invisible")).toBe(false);
|
||||
});
|
||||
|
||||
it("body padding-top is 4px when navbar is hidden", () => {
|
||||
it("body padding-top is 0px when navbar is hidden", () => {
|
||||
const tree = MountedNavbar();
|
||||
const instance = tree.instance();
|
||||
|
||||
@@ -145,6 +155,6 @@ describe("<IdleTimer />", () => {
|
||||
window
|
||||
.getComputedStyle(document.body, null)
|
||||
.getPropertyValue("padding-top")
|
||||
).toBe("4px");
|
||||
).toBe("0px");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user