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
Update ways of configuring menu attributes #650
Conversation
de4763e
to
7cfc175
Compare
@@ -57,6 +57,10 @@ | |||
.custom-hint-class { | |||
box-shadow: inset 0 0 0 5px #44952e; | |||
} | |||
|
|||
.custom-menu-class { | |||
box-shadow: 0 3px 0 0 #fd0, 3px 3px 0 0 #fd0, -3px 3px 0 0 #fd0; |
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.
Bit wordy, but extends the yellow focus border to wrap around the menu, not just the input, for a nice visual change.
src/autocomplete.js
Outdated
const menuIsVisible = menuOpen || showNoOptionsFound | ||
const menuModifierVisibility = `${menuClassName}--${(menuIsVisible) ? 'visible' : 'hidden'}` | ||
|
||
const safeMenuAttributes = sanitiseMenuAttributes(menuAttributes || {}) |
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.
Instead of lots of new sanitisation code, can we overwrite role/id instead?
menuAttributes.id = id
menuAttributes.role = role
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.
That's a good idea for avoiding to delete
the id
and the role
, didn't think of that. We could do the same with class
and className
(we'd need to set both, but I don't think that's a massive issue. Could try setting one to null
depending on how things work with React/Preact).
I'd still be keen to clone the object to avoid modifying the prop we're given, or do you think it's over the top?
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.
With object spread?
We had {...menuAttributes}
on line 538 previously:
Are you thinking to overwrite role/id with {...menuAttributes, id, role}
instead?
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.
Yeah, just with an object spread, so that when we set the id
or role
, it doesn't leak the modifications to the object that was passed as props directly. Thinking this'll end up with something like:
// Compute the menu classes from the array
// including `menuAttributes.class` and `menuAttributes.className`
const menuClasses = ...
const computedMenuAttributes = {
...menuAttributes,
// Override the attributes the component computes
id: `${id}__listbox`,
role: 'listbox',
className: menuClasses.join(' ')
}
// Figure a way to delete the `class` property
delete computedMenuAttributes.class
// Then in the JSX, leaving the handler here for consistency with the other elements
// whose handlers are set in JSX. But could equaly go in `computedMenuAttributes` as well.
<ul
onMouseLeave={(event) => this.handleListMouseLeave(event)}
{...computedMenuAttributes} >
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.
Updated with something of the shape I described. Moved onMouseLeave
in the computedAttributes
to make the JSX on one line in the end.
b972a2d
to
d1967d5
Compare
in anticipation of pushing optional values to the array before it's joined in the JSX
7cfc175
to
9eb5e1d
Compare
id: `${id}__listbox`, | ||
role: 'listbox', | ||
className: menuClassList.join(' '), | ||
onMouseLeave: this.handleListMouseLeave |
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.
Removed the wrapping arrow function, as the handler is bound in the constructor already, so that'll save re-creating listeners each time the menu is re-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.
Shall we do the same to handleInputClick
?
9eb5e1d
to
7c105ae
Compare
README.md
Outdated
> This option will not override the attributes computed by the component | ||
> - `id` and `role` are dropped to limit risks to accessibility | ||
> - `className` and `class` are appended to the `class` attribute of the menu so it keeps the classes computed by the component |
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've had a go at re-wording this to include all three id
, role
and onMouseLeave
Good to explain and link to menuClasses
too? Don't worry about explaining the class
/className
difference since we haven't already done so in the dropdownArrow
docs
> This option will not override the attributes computed by the component | |
> - `id` and `role` are dropped to limit risks to accessibility | |
> - `className` and `class` are appended to the `class` attribute of the menu so it keeps the classes computed by the component | |
> To maintain assistive technology support, menu attributes `id`, `role` and `onMouseLeave` cannot be overridden using `menuAttributes`. Setting `className` will append to the component default and [`menuClasses`](#menuClasses) values. |
src/autocomplete.js
Outdated
if (menuAttributes?.className) { | ||
menuClassList.push(menuAttributes.className) | ||
} | ||
|
||
if (menuAttributes?.class) { | ||
menuClassList.push(menuAttributes.class) | ||
} |
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 like class
takes precedence in Preact, rather than allowing both?
if (menuAttributes?.className) { | |
menuClassList.push(menuAttributes.className) | |
} | |
if (menuAttributes?.class) { | |
menuClassList.push(menuAttributes.class) | |
} | |
if (menuAttributes?.class || menuAttributes?.className) { | |
menuClassList.push(menuAttributes?.class || menuAttributes?.className) | |
} |
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.
Yeah, that's a good shout. I'll amend 😊
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.
Added extra test cases while I was at it.
7c105ae
to
d8f8b77
Compare
4db7b55
to
d031e68
Compare
@colinrotherham Things should be all tidy. The first force-push has the interesting changes, the second being just the tidy up of a stray comma that |
README.md
Outdated
|
||
Type: `string | null` | ||
|
||
Adds custom html classes to the menu elements. |
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.
We just say "menu" elsewhere but should we fix elements → element, or be specific like menuAttributes
?
Adds custom html classes to the menu elements. | |
Adds custom html classes to the generated `ul` menu element. |
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.
Updated both here and for menuAttributes
😊
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.
Even better, thank you
d031e68
to
7ed8b6b
Compare
7ed8b6b
to
25cc4a3
Compare
Prevent the attributes set through
menuAttributes
from overriding any of the attributes set internally:id
androle
are dropped to limit risks to accessibilityclassName
andclass
are appended to theclass
attribute of the menu so it keeps the classes computed by the componentIn addition to the update to
menuAttributes
, the PR also adds amenuClasses
. Even if it doubles with withmenuAttributes.(class|className)
, it provides a API with a name consistent withinputClasses
andhintClasses
from #649 .