Skip to content

Commit

Permalink
feat: Allow dynamic value change for color picker #1154 (#2100)
Browse files Browse the repository at this point in the history
  • Loading branch information
marek-mihok authored Aug 7, 2023
1 parent 04df281 commit 10b35dd
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 7 deletions.
68 changes: 68 additions & 0 deletions ui/src/color_picker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,44 @@ describe('ColorPicker.tsx', () => {
expect(wave.args[name]).toBe('#DDD')
})

it('Set args when value is updated to different value', () => {
const { rerender } = render(<XColorPicker model={colorPickerProps} />)
expect(wave.args[name]).toBeFalsy()
rerender(<XColorPicker model={{ ...colorPickerProps, value: 'blue' }} />)

expect(wave.args[name]).toBe('blue')
})

it('Set args when value is updated to initial value', () => {
const { container, rerender } = render(<XColorPicker model={{ ...colorPickerProps, value: 'blue' }} />)
expect(wave.args[name]).toBe('blue')

fireEvent.input(container.querySelectorAll('input')[0]!, { target: { value: 'dddddd' } })
expect(wave.args[name]).toBe('#dddddd')

rerender(<XColorPicker model={{ ...colorPickerProps, value: 'blue' }} />)
expect(wave.args[name]).toBe('blue')
})

it('Set args when value is updated to different value - Inline picker', () => {
const { rerender } = render(<XColorPicker model={{ ...colorPickerProps, inline: true }} />)
expect(wave.args[name]).toBeFalsy()
rerender(<XColorPicker model={{ ...colorPickerProps, inline: true, value: '#DDD' }} />)

expect(wave.args[name]).toBe('#DDD')
})

it('Set args when value is updated to initial value - Inline picker', () => {
const { container, rerender } = render(<XColorPicker model={{ ...colorPickerProps, inline: true, value: '#AAA' }} />)
expect(wave.args[name]).toBe('#AAA')

fireEvent.input(container.querySelectorAll('input')[0]!, { target: { value: '#BBB' } })
expect(wave.args[name]).toBe('#BBB')

rerender(<XColorPicker model={{ ...colorPickerProps, inline: true, value: '#AAA' }} />)
expect(wave.args[name]).toBe('#AAA')
})

it('Calls sync when trigger is specified', () => {
const { container } = render(<XColorPicker model={{ ...colorPickerProps, trigger: true }} />)
// Changing alpha in order to trigger component's onChange.
Expand Down Expand Up @@ -91,5 +129,35 @@ describe('ColorPicker.tsx', () => {

expect(pushMock).not.toBeCalled()
})

it('Update choices', () => {
const { rerender, getAllByRole } = render(<XColorPicker model={{ ...colorPickerProps, choices: ['yellow', 'red', 'blue'] }} />)
expect(getAllByRole('radio')[0]).toHaveProperty('title', 'yellow')
expect(getAllByRole('radio')[1]).toHaveProperty('title', 'red')
expect(getAllByRole('radio')[2]).toHaveProperty('title', 'blue')
rerender(<XColorPicker model={{ ...colorPickerProps, choices: ['yellow', 'orange'] }} />)

expect(getAllByRole('radio')[0]).toHaveProperty('title', 'yellow')
expect(getAllByRole('radio')[1]).toHaveProperty('title', 'orange')
})

it('Set args when value is updated to different value - Swatch picker', () => {
const { rerender } = render(<XColorPicker model={{ ...colorPickerProps, value: '#AAA' }} />)
expect(wave.args[name]).toBe('#AAA')
rerender(<XColorPicker model={{ ...colorPickerProps, value: '#BBB' }} />)

expect(wave.args[name]).toBe('#BBB')
})

it('Set args when value is updated to initial value - Swatch picker', () => {
const { rerender, getAllByRole } = render(<XColorPicker model={{ ...colorPickerProps, value: '#AAA' }} />)
expect(wave.args[name]).toBe('#AAA')

fireEvent.click(getAllByRole('radio')[1])
expect(wave.args[name]).toBe('#BBB')

rerender(<XColorPicker model={{ ...colorPickerProps, value: '#AAA' }} />)
expect(wave.args[name]).toBe('#AAA')
})
})
})
24 changes: 17 additions & 7 deletions ui/src/color_picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ const
onChange(null, color)
}

React.useEffect(() => {
const color = Fluent.getColorFromString(val)
if (color) {
setColor(color)
setColorText(color.str)
}
wave.args[model.name] = val
}, [model.name, model.value, val])

return (
<div className={css.inlinePickerContainer}>
{model.label && <Fluent.Label>{model.label}</Fluent.Label>}
Expand All @@ -111,18 +120,19 @@ export const
[selectedColorId, setSelectedColorId] = React.useState<S | null>(defaultValue),
onSwatchChange = (_e: React.FormEvent<HTMLElement>, _id?: S, color = defaultValue) => {
wave.args[name] = color
model.value = color || undefined
setSelectedColorId(color)
if (trigger) wave.push()
},
onChange = (_e: React.SyntheticEvent<HTMLElement>, { str }: Fluent.IColor) => {
wave.args[name] = str || defaultValue
if (trigger) wave.push()
},
onChange = (e: React.SyntheticEvent<HTMLElement>, { str }: Fluent.IColor) => onSwatchChange(e, undefined, str),
normalizedWidth = formItemWidth(width),
minMaxWidth = !normalizedWidth?.includes('%') ? `calc(${normalizedWidth} - 35px)` : 'initial'

// eslint-disable-next-line react-hooks/exhaustive-deps
React.useEffect(() => { wave.args[name] = defaultValue }, [])

React.useEffect(() => {
wave.args[name] = defaultValue
setSelectedColorId(defaultValue)
}, [defaultValue, name])

return (
<div data-test={name}>
Expand All @@ -138,7 +148,7 @@ export const
: (
<Fluent.ColorPicker
alphaType={alpha ? 'alpha' : 'none'}
color={defaultValue || '#000'}
color={selectedColorId || '#000'}
onChange={onChange}
styles={{ root: { width: normalizedWidth, maxWidth: normalizedWidth }, colorRectangle: { minWidth: minMaxWidth, maxWidth: minMaxWidth } }}
/>
Expand Down

0 comments on commit 10b35dd

Please sign in to comment.