Skip to content

Commit

Permalink
Added pressed state, aria atts to toolbar button
Browse files Browse the repository at this point in the history
  • Loading branch information
Piyush Jain committed Aug 4, 2021
1 parent f4c32ea commit 2cd5090
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 13 deletions.
45 changes: 41 additions & 4 deletions packages/apputils/src/toolbar.tsx
Expand Up @@ -590,6 +590,11 @@ export namespace ToolbarButtonComponent {
tooltip?: string;
onClick?: () => void;
enabled?: boolean;
ariaLabel?: string;
pressed?: boolean;
pressedIcon?: LabIcon.IMaybeResolvable;
pressedIconClass?: string;
pressedTooltip?: string;

/**
* Trigger the button on the actual onClick event rather than onMouseDown.
Expand Down Expand Up @@ -637,28 +642,46 @@ export function ToolbarButtonComponent(props: ToolbarButtonComponent.IProps) {
}
};

const getTooltip = () => {
if (props.pressed && props.pressedTooltip) {
return props.pressedTooltip;
} else {
return props.tooltip || props.iconLabel;
}
};

const getIconClass = () => {
if (props.pressed && props.pressedIconClass) {
return props.pressedIconClass;
} else {
return props.iconClass;
}
};

return (
<Button
className={
props.className
? props.className + ' jp-ToolbarButtonComponent'
: 'jp-ToolbarButtonComponent'
}
aria-label={props.ariaLabel || ''}
aria-pressed={props.pressed}
disabled={props.enabled === false}
onClick={props.actualOnClick ?? false ? handleClick : undefined}
onMouseDown={
!(props.actualOnClick ?? false) ? handleMouseDown : undefined
}
onKeyDown={handleKeyDown}
title={props.tooltip || props.iconLabel}
title={getTooltip()}
minimal
>
{(props.icon || props.iconClass) && (
<LabIcon.resolveReact
icon={props.icon}
icon={props.pressed ? props.pressedIcon : props.icon}
iconClass={
// add some extra classes for proper support of icons-as-css-background
classes(props.iconClass, 'jp-Icon')
classes(getIconClass(), 'jp-Icon')
}
className="jp-ToolbarButtonComponent-icon"
tag="span"
Expand Down Expand Up @@ -693,9 +716,23 @@ export class ToolbarButton extends ReactWidget {
super();
addToolbarButtonClass(this);
}

set pressed(value: boolean) {
if (value != this._pressed) {
this._pressed = value;
this.update();
}
}

get pressed() {
return this._pressed;
}

render() {
return <ToolbarButtonComponent {...this.props} />;
return <ToolbarButtonComponent {...this.props} pressed={this._pressed} />;
}

private _pressed = false;
}

/**
Expand Down
45 changes: 45 additions & 0 deletions packages/apputils/test/toolbar.spec.ts
Expand Up @@ -17,6 +17,7 @@ import { CommandRegistry } from '@lumino/commands';
import { ReadonlyPartialJSONObject } from '@lumino/coreutils';
import { Widget } from '@lumino/widgets';
import { simulate } from 'simulate-event';
import { bugDotIcon, bugIcon } from '@jupyterlab/ui-components';

const server = new JupyterServer();

Expand Down Expand Up @@ -437,6 +438,22 @@ describe('@jupyterlab/apputils', () => {
});
});

it('should accept aria label', async () => {
const widget = new ToolbarButton({
className: 'foo',
iconClass: 'iconFoo',
onClick: () => {
return void 0;
},
tooltip: 'bar',
ariaLabel: 'button'
});
Widget.attach(widget, document.body);
await framePromise();
const button = widget.node.firstChild as HTMLElement;
expect(button.getAttribute('aria-label')).toBe('button');
});

describe('#dispose()', () => {
it('should dispose of the resources used by the widget', () => {
const button = new ToolbarButton();
Expand Down Expand Up @@ -502,6 +519,34 @@ describe('@jupyterlab/apputils', () => {
});
});

describe('#pressed()', () => {
it('should update the pressed state', async () => {
const widget = new ToolbarButton({
icon: bugIcon,
tooltip: 'tooltip',
pressedTooltip: 'pressed tooltip',
pressedIcon: bugDotIcon
});
Widget.attach(widget, document.body);
await framePromise();
const button = widget.node.firstChild as HTMLElement;
expect(widget.pressed).toBe(false);
expect(button.title).toBe('tooltip');
expect(button.getAttribute('aria-pressed')).toEqual('false');
let icon = button.querySelectorAll('svg');
expect(icon[0].getAttribute('data-icon')).toEqual('ui-components:bug');
widget.pressed = true;
await framePromise();
expect(widget.pressed).toBe(true);
expect(button.title).toBe('pressed tooltip');
expect(button.getAttribute('aria-pressed')).toEqual('true');
icon = button.querySelectorAll('svg');
expect(icon[0].getAttribute('data-icon')).toEqual(
'ui-components:bug-dot'
);
});
});

// describe('#onAfterAttach()', () => {
// it('should add event listeners to the node', () => {
// const button = new LogToolbarButton();
Expand Down
14 changes: 6 additions & 8 deletions packages/debugger/src/handler.ts
Expand Up @@ -23,7 +23,7 @@ import { Kernel, KernelMessage, Session } from '@jupyterlab/services';

import { ITranslator, nullTranslator } from '@jupyterlab/translation';

import { bugIcon } from '@jupyterlab/ui-components';
import { bugDotIcon, bugIcon } from '@jupyterlab/ui-components';

import { Debugger } from './debugger';

Expand Down Expand Up @@ -51,7 +51,10 @@ function updateIconButton(
const icon = new ToolbarButton({
className: 'jp-DebuggerBugButton',
icon: bugIcon,
tooltip: trans.__('Enable / Disable Debugger'),
tooltip: trans.__('Enable Debugger'),
ariaLabel: trans.__('Enable/Disable Debugger'),
pressedIcon: bugDotIcon,
pressedTooltip: trans.__('Disable Debugger'),
onClick
});
widget.toolbar.insertBefore('kernelName', 'debugger-icon', icon);
Expand All @@ -67,12 +70,7 @@ function updateIconButton(
* @param on true if switched on, false otherwise
*/
function updateIconButtonState(widget: ToolbarButton, on: boolean) {
const cls = 'jp-debug-button-on';
if (on) {
widget.addClass(cls);
} else {
widget.removeClass(cls);
}
widget.pressed = on;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/debugger/style/base.css
Expand Up @@ -20,6 +20,6 @@
margin-right: 0px;
}

.jp-debug-button-on .jp-DebuggerBugButton .jp-icon3[fill] {
.jp-DebuggerBugButton[aria-pressed='true'] path {
fill: var(--jp-warn-color0);
}
2 changes: 2 additions & 0 deletions packages/ui-components/src/icon/iconimports.ts
Expand Up @@ -9,6 +9,7 @@ import { LabIcon } from './labicon';

// icon svg import statements
import addSvgstr from '../../style/icons/toolbar/add.svg';
import bugDotSvgstr from '../../style/icons/toolbar/bug-dot.svg';
import bugSvgstr from '../../style/icons/toolbar/bug.svg';
import buildSvgstr from '../../style/icons/sidebar/build.svg';
import caretDownEmptySvgstr from '../../style/icons/arrow/caret-down-empty.svg';
Expand Down Expand Up @@ -89,6 +90,7 @@ import yamlSvgstr from '../../style/icons/filetype/yaml.svg';

// LabIcon instance construction
export const addIcon = new LabIcon({ name: 'ui-components:add', svgstr: addSvgstr });
export const bugDotIcon = new LabIcon({ name: 'ui-components:bug-dot', svgstr: bugDotSvgstr });
export const bugIcon = new LabIcon({ name: 'ui-components:bug', svgstr: bugSvgstr });
export const buildIcon = new LabIcon({ name: 'ui-components:build', svgstr: buildSvgstr });
export const caretDownEmptyIcon = new LabIcon({ name: 'ui-components:caret-down-empty', svgstr: caretDownEmptySvgstr });
Expand Down
4 changes: 4 additions & 0 deletions packages/ui-components/style/deprecated.css
Expand Up @@ -13,6 +13,7 @@

:root {
--jp-icon-add: url('icons/toolbar/add.svg');
--jp-icon-bug-dot: url('icons/toolbar/bug-dot.svg');
--jp-icon-bug: url('icons/toolbar/bug.svg');
--jp-icon-build: url('icons/sidebar/build.svg');
--jp-icon-caret-down-empty-thin: url('icons/arrow/caret-down-empty-thin.svg');
Expand Down Expand Up @@ -97,6 +98,9 @@
.jp-AddIcon {
background-image: var(--jp-icon-add);
}
.jp-BugDotIcon {
background-image: var(--jp-icon-bug-dot);
}
.jp-BugIcon {
background-image: var(--jp-icon-bug);
}
Expand Down
6 changes: 6 additions & 0 deletions packages/ui-components/style/icons/toolbar/bug-dot.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2cd5090

Please sign in to comment.