Skip to content
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

Adds Input suffixes and prefixes #77

Merged
merged 11 commits into from
Nov 27, 2020

Conversation

andy-polhill
Copy link
Contributor

@andy-polhill andy-polhill commented Nov 23, 2020

Description

Initially raising this as a draft PR to get some visibility on it, it proved to be slightly larger than expected and any help getting it over the line would be most appreciated. It's probably worth reviewing one commit at a time.

Outstanding work

  • Check up on a11y best practice
  • Cross browser testing
  • Self review of the code

Requirements

Create the ability to add input prefixes and suffixes to input fields which may contain buttons. To enable this work a couple of smaller commits were made.

  • Addition of a small button variant
  • Addition of a small spinner variant
  • Addition of disabled property to button
  • Addition of an 'add-on' button variant.

As you can see from the designs the buttons are within the borders of the input field. This left me with two possible implementation options.

  1. Absolutely position the input suffix/prefix inside the field. This would work except that the suffix could contain text and therefore be of a variable size, we would have to use JavaScript to detect the size the suffix before offsetting it
  2. Add a wrapper around the input field, and move the focus events up to the wrapping element. We can then put the input fields, suffixes and prefixes inside that wrapper and use flexbox to control them.

I ended up going with option 2 as I think option 1 would lead to a flicker as the JavaScript calculated the suffix width.

From an a11y point of view I have linked the prefix and suffix to the described-by attribute of the input field. I don't treat the button any different from the text span, although I think a bit more testing on this would be nice. There is a similar discussion on GOV.uk at the moment

Screenshot 2020-11-23 at 21 46 01Screenshot 2020-11-23 at 21 45 23Screenshot 2020-11-23 at 21 46 19

https://deploy-preview-77--legal-and-general-canopy.netlify.app/?path=/story/components-form-input--with-button-suffix

https://legalandgeneral.invisionapp.com/d/main#/console/19910472/416751159/preview

Checklist:

  • The commit messages follow the convention for this project
  • I have provided an adequate amount of test coverage
  • I have added the functionality to the test app
  • I have provided a story in storybook to document the changes
  • I have provided documentation in the notes section of the story
  • I have added any new public feature modules to public-api.ts
  • I have linked the new component to adobe DSM (if appropriate)

@andy-polhill andy-polhill added the enhancement New feature or request label Nov 24, 2020
@andy-polhill andy-polhill requested a review from a team November 24, 2020 09:29
@alexcanning
Copy link
Contributor

Should I be able to do this?

2020-11-24_11-33-38_am

@alexcanning
Copy link
Contributor

Focus on secondary buttons falls beneath primary button

2020-11-24_11-37-43_am

@andy-polhill andy-polhill force-pushed the input-with-button branch 3 times, most recently from 059b8eb to 30cd041 Compare November 25, 2020 10:18
@andy-polhill
Copy link
Contributor Author

#77 (comment)
I fixed the focus issue.
Screenshot 2020-11-25 at 10 23 52

@andy-polhill
Copy link
Contributor Author

#77 (comment)

You can in theory put more suffixes in than you would ever need, there is some responsibility on the user to be sensible. I fixed the alignment issue in that screen shot though.

@andy-polhill andy-polhill marked this pull request as ready for review November 25, 2020 10:35
Copy link
Contributor

@elenagarrone elenagarrone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! I just had few small comments plus the followings for storybook:

  • the with button: the button doesn't have text so the screen reader only reads "button"
  • the with suffix: the example has the percentage but the label is still "Name" which makes no sense ;) this is just me being annoying :D
  • the with prefix: same as per above comment
  • the with multiple button suffixes: both the buttons don't have text so nothing is read to the screen readers apart from "button"

package.json Outdated Show resolved Hide resolved
[iconButton]="iconButton"
[iconPosition]="iconPosition"
[loading]="loading"
[fullWidth]="fullWidth"
[size]="size"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if maybe we should have a single size input that includes fullWidth instead of having them as two separate inputs. They both affect the size of the button so I think it makes sense 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the downside of doing this is that you may want a button to be both sm and fullWidth, which would be easy to do with separate inputs. If they were combined, we may need more options such as sm-full-width, md-full-width and so on, which could get long.

Copy link
Contributor Author

@andy-polhill andy-polhill Nov 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could help reduce the number of options, links a bit to this issue.. https://github.com/canopy-collective/canopy/issues/251. I didn't actually change anything around that on this PR though, I just put it into alphabetical order. (which I realise doesn't make it easier for the reviewer 😀 )

return this._prefixChildren;
}

@Input() id = `lg-input-${nextUniqueId++}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to save nextUniqueId++ into a separate const and then use it, otherwise if we end up reusing it, it will increase each time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was mostly reformatting and not changed in the PR. I'm open to changing it though but I'm not sure I quite follow. The idea is that it should increase each time, it was a convention I shamefully borrowed from material ui

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it should increase each time a new component is instantiated.
I have had to fix multiple instances where we did the following mistake:

@Input() id = `lg-input-${nextUniqueId++}`;
anotherVariable = `my-variable-${nextUniqueId++}`

which produces:

@Input() id = `lg-input-1`;
anotherVariable = `my-variable-2`

while it should be:

@Input() id = `lg-input-1`;
anotherVariable = `my-variable-1`

I know in this component this is not an issue atm but it did happen multiple times and I'm just concerned that someone might come along and do the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah ok that makes sense, so in theory with the first example it still works as the IDs are unique, but it's harder to ascertain which elements join together as the numerical part of the id is different. (pushed a change)

private hasHover = false;
private disabledStateChanges: Subscription;

ngAfterContentInit() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like us to start using return types a bit more. Could you please add the return types for these functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, I've added a bunch to this file, I wonder if there is a lint warning we can add?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I'm sure there is as we have it in our project. Might be one for when we create the global linting?


.lg-input-field {
$block: &;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not 100% sure the $block name works well, I wonder if $field would be better? Not super fussed either way on this though :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went for block as in the block inBEM, but in hindsight that may be misread, did you read it as block like display:block?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it took me a couple of takes to realise what was going on, maybe renaming it could make the code easier to scan. Then again, it's pretty clear once you know what's going on. So happy either way really :)

[iconButton]="iconButton"
[iconPosition]="iconPosition"
[loading]="loading"
[fullWidth]="fullWidth"
[size]="size"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the downside of doing this is that you may want a button to be both sm and fullWidth, which would be easy to do with separate inputs. If they were combined, we may need more options such as sm-full-width, md-full-width and so on, which could get long.

owensgit
owensgit previously approved these changes Nov 26, 2020
@andy-polhill
Copy link
Contributor Author

@elenagarrone on these ones...

the with button: the button doesn't have text so the screen reader only reads "button"
the with suffix: the example has the percentage but the label is still "Name" which makes no sense ;) this is just me being annoying :D
the with prefix: same as per above comment
the with multiple button suffixes: both the buttons don't have text so nothing is read to the screen readers apart from "button"

I've hopefully fixed the first one I was accidentally not rendering the text when it was an icon button. On the other ones I've tweaked the default text for those examples, people could still override them with silly things. I'm hoping by fixing the first one I've also fixed the last one, but there was text in the close button, so I'm slightly surprised that didn't read out, I might need to borrow your screen reader skills.

@elenagarrone
Copy link
Contributor

elenagarrone commented Nov 27, 2020

@elenagarrone on these ones...

the with button: the button doesn't have text so the screen reader only reads "button"
the with suffix: the example has the percentage but the label is still "Name" which makes no sense ;) this is just me being annoying :D
the with prefix: same as per above comment
the with multiple button suffixes: both the buttons don't have text so nothing is read to the screen readers apart from "button"

I've hopefully fixed the first one I was accidentally not rendering the text when it was an icon button. On the other ones I've tweaked the default text for those examples, people could still override them with silly things. I'm hoping by fixing the first one I've also fixed the last one, but there was text in the close button, so I'm slightly surprised that didn't read out, I might need to borrow your screen reader skills.

The text in the first and last button is still not read and the reason is that you've set the lg-btn-text to have visibility: hidden. Most screen readers will not read elements with visibility: hidden or display: block. I would suggest you use the mixin lg-visually-hidden or the class .lg-visually-hidden which will allow screen readers to read the text.

@andy-polhill
Copy link
Contributor Author

#77 (comment)
Good spot on this @elenagarrone , it was actually a bug on the original icon button implementation, I have tagged a separate commit onto this PR to fix it.

elenagarrone
elenagarrone previously approved these changes Nov 27, 2020
Copy link
Contributor

@elenagarrone elenagarrone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work 👍

BREAKING CHANGE:
- The input.scss styles have been wrapped into the main 'input-field.component.scss' file, if you were referencing this file directly any references may need updating
- The input button types have changed to be more specific. If you were referencing the types directly you will need to update the following:
  `Variant` => `ButtonVariant`
  `Behaviour` => `ButtonBehaviour`
There are a couple of instances where we use Array.includes in the components, consumers will need
to manually polyfill this. We should either mention this in the docs or modify the code.
Previously the button text was set to visibility:hidden; this was preventing it being read out on
screen readers, updated to use the lg-visually-hidden mixin which is more screen reader friendly.
@owensgit owensgit self-requested a review November 27, 2020 16:07
Copy link
Contributor

@owensgit owensgit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition Andy! 👍

@owensgit owensgit merged commit 8c24443 into Legal-and-General:master Nov 27, 2020
@andy-polhill andy-polhill deleted the input-with-button branch November 27, 2020 16:14
@github-actions
Copy link
Contributor

🎉 This PR is included in version 3.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request released
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants