Skip to content

Commit

Permalink
Backport PR jupyterlab#497: Add content-visibility hide mode
Browse files Browse the repository at this point in the history
  • Loading branch information
krassowski committed Dec 24, 2022
1 parent 92491a6 commit ad86fd9
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 48 deletions.
19 changes: 11 additions & 8 deletions packages/widgets/src/docklayout.ts
Expand Up @@ -852,18 +852,21 @@ export class DockLayout extends Layout {

// Using transform create an additional layer in the pixel pipeline
// to limit the number of layer, it is set only if there is more than one widget.
if (
this._hiddenMode === Widget.HiddenMode.Scale &&
refNode.tabBar.titles.length > 0
) {
if (refNode.tabBar.titles.length == 1) {
if (this._hiddenMode === Widget.HiddenMode.Scale) {
if (refNode.tabBar.titles.length === 0) {
// Singular tab should use display mode to limit number of layers.
widget.hiddenMode = Widget.HiddenMode.Display;
} else if (refNode.tabBar.titles.length == 1) {
// If we are adding a second tab, switch the existing tab back to scale.
const existingWidget = refNode.tabBar.titles[0].owner;
existingWidget.hiddenMode = Widget.HiddenMode.Scale;
} else {
// For the third and subsequent tabs no special action is needed.
widget.hiddenMode = Widget.HiddenMode.Scale;
}

widget.hiddenMode = Widget.HiddenMode.Scale;
} else {
widget.hiddenMode = Widget.HiddenMode.Display;
// For all other modes just propagate the current mode.
widget.hiddenMode = this._hiddenMode;
}

// Insert the widget's tab relative to the target index.
Expand Down
96 changes: 58 additions & 38 deletions packages/widgets/src/widget.ts
Expand Up @@ -183,30 +183,23 @@ export class Widget implements IMessageHandler, IObservableDisposable {
if (this._hiddenMode === value) {
return;
}
this._hiddenMode = value;
switch (value) {
case Widget.HiddenMode.Display:
this.node.style.willChange = 'auto';
break;
case Widget.HiddenMode.Scale:
this.node.style.willChange = 'transform';
break;

if (this.isHidden) {
// Reset styles set by previous mode.
this._toggleHidden(false);
}

if (value == Widget.HiddenMode.Scale) {
this.node.style.willChange = 'transform';
} else {
this.node.style.willChange = 'auto';
}

this._hiddenMode = value;

if (this.isHidden) {
if (value === Widget.HiddenMode.Display) {
this.addClass('lm-mod-hidden');
/* <DEPRECATED> */
this.addClass('p-mod-hidden');
/* </DEPRECATED> */
this.node.style.transform = '';
} else {
this.node.style.transform = 'scale(0)';
this.removeClass('lm-mod-hidden');
/* <DEPRECATED> */
this.removeClass('p-mod-hidden');
/* </DEPRECATED> */
}
// Set styles for new mode.
this._toggleHidden(true);
}
}

Expand Down Expand Up @@ -434,14 +427,7 @@ export class Widget implements IMessageHandler, IObservableDisposable {
}
this.clearFlag(Widget.Flag.IsHidden);
this.node.removeAttribute('aria-hidden');
if (this.hiddenMode === Widget.HiddenMode.Display) {
this.removeClass('lm-mod-hidden');
/* <DEPRECATED> */
this.removeClass('p-mod-hidden');
/* </DEPRECATED> */
} else {
this.node.style.transform = '';
}
this._toggleHidden(false);

if (this.isAttached && (!this.parent || this.parent.isVisible)) {
MessageLoop.sendMessage(this, Widget.Msg.AfterShow);
Expand Down Expand Up @@ -469,14 +455,7 @@ export class Widget implements IMessageHandler, IObservableDisposable {
}
this.setFlag(Widget.Flag.IsHidden);
this.node.setAttribute('aria-hidden', 'true');
if (this.hiddenMode === Widget.HiddenMode.Display) {
this.addClass('lm-mod-hidden');
/* <DEPRECATED> */
this.addClass('p-mod-hidden');
/* </DEPRECATED> */
} else {
this.node.style.transform = 'scale(0)';
}
this._toggleHidden(true);

if (this.isAttached && (!this.parent || this.parent.isVisible)) {
MessageLoop.sendMessage(this, Widget.Msg.AfterHide);
Expand Down Expand Up @@ -759,6 +738,42 @@ export class Widget implements IMessageHandler, IObservableDisposable {
*/
protected onChildRemoved(msg: Widget.ChildMessage): void {}

private _toggleHidden(hidden: boolean) {
if (hidden) {
switch (this._hiddenMode) {
case Widget.HiddenMode.Display:
this.addClass('lm-mod-hidden');
/* <DEPRECATED> */
this.addClass('p-mod-hidden');
/* </DEPRECATED> */
break;
case Widget.HiddenMode.Scale:
this.node.style.transform = 'scale(0)';
break;
case Widget.HiddenMode.ContentVisibility:
this.node.style.contentVisibility = 'hidden';
this.node.style.zIndex = '-1';
break;
}
} else {
switch (this._hiddenMode) {
case Widget.HiddenMode.Display:
this.removeClass('lm-mod-hidden');
/* <DEPRECATED> */
this.removeClass('p-mod-hidden');
/* </DEPRECATED> */
break;
case Widget.HiddenMode.Scale:
this.node.style.transform = '';
break;
case Widget.HiddenMode.ContentVisibility:
this.node.style.contentVisibility = '';
this.node.style.zIndex = '';
break;
}
}
}

private _flags = 0;
private _layout: Layout | null = null;
private _parent: Widget | null = null;
Expand Down Expand Up @@ -819,7 +834,12 @@ export namespace Widget {
/**
* Hide the widget by setting the `transform` to `'scale(0)'`.
*/
Scale
Scale,

/**
*Hide the widget by setting the `content-visibility` to `'hidden'`.
*/
ContentVisibility
}

/**
Expand Down
32 changes: 30 additions & 2 deletions packages/widgets/tests/src/widget.spec.ts
Expand Up @@ -740,10 +740,38 @@ describe('@lumino/widgets', () => {
widget.dispose();
});

it('should add class when switching from scale to display', () => {
for (const fromMode of [
Widget.HiddenMode.Scale,
Widget.HiddenMode.ContentVisibility
]) {
it(`should add class when switching from ${fromMode} to display`, () => {
let widget = new Widget();
Widget.attach(widget, document.body);
widget.hiddenMode = fromMode;
widget.hide();
widget.hiddenMode = Widget.HiddenMode.Display;
expect(widget.hasClass('lm-mod-hidden')).to.equal(true);
expect(widget.node.style.transform).to.equal('');
expect(widget.node.style.willChange).to.equal('auto');
widget.dispose();
});
}

it('should use content-visibility in relevant mode', () => {
let widget = new Widget();
Widget.attach(widget, document.body);
widget.hiddenMode = Widget.HiddenMode.Scale;
widget.hiddenMode = Widget.HiddenMode.ContentVisibility;
widget.hide();
expect(widget.hasClass('lm-mod-hidden')).to.equal(false);
expect(widget.node.style.contentVisibility).to.equal('hidden');
expect(widget.node.style.willChange).to.equal('auto');
widget.dispose();
});

it('should add class when switching from content-visibility to display', () => {
let widget = new Widget();
Widget.attach(widget, document.body);
widget.hiddenMode = Widget.HiddenMode.ContentVisibility;
widget.hide();
widget.hiddenMode = Widget.HiddenMode.Display;
expect(widget.hasClass('lm-mod-hidden')).to.equal(true);
Expand Down
1 change: 1 addition & 0 deletions review/api/widgets.api.md
Expand Up @@ -1267,6 +1267,7 @@ export namespace Widget {
IsVisible = 8
}
export enum HiddenMode {
ContentVisibility = 2,
Display = 0,
Scale = 1
}
Expand Down

0 comments on commit ad86fd9

Please sign in to comment.