Skip to content

Commit

Permalink
Merge pull request #649 from alphagov/styling-props
Browse files Browse the repository at this point in the history
Update options for styling component inputs
  • Loading branch information
romaricpascal authored Jan 30, 2024
2 parents 40350ae + d1967d5 commit 3906cdc
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 31 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ You can also import it using Sass:
@import "accessible-autocomplete";
```

> [!NOTE]
>
> When styling the `.autocomplete__input` element, be aware that the `autoselect` option will render a second `.autocomplete__hint` input element for suggestion text. Both elements should be styled to ensure suggestions exactly align with the typed input text.
### Using with Preact

If you already use Preact in your application, you can import a bundle that will use that:
Expand Down Expand Up @@ -183,12 +187,22 @@ function suggest (query, populateResults) {

### Other options

#### `inputClasses` (default: `''`)
#### `inputClasses` (default: `null`)

Type: `string`
Type: `string | null`

Adds custom html classes to the generated `input` element.

If [`autoselect`](#autoselect) is set to `true`, the option [`hintClasses`](#hintClasses) can be configured separately or it will default to the `inputClasses` value.

#### `hintClasses` (default: `null`)

Type: `string | null`

Adds custom html classes to the additional `input` element that appears when what the user typed matches the start of a suggestion.

If [`autoselect`](#autoselect) is set to `true`, the option [`inputClasses`](#inputClasses) will be used as the default value unless `hintClasses` is set to an empty string `''`.

#### `menuAttributes` (default: `{}`)

Type: `Object`
Expand Down
2 changes: 1 addition & 1 deletion dist/accessible-autocomplete.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/accessible-autocomplete.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/lib/accessible-autocomplete.preact.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/lib/accessible-autocomplete.preact.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/lib/accessible-autocomplete.react.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/lib/accessible-autocomplete.react.min.js.map

Large diffs are not rendered by default.

85 changes: 65 additions & 20 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@
max-width: 20em;
margin-bottom: 4rem;
}

/* Custom classes for the `XYZClasses` props with visual changes to see their effect without inspecting */
.app-input {
/* Adjust the font to check that both hint and input get the class by default,
to ensure the hint suggestion exactly aligns with the typed input text */
font-family: serif;
}

.app-hint {
box-shadow: inset 0 0 0 5px #44952e;
}
</style>
<link rel="stylesheet" href="../dist/accessible-autocomplete.min.css">
</head>
Expand Down Expand Up @@ -121,6 +132,22 @@ <h3><code>{ showAllValues: true, dropdownArrow: () => '' }</code></h3>
<label for="autocomplete-customDropdownArrow">Country</label>
<div id="tt-customDropdownArrow" class="autocomplete-wrapper"></div>

<h3><code>{ inputClasses: 'app-input'}</code></h3>
<p>
The classes provided in <code>inputClasses</code> are added to
the component's <code>&lt;input&gt;</code>.
</p>
<label for="autocomplete-inputClasses">Country</label>
<div id="tt-inputClasses" class="autocomplete-wrapper"></div>

<h3><code>{ hintClasses: 'app-hint'}</code></h3>
<p>
The classes provided in <code>hintClasses</code> are added to
the component's hint that appears when the value matches the start of a suggestion.
</p>
<label for="autocomplete-hintClasses">Country</label>
<div id="tt-hintClasses" class="autocomplete-wrapper"></div>

<h2>Advanced features</h2>

<h3>Progressive enhancement</h3>
Expand Down Expand Up @@ -434,8 +461,7 @@ <h3>Translating texts</h3>
source: countries,
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input"
}
})
</script>

Expand All @@ -449,8 +475,7 @@ <h3>Translating texts</h3>
source: countries,
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input"
}
})
</script>

Expand All @@ -464,8 +489,7 @@ <h3>Translating texts</h3>
source: countries,
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input"
}
})
</script>

Expand All @@ -479,8 +503,7 @@ <h3>Translating texts</h3>
source: countries,
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input"
}
})
</script>

Expand All @@ -489,13 +512,42 @@ <h3>Translating texts</h3>
id = 'autocomplete-defaultValue'
accessibleAutocomplete({
defaultValue: 'Germany',
element: element,
id: id,
source: countries,
menuAttributes: {
"aria-labelledby": id
}
})
</script>

<script type="text/javascript">
element = document.querySelector('#tt-inputClasses')
id = 'autocomplete-inputClasses'
accessibleAutocomplete({
element: element,
id: id,
source: countries,
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input"
autoselect: true,
inputClasses: 'app-input'
})
</script>

<script type="text/javascript">
element = document.querySelector('#tt-hintClasses')
id = 'autocomplete-hintClasses'
accessibleAutocomplete({
element: element,
id: id,
source: countries,
menuAttributes: {
"aria-labelledby": id
},
autoselect: true,
hintClasses: 'app-hint'
})
</script>

Expand Down Expand Up @@ -541,7 +593,6 @@ <h3>Translating texts</h3>
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input",
templates: {
inputValue: inputValueTemplate,
suggestion: suggestionTemplate
Expand All @@ -559,8 +610,7 @@ <h3>Translating texts</h3>
source: countries,
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input"
}
})
</script>

Expand All @@ -574,8 +624,7 @@ <h3>Translating texts</h3>
source: countries,
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input"
}
})
</script>

Expand All @@ -589,8 +638,7 @@ <h3>Translating texts</h3>
source: countries,
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input"
}
})
</script>

Expand All @@ -604,8 +652,7 @@ <h3>Translating texts</h3>
source: countries,
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input"
}
})
</script>

Expand All @@ -619,7 +666,6 @@ <h3>Translating texts</h3>
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input",
source: countries,
tStatusQueryTooShort: function (minQueryLength) {
return 'Tippe mindestens ' + minQueryLength + ' Zeichen ein für Resultate.'
Expand Down Expand Up @@ -655,7 +701,6 @@ <h3>Translating texts</h3>
menuAttributes: {
"aria-labelledby": id
},
inputClasses: "govuk-input",
dropdownArrow: function (config) {
return '<svg class="' + config.className + '" style="top: 8px;" viewBox="0 0 512 512" ><path d="M256,298.3L256,298.3L256,298.3l174.2-167.2c4.3-4.2,11.4-4.1,15.8,0.2l30.6,29.9c4.4,4.3,4.5,11.3,0.2,15.5L264.1,380.9 c-2.2,2.2-5.2,3.2-8.1,3c-3,0.1-5.9-0.9-8.1-3L35.2,176.7c-4.3-4.2-4.2-11.2,0.2-15.5L66,131.3c4.4-4.3,11.5-4.4,15.8-0.2L256,298.3 z"/></svg>'
}
Expand Down
8 changes: 5 additions & 3 deletions src/autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ export default class Autocomplete extends Component {
tAssistiveHint: () => 'When autocomplete results are available use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.',
dropdownArrow: DropdownArrowDown,
menuAttributes: {},
inputClasses: ''
inputClasses: null,
hintClasses: null
}

elementReferences = {}
Expand Down Expand Up @@ -420,7 +421,8 @@ export default class Autocomplete extends Component {
tAssistiveHint,
dropdownArrow: dropdownArrowFactory,
menuAttributes,
inputClasses
inputClasses,
hintClasses
} = this.props
const { focused, hovered, menuOpen, options, query, selected, ariaHint, validChoiceMade } = this.state
const autoselect = this.hasAutoselect()
Expand Down Expand Up @@ -507,7 +509,7 @@ export default class Autocomplete extends Component {
/>

{hintValue && (
<span><input className={hintClassName} readonly tabIndex='-1' value={hintValue} /></span>
<span><input className={[hintClassName, hintClasses === null ? inputClasses : hintClasses].filter(Boolean).join(' ')} readonly tabIndex='-1' value={hintValue} /></span>
)}

<input
Expand Down
28 changes: 28 additions & 0 deletions test/integration/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,33 @@ const customTemplatesExample = () => {
})
}

const classesPropsExamples = () => {
describe('classes properties', () => {
it('should set `inputClasses` on both hint and input', async () => {
const $input = await $('input#autocomplete-inputClasses')
await expect($input).toHaveElementClass('app-input')

// Trigger the display of the hint
await $input.setValue('fra')

const $hint = $input.parentElement().$('.autocomplete__hint')
await expect($hint).toBeDisplayed()
await expect($hint).toHaveElementClass('app-input')
})

it('should set `hintClasses` on the hint', async () => {
const $input = await $('input#autocomplete-hintClasses')

// Trigger the display of the hint
await $input.setValue('fra')

const $hint = $input.parentElement().$('.autocomplete__hint')
await expect($hint).toBeDisplayed()
await expect($hint).toHaveElementClass('app-hint')
})
})
}

const takeScreenshotsIfFail = () => {
afterEach(async function () {
const testFailed = this.currentTest.state === 'failed'
Expand All @@ -248,6 +275,7 @@ describe('Accessible Autocomplete', () => {

basicExample()
customTemplatesExample()
classesPropsExamples()

takeScreenshotsIfFail()
})
Expand Down

0 comments on commit 3906cdc

Please sign in to comment.