Skip to content

Commit 7b3d237

Browse files
committed
wip: some more styles
1 parent 1fc550e commit 7b3d237

34 files changed

+367
-178
lines changed

packages/webui/src/client/lib/Components/DropdownInput.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useCallback, useMemo } from 'react'
22
import ClassNames from 'classnames'
3+
import Form from 'react-bootstrap/esm/Form'
34

45
export interface DropdownInputOption<TValue> {
56
value: TValue
@@ -126,8 +127,8 @@ export function DropdownInputControl<TValue>({
126127

127128
return (
128129
<div className="select focusable">
129-
<select
130-
className={ClassNames('form-control', classNames, {
130+
<Form.Select
131+
className={ClassNames(classNames, {
131132
'option-missing': currentOptionMissing,
132133
})}
133134
value={value + ''}
@@ -149,7 +150,7 @@ export function DropdownInputControl<TValue>({
149150
</option>
150151
)
151152
)}
152-
</select>
153+
</Form.Select>
153154
</div>
154155
)
155156
}

packages/webui/src/client/lib/Components/LabelAndOverrides.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ export function LabelAndOverrides<T extends object, TValue = any>({
6161
} else if (defaultValue === true) {
6262
displayValue = 'true'
6363
} else if (!defaultValue) {
64-
displayValue = '""'
64+
displayValue = ''
6565
} else if (Array.isArray(defaultValue) || typeof defaultValue === 'object') {
6666
displayValue = JSON.stringify(defaultValue) || ''
6767
} else {
6868
// Display it as a string
69-
displayValue = `"${defaultValue}"`
69+
displayValue = `${defaultValue}`
7070
}
7171
}
7272

packages/webui/src/client/lib/SplitDropdown.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import React, { useState, ReactNode, useCallback } from 'react'
22
import ClassNames from 'classnames'
33

4-
import { faChevronUp } from '@fortawesome/free-solid-svg-icons'
5-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
6-
74
interface IProps {
85
selectedKey: string
96
className?: string
@@ -46,7 +43,7 @@ export function SplitDropdown(props: Readonly<IProps>): JSX.Element {
4643
>
4744
<div className="expco-title focusable-main">{getSelected()}</div>
4845
<div className="action-btn right expco-expand subtle" onClick={toggleExpco}>
49-
<FontAwesomeIcon icon={faChevronUp} />
46+
&nbsp;
5047
</div>
5148
<div className="expco-body bd">
5249
{props.options?.map((child, index) => (

packages/webui/src/client/lib/colorPicker.tsx

Lines changed: 124 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import * as React from 'react'
22
import * as _ from 'underscore'
33
import ClassNames from 'classnames'
4-
5-
import { faChevronUp } from '@fortawesome/free-solid-svg-icons'
6-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
4+
import { Manager, Popper, Reference } from 'react-popper'
75

86
export interface ColorPickerEvent {
97
selectedValue: string
@@ -36,6 +34,7 @@ interface IProps {
3634
placeholder?: string
3735
className?: string
3836
value?: string
37+
disabled?: boolean
3938
onChange?: (event: ColorPickerEvent) => void
4039
}
4140

@@ -45,6 +44,9 @@ interface IState {
4544
}
4645

4746
export class ColorPicker extends React.Component<IProps, IState> {
47+
private _popperRef: HTMLElement | null = null
48+
private _popperUpdate: (() => Promise<any>) | undefined
49+
4850
constructor(props: IProps) {
4951
super(props)
5052

@@ -58,10 +60,14 @@ export class ColorPicker extends React.Component<IProps, IState> {
5860
this.refreshChecked()
5961
}
6062

61-
componentDidUpdate(prevProps: IProps): void {
63+
async componentDidUpdate(prevProps: IProps): Promise<void> {
6264
if (this.props.value !== prevProps.value) {
6365
this.refreshChecked()
6466
}
67+
68+
if (this.state.expanded && typeof this._popperUpdate === 'function') {
69+
await this._popperUpdate()
70+
}
6571
}
6672

6773
private refreshChecked() {
@@ -79,51 +85,135 @@ export class ColorPicker extends React.Component<IProps, IState> {
7985
private handleChange = (value: string) => {
8086
this.setState({
8187
selectedValue: value,
88+
expanded: false,
8289
})
8390

8491
if (this.props.onChange && typeof this.props.onChange === 'function') {
8592
this.props.onChange({ selectedValue: value })
8693
}
87-
this.toggleExpco()
8894
}
8995

90-
private toggleExpco = () => {
96+
private toggleExpco = async (e: React.MouseEvent<HTMLElement>) => {
97+
e.preventDefault()
98+
e.stopPropagation()
99+
100+
if (this.props.disabled) return
101+
102+
if (typeof this._popperUpdate === 'function') {
103+
await this._popperUpdate()
104+
}
105+
91106
this.setState({
92107
expanded: !this.state.expanded,
93108
})
94109
}
95110

111+
private setPopperRef = (ref: HTMLDivElement | null, popperRef: React.Ref<any>) => {
112+
this._popperRef = ref
113+
if (typeof popperRef === 'function') {
114+
popperRef(ref)
115+
}
116+
}
117+
118+
private setUpdate = (update: () => Promise<any>) => {
119+
this._popperUpdate = update
120+
}
121+
122+
private onBlur = (event: React.FocusEvent<HTMLDivElement>) => {
123+
if (
124+
!(
125+
event.relatedTarget &&
126+
event.relatedTarget instanceof HTMLElement &&
127+
this._popperRef &&
128+
(this._popperRef === event.relatedTarget || this._popperRef.contains(event.relatedTarget))
129+
)
130+
) {
131+
this.setState({
132+
expanded: false,
133+
})
134+
}
135+
}
136+
96137
render(): JSX.Element {
97138
return (
98-
<div
99-
className={ClassNames(
100-
'expco focusable subtle colorpicker',
101-
{
102-
'expco-expanded': this.state.expanded,
103-
},
104-
this.props.className
105-
)}
106-
>
107-
<div className={ClassNames('expco-title focusable-main')} onClick={this.toggleExpco}>
108-
<div className="color-preview" style={{ backgroundColor: this.state.selectedValue }}></div>
109-
</div>
110-
<a className="action-btn right expco-expand subtle" onClick={this.toggleExpco}>
111-
<FontAwesomeIcon icon={faChevronUp} />
112-
</a>
113-
<div className="expco-body bd">
114-
{_.values(
115-
_.mapObject(this.props.availableOptions, (value, key) => {
116-
return (
117-
<div className="expco-item" key={key}>
118-
<label className="action-btn" onClick={() => this.handleChange(value)}>
119-
<div className="color-preview" style={{ backgroundColor: value }}></div>
120-
</label>
121-
</div>
122-
)
123-
})
139+
<Manager>
140+
<Reference>
141+
{({ ref }) => (
142+
<div
143+
ref={ref}
144+
className={ClassNames(
145+
'expco form-select colorpicker',
146+
{
147+
'expco-expanded': this.state.expanded,
148+
disabled: this.props.disabled,
149+
},
150+
this.props.className
151+
)}
152+
tabIndex={-1}
153+
onBlur={this.onBlur}
154+
onClick={this.toggleExpco}
155+
>
156+
<div className={ClassNames('expco-title focusable-main')} onClick={this.toggleExpco}>
157+
<div className="color-preview" style={{ backgroundColor: this.state.selectedValue }}></div>
158+
</div>
159+
<a className="action-btn right expco-expand" onClick={this.toggleExpco}>
160+
&nbsp;
161+
</a>
162+
</div>
124163
)}
125-
</div>
126-
</div>
164+
</Reference>
165+
<Popper
166+
placement="bottom-start"
167+
modifiers={[
168+
{ name: 'flip', enabled: false },
169+
{ name: 'offset', enabled: true, options: { offset: [0, -1] } },
170+
{
171+
name: 'eventListeners',
172+
enabled: true,
173+
options: {
174+
scroll: this.state.expanded,
175+
resize: this.state.expanded,
176+
},
177+
},
178+
]}
179+
>
180+
{({ ref, style, placement, update }) => {
181+
this.setUpdate(update)
182+
return (
183+
<div
184+
ref={(r) => this.setPopperRef(r, ref)}
185+
style={style}
186+
data-placement={placement}
187+
className={ClassNames(
188+
'expco expco-popper colorpicker',
189+
{
190+
'expco-expanded': this.state.expanded,
191+
},
192+
this.props.className
193+
)}
194+
tabIndex={-1}
195+
onBlur={this.onBlur}
196+
>
197+
{this.state.expanded && (
198+
<div className="expco-body bd">
199+
<div className="expco-list">
200+
{_.map(this.props.availableOptions, (value, key) => {
201+
return (
202+
<div className="expco-item" key={key}>
203+
<label className="action-btn" onClick={() => this.handleChange(value)}>
204+
<div className="color-preview" style={{ backgroundColor: value }}></div>
205+
</label>
206+
</div>
207+
)
208+
})}
209+
</div>
210+
</div>
211+
)}
212+
</div>
213+
)
214+
}}
215+
</Popper>
216+
</Manager>
127217
)
128218
}
129219
}

0 commit comments

Comments
 (0)