Skip to content

Commit

Permalink
revert removing forget active option
Browse files Browse the repository at this point in the history
  • Loading branch information
amk221 committed Nov 14, 2024
1 parent 9ff3c85 commit 144c1f4
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 21 deletions.
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
## 16.4.0

- Remove cycling options, to get closer to native behaviour
- Forgets active option on mouseout, to get closer to native behaviour

## 16.3.1

Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ This addon will automatically render a [Combobox](https://developer.mozilla.org/
- **This addon**: Does not select the option
- **Reason**: Allows for further customisation

#### Mousing out

- **Native**: Forgets current option<br>
- **This addon**: Remembers current option
- **Reason**: This is because, the select box still has focus and as such, it is still receptive to user input - like pressing Enter to select that option. It also makes styling the different states easier with CSS and can prevent the active option from jumping around when mousing in and out.

</details>

## `SelectBox`
Expand Down
8 changes: 8 additions & 0 deletions addon/components/select-box/index.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ export default class SelectBox extends Component {
return [...this.element.querySelectorAll('.select-box__option')];
}

get hasFocus() {
return this.interactiveElement === document.activeElement;
}

@cached
get options() {
if (!this.element) {
Expand Down Expand Up @@ -301,6 +305,10 @@ export default class SelectBox extends Component {

@action
handleMouseLeave() {
if (this.hasFocus) {
return;
}

this._forgetActiveOption();
}

Expand Down
64 changes: 44 additions & 20 deletions tests/integration/components/select-box/mouse-option-test.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -183,18 +183,22 @@ module('select-box (mouseenter option)', function (hooks) {
});

test('mousing out of a select box deactivates the options when it does not have focus', async function (assert) {
assert.expect(2);
assert.expect(4);

await render(<template>
<SelectBox as |sb|>
<SelectBox @value="c" as |sb|>
<sb.Options>
<sb.Option>a</sb.Option>
<sb.Option>b</sb.Option>
<sb.Option>c</sb.Option>
<sb.Option @value="a">a</sb.Option>
<sb.Option @value="b">b</sb.Option>
<sb.Option @value="c">c</sb.Option>
</sb.Options>
</SelectBox>
</template>);

assert
.dom('.select-box__option:nth-child(3)')
.hasAttribute('aria-current', 'true');

await triggerEvent('.select-box__option:nth-child(2)', 'mouseenter');

assert
Expand All @@ -210,40 +214,60 @@ module('select-box (mouseenter option)', function (hooks) {
'false',
"it was set to current so the developer doesn't have to battle with :hover vs current"
);

assert
.dom('.select-box__option:nth-child(3)')
.hasAttribute(
'aria-current',
'true',
'falls back to selected value, since that is where keybaord control starts from'
);
});

test('mousing out of a select box deactivates the options when it has focus (listbox)', async function (assert) {
assert.expect(2);
test('mousing out of a select box does not deactivate the options when it has focus (listbox)', async function (assert) {
assert.expect(4);

await render(<template>
<SelectBox as |sb|>
<SelectBox @value="c" as |sb|>
<sb.Options>
<sb.Option>a</sb.Option>
<sb.Option>b</sb.Option>
<sb.Option>c</sb.Option>
<sb.Option @value="a">a</sb.Option>
<sb.Option @value="b">b</sb.Option>
<sb.Option @value="c">c</sb.Option>
</sb.Options>
</SelectBox>
</template>);

await focus('.select-box__options');

assert
.dom('.select-box__option:nth-child(3)')
.hasAttribute('aria-current', 'true');

await triggerEvent('.select-box__option:nth-child(2)', 'mouseenter');

assert
.dom('.select-box__option:nth-child(2)')
.hasAttribute('aria-current', 'true', 'precondition');
.hasAttribute('aria-current', 'true');

await triggerEvent('.select-box', 'mouseleave');

assert.dom('.select-box__option:nth-child(2)').hasAttribute(
'aria-current',
'false',
`the list box still has focus, and as such it is receptive to user input
therefore, one might expect the current option to remain as such,
but this addon tries to mimic native select boxes as much as possible`
'true',
`still focused, and so still receptive to user input, pressing enter will select
the active option`
);

assert
.dom('.select-box__option:nth-child(3)')
.hasAttribute(
'aria-current',
'false',
'does not falls back to selected value'
);
});

test('mousing out of a select box deactivates the options when it has focus (comobox - trigger)', async function (assert) {
test('mousing out of a select box does not deactivate the options when it has focus (comobox - trigger)', async function (assert) {
assert.expect(1);

await render(<template>
Expand All @@ -263,10 +287,10 @@ module('select-box (mouseenter option)', function (hooks) {

assert
.dom('.select-box__option:nth-child(2)')
.hasAttribute('aria-current', 'false');
.hasAttribute('aria-current', 'true');
});

test('mousing out of a select box deactivates the options when it has focus (comobox - input)', async function (assert) {
test('mousing out of a select box does not deactivate the options when it has focus (comobox - input)', async function (assert) {
assert.expect(1);

await render(<template>
Expand All @@ -286,7 +310,7 @@ module('select-box (mouseenter option)', function (hooks) {

assert
.dom('.select-box__option:nth-child(2)')
.hasAttribute('aria-current', 'false');
.hasAttribute('aria-current', 'true');
});

test('mousing down on an option does not select it', async function (assert) {
Expand Down

0 comments on commit 144c1f4

Please sign in to comment.