darrenjennings / vue-autosuggest

🔍 Vue autosuggest component.

Home Page:https://darrenjennings.github.io/vue-autosuggest

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[before|after]-input no longer adjacent to input

jenglish404 opened this issue · comments

  • vue-autosuggest version: 2.2.0
  • node version: 12.18.1
  • npm (or yarn) version: 6.14.8

Problem description:

In the most recent change, it looks like a div was added as a wrapper around the input:

<slot name="before-input" /><div
      role="combobox"
      :aria-expanded="isOpen ? 'true' : 'false'"
      aria-haspopup="listbox"
      :aria-owns="`${componentAttrIdAutosuggest}-${componentAttrPrefix}__results`"
    ><input
      :type="internal_inputProps.type"
      :value="internalValue"
      :autocomplete="internal_inputProps.autocomplete"
      :class="[isOpen ? `${componentAttrPrefix}__input--open` : '', internal_inputProps['class']]"
      v-bind="internal_inputProps"
      aria-autocomplete="list"
      :aria-activedescendant="isOpen && currentIndex !== null ? `${componentAttrPrefix}__results-item--${currentIndex}` : ''"
      :aria-controls="`${componentAttrIdAutosuggest}-${componentAttrPrefix}__results`"
      @input="inputHandler"
      @keydown="handleKeyStroke"
      v-on="listeners"
    ></div><slot name="after-input" />

The end result is that the [before|after]-input slots are now before|after the div, not the input. We were using the after-input slot along with some Sass that relies on the label being adjacent to the input (input + label):

input[type='text'] {
  & + label {
      font-size: 12px;
      position: absolute;
      top: -10px;
      left: 14px;
      opacity: 0;
      color: transparent;
      @include transition-all;
  }
  
  // input focus
  &:focus {
    &::placeholder {
        color: transparent;
      }
  }

  &:not(:placeholder-shown) {
      & + label {
        top: -17px;
        left: 5px;
        opacity: 1;
      }

      &::placeholder {
        color: transparent;
      }
    }
}

Here's what that looks like in action (label floats above input when input receives focus):
floating-label

Since the after-input slot is no longer adjacent to the input, it breaks this styling. I tried working around this, but there's no sibling-of-parent CSS selector (that I'm aware of).

Suggested solution:

Option 1

Revert the change (remove the div wrapper). I see that some of the aria attributes have been shuffled around, so if it needs to be this way then...

Option 2

Move the [before|after]-input slots inside the wrapper so that they're once again adjacent to the input.

I'm happy to make the change and open a PR if that helps.

@jenglish404 can you instead adjust your selectors? The a11y change was important, so would make sense to fix any css that relies on html hierarchy in userland vs. having the label or any other before/after slot content be contained inside of a role="comboxbox". The html from the combobox wai-aria spec suggests putting the label outside:

<label for="ex1-input"
       id="ex1-label"
       class="combobox-label">
  Choice 1 Fruit or Vegetable
</label>
<div class="combobox-wrapper">
  <div role="combobox"
       aria-expanded="false"
       aria-owns="ex1-listbox"
       aria-haspopup="listbox"
       id="ex1-combobox">
    <input type="text"
           aria-autocomplete="list"
           aria-controls="ex1-listbox"
           id="ex1-input">
  </div>
  <ul aria-labelledby="ex1-label"
      role="listbox"
      id="ex1-listbox"
      class="listbox hidden">
  </ul>
</div>```

No worries. I was able to get this to work by adding focus and focusout listeners on the vue-autosuggest component:

<vue-autosuggest
        :suggestions="suggestions"
        :input-props="inputProps"
        :get-suggestion-value="getSuggestionValue"
        @selected="onResultSelected"
        @keypress="handleKeypress"
        @input="onInputChange"
        @focus="onInputFocus"
        @focusout="onInputFocusout"
      >
 ...

...where onInputFocus and onInputFocusout toggle a flag that can be used to set a class on the outer container and subsequently style the label to match the rest of our site.

Thank you so much for the speedy reply!