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

Commit 708570c

Browse files
committed
feat: allow controllers to control the color of the status stripe
Fixes #5490
1 parent 903fc62 commit 708570c

File tree

11 files changed

+204
-35
lines changed

11 files changed

+204
-35
lines changed

packages/core/src/core/events.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ eventChannelUnsafe.setMaxListeners(100)
3636

3737
export default eventChannelUnsafe
3838

39+
export type StatusStripeChangeEvent = {
40+
type: 'default' | 'blue' | 'yellow' | 'red'
41+
message?: string
42+
}
43+
3944
export type TabLayoutChangeEvent = { isSidecarNowHidden: boolean }
4045
type TabLayoutChangeHandler = (evt: TabLayoutChangeEvent) => void
4146

@@ -115,6 +120,11 @@ class WriteEventBus extends EventBusBase {
115120
this.eventBus.emit('/snapshot/request', cb)
116121
}
117122

123+
/** Request a status stripe change */
124+
public emitStatusStripeChangeRequest(evt: StatusStripeChangeEvent): void {
125+
this.eventBus.emit('/status-stripe/change', evt)
126+
}
127+
118128
public emitWithTabId(channel: '/tab/offline' | '/tab/close/request', tabId: string, tab?: Tab): void {
119129
this.eventBus.emit(`${channel}/${tabId}`, tabId, tab)
120130
}
@@ -151,6 +161,16 @@ class ReadEventBus extends WriteEventBus {
151161
this.eventBus.off('/snapshot', listener)
152162
}
153163

164+
/** Request a status stripe change */
165+
public onStatusStripeChangeRequest(listener: (evt: StatusStripeChangeEvent) => void): void {
166+
this.eventBus.on('/status-stripe/change', listener)
167+
}
168+
169+
/** Request a status stripe change */
170+
public offStatusStripeChangeRequest(listener: (evt: StatusStripeChangeEvent) => void): void {
171+
this.eventBus.off('/status-stripe/change', listener)
172+
}
173+
154174
/** User switching focus from one Split to another, within one Tab */
155175
public onSplitSwitch(listener: (tab?: Tab | number) => void): void {
156176
this.eventBus.on('/tab/switch/split', listener)

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export {
7676
wireToTabEvents,
7777
wireToStandardEvents,
7878
eventBus,
79+
StatusStripeChangeEvent,
7980
TabLayoutChangeEvent
8081
} from './core/events'
8182

packages/core/src/repl/events.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,7 @@ export type SnapshotWindow = {
8383
*
8484
*/
8585
export type Snapshot = {
86+
title?: string
87+
description?: string
8688
windows: SnapshotWindow[]
8789
}

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ import {
3535
import Card from '../spi/Card'
3636
import KuiContext from './context'
3737
import KuiConfiguration from './KuiConfiguration'
38-
import { ComboSidecar, InputStripe, StatusStripe, TabContainer, Loading, Alert } from '../..'
38+
import StatusStripe, { Props as StatusStripeProps } from './StatusStripe'
39+
import { ComboSidecar, InputStripe, TabContainer, Loading, Alert } from '../..'
3940

4041
import KuiIcon from '../../../icons/png/WelcomeLight.png'
4142

@@ -204,6 +205,25 @@ export class Kui extends React.PureComponent<Props, State> {
204205
})
205206
}
206207

208+
/**
209+
* Props to pass to StatusStripe. This allows us to set the desired
210+
* status stripe color at startup time, rather than seeing the
211+
* default color, followed quickly by a change to the color desired
212+
* by the controller backing the given `props.commandLine`. The
213+
* controller may still want to specialize the status stripe
214+
* further, but at least we can avoid that odd
215+
* e.g. defaultColor-then-blue effect.
216+
*
217+
*/
218+
private statusStripeProps(): StatusStripeProps {
219+
if (this.props.commandLine) {
220+
const statusStripeIdx = this.props.commandLine.findIndex(_ => _ === '--status-stripe')
221+
if (statusStripeIdx >= 0) {
222+
return { type: this.props.commandLine[statusStripeIdx + 1] as StatusStripeProps['type'] }
223+
}
224+
}
225+
}
226+
207227
public componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
208228
console.error(error, errorInfo)
209229
}
@@ -242,7 +262,7 @@ export class Kui extends React.PureComponent<Props, State> {
242262
<ComboSidecar />
243263
</TabContainer>
244264
{this.props.toplevel}
245-
<StatusStripe>{this.props.children}</StatusStripe>
265+
<StatusStripe {...this.statusStripeProps()}>{this.props.children}</StatusStripe>
246266
</div>
247267
</KuiContext.Provider>
248268
)

plugins/plugin-client-common/src/components/Client/StatusStripe/index.tsx

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,30 @@
1818
/* eslint-disable react/prop-types */
1919

2020
import * as React from 'react'
21-
import { pexecInCurrentTab, i18n } from '@kui-shell/core'
21+
import { eventBus, pexecInCurrentTab, i18n, StatusStripeChangeEvent } from '@kui-shell/core'
2222

2323
import Icons from '../../spi/Icons'
24+
import Markdown from '../../Content/Markdown'
25+
import '../../../../web/scss/components/StatusStripe/StatusStripe.scss'
2426

2527
const strings = i18n('plugin-client-common')
2628

27-
export default class StatusStripe extends React.PureComponent {
29+
type State = StatusStripeChangeEvent
30+
export type Props = Partial<State>
31+
32+
export default class StatusStripe extends React.PureComponent<Props, State> {
33+
public constructor(props: Props) {
34+
super(props)
35+
eventBus.onStatusStripeChangeRequest(this.onChangeRequest.bind(this))
36+
37+
this.state = Object.assign({ type: 'default' }, props)
38+
}
39+
40+
/** Status Stripe change request */
41+
private onChangeRequest(evt: StatusStripeChangeEvent) {
42+
this.setState(evt)
43+
}
44+
2845
/**
2946
* User has clicked on the Settings icon.
3047
*
@@ -43,20 +60,41 @@ export default class StatusStripe extends React.PureComponent {
4360
}
4461

4562
/**
46-
* Render any widgets specified by the client.
63+
* Render the current State.message, if any
64+
*
65+
*/
66+
private message() {
67+
if (this.state.message) {
68+
return (
69+
<div className="kui--status-stripe-element left-pad">
70+
<Markdown source={this.state.message} />
71+
</div>
72+
)
73+
}
74+
}
75+
76+
/**
77+
* Render any widgets specified by the client. Note how we don't
78+
* show widgets if we were given a message. See
79+
* https://github.com/IBM/kui/issues/5490
4780
*
4881
*/
4982
private widgets() {
50-
if (React.Children.count(this.props.children) === 0) {
83+
if (this.state.type !== 'default' || React.Children.count(this.props.children) === 0) {
5184
return this.filler()
5285
} else {
5386
return this.props.children
5487
}
5588
}
5689

90+
private className() {
91+
return 'kui--status-stripe' + (this.state.type === 'default' ? ' kui--inverted-color-context' : '')
92+
}
93+
5794
public render() {
5895
return (
59-
<div className="kui--status-stripe kui--inverted-color-context zoomable" id="kui--status-stripe">
96+
<div className={this.className()} id="kui--status-stripe" data-type={this.state.type}>
97+
{this.message()}
6098
{this.widgets()}
6199

62100
<div className="kui--status-stripe-button">

plugins/plugin-client-common/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import '../web/css/static/carbon-overrides-common.css'
2323
import '../web/css/static/inverted-colors.css'
2424
import '../web/css/static/ui.css'
2525
import '../web/css/static/repl.scss'
26-
import '../web/css/static/status-stripe.css'
2726

2827
// default client
2928
export { default as Kui, Props as KuiProps } from './components/Client/Kui'

plugins/plugin-client-common/web/css/static/status-stripe.css renamed to plugins/plugin-client-common/web/scss/components/StatusStripe/StatusStripe.scss

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,56 @@
1+
/*
2+
* Copyright 2020 IBM Corporation
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+
117
$font-size: 0.75rem;
218

19+
/** StatusStripeChangeEvent.type */
20+
$fg-type-default: var(--color-text-01);
21+
$bg-type-default: var(--color-sidecar-header);
22+
23+
$fg-type-blue: var(--color-base00);
24+
$bg-type-blue: var(--color-brand-03);
25+
26+
$bg-type-yellow: var(--color-yellow);
27+
$bg-type-red: var(--color-red);
28+
329
.kui--status-stripe {
430
display: flex;
531
flex-basis: 2.25rem;
6-
background-color: var(--color-sidecar-header);
7-
color: var(--color-text-01);
32+
background-color: $bg-type-default;
33+
color: $fg-type-default;
34+
35+
&[data-type='blue'] {
36+
color: $fg-type-blue;
37+
background-color: $bg-type-blue;
38+
}
39+
&[data-type='yellow'] {
40+
background-color: $bg-type-yellow;
41+
}
42+
&[data-type='red'] {
43+
background-color: $bg-type-red;
44+
}
45+
46+
/* markdown */
47+
p {
48+
letter-spacing: 0.16px;
49+
code {
50+
font-family: var(--font-sans-serif);
51+
color: var(--color-base01);
52+
}
53+
}
854

955
z-index: 10;
1056
box-shadow: 0 -1px 1px var(--color-base05);
@@ -22,16 +68,16 @@ $font-size: 0.75rem;
2268
.kui--status-stripe-element svg {
2369
fill: currentColor;
2470
}
25-
.kui--status-stripe-element[data-view="obscured"] {
71+
.kui--status-stripe-element[data-view='obscured'] {
2672
color: var(--color-text-02);
2773
}
28-
.kui--status-stripe-element[data-view="obscured"] svg {
74+
.kui--status-stripe-element[data-view='obscured'] svg {
2975
fill: var(--color-text-02);
3076
}
31-
.kui--status-stripe-element[data-view="ok"] svg {
77+
.kui--status-stripe-element[data-view='ok'] svg {
3278
fill: var(--color-green);
3379
}
34-
.kui--status-stripe-element:not(.kui--status-stripe-tag-element)[data-view="warn"] {
80+
.kui--status-stripe-element:not(.kui--status-stripe-tag-element)[data-view='warn'] {
3581
filter: grayscale(0.15) brightness(0.9);
3682

3783
&,
@@ -43,10 +89,10 @@ $font-size: 0.75rem;
4389
filter: none;
4490
}
4591
}
46-
.kui--status-stripe-element[data-view="error"] svg {
92+
.kui--status-stripe-element[data-view='error'] svg {
4793
fill: var(--color-error);
4894
}
49-
.kui--status-stripe-element[data-view="hidden"] {
95+
.kui--status-stripe-element[data-view='hidden'] {
5096
display: none;
5197
}
5298

0 commit comments

Comments
 (0)