Skip to content
This repository was archived by the owner on Jul 30, 2025. It is now read-only.

Commit 6e94df5

Browse files
committed
feat: escape to toggle Sidebar visibility
Also cleans up sidebar scss, consolidating into web/scss/components/Sidebar
1 parent 51fb118 commit 6e94df5

File tree

10 files changed

+216
-155
lines changed

10 files changed

+216
-155
lines changed

plugins/plugin-bash-like/src/pty/client.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,11 @@ export const doExec = (
855855
xtermContainer = document.createElement('xterm')
856856
xtermContainer.classList.add('xterm-container')
857857

858+
// swallow escape key presses against the xterm container,
859+
// e.g. we don't want hitting escape in vi to propagate to
860+
// other kui elements
861+
xtermContainer.onkeyup = evt => evt.key === 'Escape' && evt.stopPropagation()
862+
858863
if (execOptions.replSilence) {
859864
debug('repl silence')
860865
xtermContainer.style.display = 'none'

plugins/plugin-client-common/src/components/Client/Sidebar.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,31 @@
1515
*/
1616

1717
import React from 'react'
18-
import { encodeComponent, pexecInCurrentTab } from '@kui-shell/core'
18+
import { encodeComponent, i18n, pexecInCurrentTab } from '@kui-shell/core'
1919
import { PageSidebar } from '@patternfly/react-core'
2020

2121
import BrandingProps from './props/Branding'
2222
import GuidebookProps, { isGuidebook, isMenu, MenuItem } from './props/Guidebooks'
2323

24+
import '../../../web/scss/components/Sidebar/_index.scss'
25+
2426
const Nav = React.lazy(() => import('@patternfly/react-core').then(_ => ({ default: _.Nav })))
2527
const NavItem = React.lazy(() => import('@patternfly/react-core').then(_ => ({ default: _.NavItem })))
2628
const NavList = React.lazy(() => import('@patternfly/react-core').then(_ => ({ default: _.NavList })))
2729
const NavExpandable = React.lazy(() => import('@patternfly/react-core').then(_ => ({ default: _.NavExpandable })))
2830

31+
const strings = i18n('plugin-client-common')
32+
2933
type Props = BrandingProps &
3034
GuidebookProps & {
3135
/** unfurled? */
3236
isOpen: boolean
3337

3438
/** visually indicate which nav item is active? */
3539
indicateActiveItem?: boolean
40+
41+
/** toggle open state */
42+
toggleOpen(): void
3643
}
3744

3845
interface State {
@@ -41,6 +48,8 @@ interface State {
4148
}
4249

4350
export default class Sidebar extends React.PureComponent<Props, State> {
51+
private readonly cleaners: (() => void)[] = []
52+
4453
public constructor(props: Props) {
4554
super(props)
4655
this.state = {}
@@ -50,6 +59,21 @@ export default class Sidebar extends React.PureComponent<Props, State> {
5059
return this.state.currentGuidebook
5160
}
5261

62+
private readonly onKeyup = (evt: KeyboardEvent) => {
63+
if (evt.key === 'Escape') {
64+
this.props.toggleOpen()
65+
}
66+
}
67+
68+
public componentDidMount() {
69+
document.addEventListener('keyup', this.onKeyup)
70+
this.cleaners.push(() => document.removeEventListener('keyup', this.onKeyup))
71+
}
72+
73+
public componentWillUnmount() {
74+
this.cleaners.forEach(_ => _())
75+
}
76+
5377
private nav() {
5478
// helps deal with isActive; if we don't have a currentGuidebook,
5579
// use the first one (for now)
@@ -89,8 +113,9 @@ export default class Sidebar extends React.PureComponent<Props, State> {
89113
<NavList>{this.props.guidebooks.map(renderItem)}</NavList>
90114
</Nav>
91115
{this.props.productName && this.props.version && (
92-
<div className="flex-align-end semi-bold kui--tab-container-sidebar-other">
93-
{this.props.productName} v{this.props.version}
116+
<div className="kui--tab-container-sidebar-other flex-layout">
117+
<span className="flex-fill sub-text">{strings('Toggle via <Esc>')}</span>
118+
<span className="inline-flex flex-align-end semi-bold">v{this.props.version}</span>
94119
</div>
95120
)}
96121
</React.Suspense>

plugins/plugin-client-common/src/components/Client/TabContainer.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,13 @@ export default class TabContainer extends React.PureComponent<Props, State> {
348348
private sidebar() {
349349
return (
350350
<Sidebar
351-
isOpen={this.state.isSidebarOpen}
352351
version={this.props.version}
353-
productName={this.props.productName}
352+
isOpen={this.state.isSidebarOpen}
353+
toggleOpen={this.toggleSidebar}
354354
guidebooks={this.props.guidebooks}
355-
guidebooksCommand={this.props.guidebooksCommand}
355+
productName={this.props.productName}
356356
indicateActiveItem={!!this.props.noTopTabs}
357+
guidebooksCommand={this.props.guidebooksCommand}
357358
/>
358359
)
359360
}

plugins/plugin-client-common/src/components/Content/Editor/SimpleEditor.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,14 @@ export default class SimpleEditor extends React.Component<Props, State> {
136136

137137
// ibid, but for Escape -> onCancel
138138
if (onCancel) {
139-
editor.addCommand(KeyCode.Escape, () => {
140-
onCancel(editor.getValue())
139+
editor.onKeyUp(evt => {
140+
if (evt.browserEvent.key === 'Escape') {
141+
// swallow the event, so other kui components don't also respond
142+
evt.browserEvent.stopPropagation()
143+
144+
// notify the enclosing component that we have cancelled editing
145+
onCancel(editor.getValue())
146+
}
141147
})
142148
}
143149
}

plugins/plugin-client-common/web/css/static/ui.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,9 @@ code.fancy-code.hljs {
297297
display: flex;
298298
justify-content: flex-end;
299299
}
300+
.inline-flex {
301+
display: inline-flex;
302+
}
300303
.flex-align-start {
301304
justify-content: flex-start;
302305
}

plugins/plugin-client-common/web/scss/components/Sidebar/_index.scss

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2021 The Kubernetes Authors
2+
* Copyright 2022 The Kubernetes Authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -13,3 +13,81 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
17+
@import 'mixins';
18+
@import '../TopTabStripe/mixins';
19+
20+
body[kui-theme-style='light'] {
21+
@include Sidebar {
22+
--kui--sidebar-color-01: var(--color-base00);
23+
--kui--sidebar-color-02: var(--color-base02);
24+
}
25+
@include TopTabStripe {
26+
@include SidebarToggleButton {
27+
--kui--sidebar-toggle-button-color: var(--color-text-02);
28+
}
29+
}
30+
}
31+
32+
@include TopTabStripe {
33+
@include Sidebar {
34+
--kui--sidebar-color-01: var(--color-text-01);
35+
--kui--sidebar-color-02: var(--color-text-02);
36+
37+
display: flex;
38+
flex-direction: column;
39+
}
40+
@include SidebarBody {
41+
flex: 1;
42+
display: flex;
43+
flex-direction: column;
44+
}
45+
@include SidebarNav {
46+
flex: 1;
47+
}
48+
@include SidebarBottomAlignedContent {
49+
padding: 0 var(--pf-global--spacer--lg);
50+
}
51+
52+
@include SidebarNavMenuButton {
53+
color: var(--kui--sidebar-color-01);
54+
}
55+
56+
@include SidebarNavMenu {
57+
@include SidebarNavItem {
58+
color: var(--kui--sidebar-color-02);
59+
}
60+
}
61+
@include SidebarNavItem {
62+
color: var(--kui--sidebar-color-01);
63+
64+
a:hover {
65+
cursor: pointer;
66+
}
67+
}
68+
@include SidebarToggleButton {
69+
--kui--sidebar-toggle-button-color: var(--kui--sidebar-color-02);
70+
font-size: 1.25em;
71+
}
72+
@include SidebarToggleIcon {
73+
color: var(--kui--sidebar-toggle-button-color);
74+
}
75+
}
76+
77+
/* Sidebar width */
78+
@include Sidebar {
79+
max-width: 15rem;
80+
}
81+
82+
/* Coloring of bottom-aligned text */
83+
@include Sidebar {
84+
@include SidebarBottomAlignedContent {
85+
.sub-text {
86+
opacity: 0.8;
87+
color: var(--kui--sidebar-color-02);
88+
}
89+
.semi-bold {
90+
color: var(--kui--sidebar-color-01);
91+
}
92+
}
93+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2022 The Kubernetes Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
@mixin SidebarToggleButton {
18+
button.kui--top-tab-stripe-header--toggle-button {
19+
@content;
20+
}
21+
}
22+
23+
@mixin SidebarToggleIcon {
24+
.kui--top-tab-stripe-header--toggle-button-icon {
25+
@content;
26+
}
27+
}
28+
29+
@mixin Sidebar {
30+
.kui--tab-container-sidebar {
31+
@content;
32+
}
33+
}
34+
35+
@mixin SidebarBody {
36+
.pf-c-page__sidebar-body {
37+
@content;
38+
}
39+
}
40+
41+
@mixin SidebarNav {
42+
.kui--tab-container-sidebar-nav {
43+
@content;
44+
}
45+
}
46+
47+
@mixin SidebarNavItem {
48+
.kui--sidebar-nav-item {
49+
@content;
50+
}
51+
}
52+
53+
@mixin SidebarNavMenu {
54+
.kui--sidebar-nav-menu {
55+
@content;
56+
}
57+
}
58+
59+
@mixin SidebarNavMenuButton {
60+
@include SidebarNavMenu {
61+
& > button {
62+
@content;
63+
}
64+
}
65+
}
66+
67+
@mixin SidebarBottomAlignedContent {
68+
.kui--tab-container-sidebar-other {
69+
@content;
70+
}
71+
}

plugins/plugin-client-common/web/scss/components/TopTabStripe/Sidebar.scss

Lines changed: 0 additions & 89 deletions
This file was deleted.

0 commit comments

Comments
 (0)