diff --git a/packages/launcher/src/index.tsx b/packages/launcher/src/index.tsx index c3a71cacad49..bae9d87266b8 100644 --- a/packages/launcher/src/index.tsx +++ b/packages/launcher/src/index.tsx @@ -187,6 +187,9 @@ export class Launcher extends VDomRenderer { } } + // The tabindex of cards in each category are separated by 100. + let tabIndexStep = 100; + // Now create the sections for each category orderedCategories.forEach(cat => { const item = categories[cat][0] as ILauncher.IItemOptions; @@ -205,20 +208,25 @@ export class Launcher extends VDomRenderer {
{toArray( - map(categories[cat], (item: ILauncher.IItemOptions) => { - return Card( - kernel, - item, - this, - this._commands, - this._callback - ); - }) + map( + categories[cat], + (item: ILauncher.IItemOptions, tabindex: number) => { + return Card( + kernel, + item, + tabIndexStep + tabindex + 1, + this, + this._commands, + this._callback + ); + } + ) )}
); sections.push(section); + tabIndexStep += 100; } }); @@ -340,6 +348,7 @@ export namespace ILauncher { function Card( kernel: boolean, item: ILauncher.IItemOptions, + tabindex: number, launcher: Launcher, commands: CommandRegistry, launcherCallback: (widget: Widget) => void @@ -349,7 +358,7 @@ function Card( const args = { ...item.args, cwd: launcher.cwd }; const caption = commands.caption(command, args); const label = commands.label(command, args); - const title = caption || label; + const title = kernel ? label : caption || label; // Build the onclick handler. let onclick = () => { @@ -377,12 +386,22 @@ function Card( }); }; + // With tabindex working, you can now pick a kernel by tabbing around and + // pressing Enter. + let onkeypress = (event: React.KeyboardEvent) => { + if (event.key === 'Enter') { + onclick(); + } + }; + // Return the VDOM element. return (
@@ -402,7 +421,7 @@ function Card( )}
- {label} +

{label}

); diff --git a/packages/launcher/style/index.css b/packages/launcher/style/index.css index fdf880ca7dba..d9708e315d83 100644 --- a/packages/launcher/style/index.css +++ b/packages/launcher/style/index.css @@ -9,8 +9,8 @@ --jp-private-launcher-top-padding: 16px; --jp-private-launcher-side-padding: 32px; --jp-private-launcher-card-size: 100px; - --jp-private-launcher-card-label-height: 25px; - --jp-private-launcher-card-icon-height: 75px; + --jp-private-launcher-card-label-height: 32px; + --jp-private-launcher-card-icon-height: 68px; --jp-private-launcher-large-icon-size: 52px; --jp-private-launcher-small-icon-size: 32px; } @@ -117,10 +117,19 @@ border-radius: var(--jp-border-radius); } +.jp-LauncherCard:focus:not(:active) { + border: 1px solid var(--jp-brand-color1); + box-shadow: var(--jp-elevation-z6); +} + .jp-LauncherCard:hover { box-shadow: var(--jp-elevation-z6); } +.jp-LauncherCard:active { + box-shadow: var(--jp-elevation-z4); +} + .jp-LauncherCard-icon { width: 100%; height: var(--jp-private-launcher-card-icon-height); @@ -150,15 +159,19 @@ .jp-LauncherCard-label { width: 100%; height: var(--jp-private-launcher-card-label-height); - line-height: var(--jp-private-launcher-card-label-height); - font-size: var(--jp-ui-font-size1); - padding: 0 8px; - color: var(--jp-ui-font-color1); + padding: 0 4px 4px 4px; box-sizing: border-box; overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; +} + +.jp-LauncherCard-label p { + height: 28px; + word-break: break-word; text-align: center; + color: var(--jp-ui-font-color1); + line-height: 14px; + font-size: 12px; + overflow: hidden; } /* Icons, kernel icons */