-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ui-select,ui-simple-select): add support for rendering selected … #1838
base: master
Are you sure you want to change the base?
Conversation
|
5be2cc4
to
a2725ad
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, see my remarks. Also please check out Chromatic, maybe this prop should be ignored there (see excludeProps in the examples.ts files)?
position: 'before' | 'after', | ||
defaultReturn: Renderable | ||
): Renderable { | ||
const isInputValueEmpty = inputValue === '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if this is null
or undefined
? I think we should handle these cases
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@matyasf I added the excludeProps to isOptionContentAppliedToInput. Also now my code handles null or undefined inputValue.
return console.warn( | ||
"isOptionContentAppliedToInput is set but no option has an isSelected='true' prop so desired content cannot be displayed in input filed" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd remove this, this can be a valid case if there is nothing selected initially.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@matyasf I think this is still a valid case if inputValue is set but isSelected is not. In this case, you end up with an option in the input field but without an icon despite you wanting to display an icon. (Try to set the selectedOptionId to null in the state and replace line 22 with this below in the last Select class example (Icons) :
const option = selectedOptionId ? this.getOptionById(selectedOptionId).label : '')
Also If nothing selected initially, this warning will not appear because the user must have set inputValue to null/'' as well (hopefully) and inputValue is already checked for being null in the code before. Try this example when nothing is selected initially, no warning.
class SingleSelectExample extends React.Component {
state = {
inputValue: '',
isShowingOptions: false,
highlightedOptionId: null,
selectedOptionId: null,
announcement: null
}
getOptionById(queryId) {
return this.props.options.find(({ id }) => id === queryId)
}
handleShowOptions = () => {
this.setState({ isShowingOptions: true })
}
handleHideOptions = () => {
const { selectedOptionId } = this.state
const option = selectedOptionId ? this.getOptionById(selectedOptionId).label : ''
this.setState({
isShowingOptions: false,
highlightedOptionId: null,
inputValue: option,
announcement: 'List collapsed.'
})
}
handleBlur = () => {
this.setState({ highlightedOptionId: null })
}
handleHighlightOption = (event, { id }) => {
event.persist()
const optionsAvailable = `${this.props.options.length} options available.`
const nowOpen = !this.state.isShowingOptions ? `List expanded. ${optionsAvailable}` : ''
const option = this.getOptionById(id).label
this.setState((state) => ({
highlightedOptionId: id,
inputValue: event.type === 'keydown' ? option : state.inputValue,
announcement: `${option} ${nowOpen}`
}))
}
handleSelectOption = (event, { id }) => {
const option = this.getOptionById(id).label
this.setState({
selectedOptionId: id,
inputValue: option,
isShowingOptions: false,
announcement: `"${option}" selected. List collapsed.`
})
}
render() {
const {
inputValue,
isShowingOptions,
highlightedOptionId,
selectedOptionId,
announcement
} = this.state
return (
<div>
<Select
renderLabel="Option Icons"
assistiveText="Use arrow keys to navigate options."
inputValue={inputValue}
isShowingOptions={isShowingOptions}
onBlur={this.handleBlur}
onRequestShowOptions={this.handleShowOptions}
onRequestHideOptions={this.handleHideOptions}
onRequestHighlightOption={this.handleHighlightOption}
onRequestSelectOption={this.handleSelectOption}
isOptionContentAppliedToInput
>
{this.props.options.map((option) => (
<Select.Option
id={option.id}
key={option.id}
isHighlighted={option.id === highlightedOptionId}
isSelected={option.id === selectedOptionId}
renderBeforeLabel={option.renderBeforeLabel}
>
{option.label}
</Select.Option>
))}
</Select>
<Alert
liveRegion={() => document.getElementById('flash-messages')}
liveRegionPoliteness="assertive"
screenReaderOnly
>
{announcement}
</Alert>
</div>
)
}
}
render(
<View>
<SingleSelectExample
options={[
{ id: 'opt1', label: 'Text', renderBeforeLabel: 'XY' },
{ id: 'opt2', label: 'Icon', renderBeforeLabel: <IconCheckSolid /> },
{
id: 'opt3',
label: 'Colored Icon',
renderBeforeLabel: (props) => {
let color = 'brand'
if (props.isHighlighted) color = 'primary-inverse'
if (props.isSelected) color = 'primary'
if (props.isDisabled) color = 'warning'
return <IconInstructureSolid color={color} />
}
}
]}
/>
</View>
)
* Whether or not the before and after content of the selected option appear in the input field. | ||
* | ||
* If the selected option has both before and after content, both will be displayed in the input field. | ||
* | ||
* One of the Select.Options isSelected prop should be true in order to display the content in the input field. | ||
* | ||
* Before and after content will not be displayed, if Select's inputValue is an empty value. | ||
* | ||
* If true and the selected option has a renderAfterInput value, it will replace the default arrow icon. | ||
* | ||
* If true and Select's own renderBeforeInput or renderAfterInput prop is set, it will display the selected option's content instead of Select's renderBeforeInput or renderAfterInput value. | ||
* | ||
* If the selected option's renderAfterInput value is empty, default arrow icon will be rendered. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use Markdown here, e.g. code blocks (backticks)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@matyasf I placed the backticks where needed.
…option's before and after content in Select and SimpleSelect input Closes: INSTUI-4225
a2725ad
to
73c40b2
Compare
…option's before and after content in Select and SimpleSelect input
Closes: INSTUI-4225
TEST PLAN:
test the case with icons before the options:
1. open the last example in Select (Icons)
2. set isOptionContentAppliedToInput to true on Select
3. the selected option's icon's should appear now in the beginning the input field and also when user selects a new option from the dropdown
test the case with icons after the options:
1. set isOptionContentAppliedToInput to true on Select in the last example
2. in SingleSelectExample's options props, rewrite renderBeforeLabel to renderBeforeLabel
3. in Select.Option replace renderBeforeLabel={option.renderBeforeLabel} with renderAfterLabel=. {option.renderAfterLabel}
4. now the arrow icon should be replaced with the selected option's icon
test the case when options have both before and after icons, both should be rendered
test the case when options are grouped: see the group example in Select (Composing option groups), it should render the selected option's before or after icon or both
test the case when none of the Select.Options' isSelected prop is true, the icon should not be rendered and a there should be a warning
test the case when Select's inputValue is empty, the icon should not be rendered
test the case when Select's own renderBeforeInput or renderAfterInput prop is set, it should display the selected option's content (icon) instead of Select's renderBeforeInput or renderAfterInput value
test the case when one of option has an empty renderAfterInput value, the default arrow icon should be rendered, but if another option with a non-empty renderAfterInput is selected, that option's icon should be rendered
test all the cases above in SimpleSelect
review the updated documentation and the new tests