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

✨ RSP-631 InputGroup: add Datepicker range variant #53

Merged
merged 9 commits into from
Mar 18, 2019
2 changes: 1 addition & 1 deletion docs/dropdown/dropdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ markup: |
<h4>Closed</h4>
<div class="spectrum-Dropdown" style="width: 240px;">
<button class="spectrum-FieldButton spectrum-Dropdown-trigger" aria-haspopup="true">
<span class="spectrum-Dropdown-label is-placeholder">Select a Country</span>
<span class="spectrum-Dropdown-label is-placeholder">Select a Country with a very long label, too long in fact</span>
<svg class="spectrum-Icon spectrum-UIIcon-ChevronDownMedium spectrum-Dropdown-icon" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-ChevronDownMedium" />
</svg>
Expand Down
59 changes: 59 additions & 0 deletions docs/inputgroup/datepicker-range-quiet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Date Picker - Range Quiet
description: A date picker uses the input group component to display a field with a button next to it
markup: |
<div class="spectrum-InputGroup spectrum-InputGroup--quiet spectrum-Datepicker spectrum-Datepicker--range" role="combobox" aria-expanded="false" aria-haspopup="dialog">
<input type="text" class="spectrum-Textfield spectrum-Textfield--quiet spectrum-InputGroup-field spectrum-Datepicker-startField" placeholder="mm/dd/yyyy" name="start" value="2018-10-01">
<div class="spectrum-Datepicker--rangeDash"></div>
<input type="text" class="spectrum-Textfield spectrum-Textfield--quiet spectrum-InputGroup-field spectrum-Datepicker-startField" placeholder="mm/dd/yyyy" name="end" value="2018-10-30">
<button type="button" class="spectrum-FieldButton spectrum-FieldButton--quiet" tabindex="-1" aria-label="Calendar">
<svg class="spectrum-Icon spectrum-UIIcon-ChevronDownMedium spectrum-Dropdown-icon" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-ChevronDownMedium" />
</svg>
</button>
<!-- To render focus ring around entire input group when one of the inputs has keyboard focus, we need this: -->
<div class="spectrum-Datepicker-focusRing" role="presentation"></div>
</div>

<p />

<div aria-invalid="true" class="spectrum-InputGroup spectrum-InputGroup--quiet spectrum-Datepicker spectrum-Datepicker--range is-invalid" role="combobox" aria-expanded="false" aria-haspopup="dialog">
<input type="text" class="spectrum-Textfield spectrum-Textfield--quiet spectrum-InputGroup-field spectrum-Datepicker-startField" aria-invalid="true" placeholder="mm/dd/yyyy" name="start" value="2018-10-01">
<div class="spectrum-Datepicker--rangeDash"></div>
<input type="text" class="spectrum-Textfield spectrum-Textfield--quiet spectrum-InputGroup-field spectrum-Datepicker-endField is-invalid" aria-invalid="true" placeholder="mm/dd/yyyy" name="end" value="2018-10-30">
<button type="button" class="spectrum-FieldButton spectrum-FieldButton--quiet is-invalid" tabindex="-1" aria-expanded="false" aria-haspopup="dialog" aria-label="Calendar">
<svg class="spectrum-Icon spectrum-UIIcon-ChevronDownMedium spectrum-Dropdown-icon" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-ChevronDownMedium" />
</svg>
</button>
<!-- To render focus ring around entire input group when one of the inputs has keyboard focus, we need this: -->
<div class="spectrum-Datepicker-focusRing" role="presentation"></div>
</div>

<p />

<div aria-disabled="true" class="spectrum-InputGroup spectrum-InputGroup--quiet spectrum-Datepicker spectrum-Datepicker--range is-disabled" role="combobox" aria-expanded="false" aria-haspopup="dialog">
<input type="text" class="spectrum-Textfield spectrum-Textfield--quiet spectrum-InputGroup-field spectrum-Datepicker-startField" placeholder="mm/dd/yyyy" name="start" value="2018-10-01" disabled>
<div class="spectrum-Datepicker--rangeDash"></div>
<input type="text" class="spectrum-Textfield spectrum-Textfield--quiet spectrum-InputGroup-field spectrum-Datepicker-endField" placeholder="mm/dd/yyyy" name="end" value="2018-10-30" disabled>
<button type="button" class="spectrum-FieldButton spectrum-FieldButton--quiet" tabindex="-1" disabled aria-expanded="false" aria-haspopup="dialog" aria-label="Calendar">
<svg class="spectrum-Icon spectrum-UIIcon-ChevronDownMedium spectrum-Dropdown-icon" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-ChevronDownMedium" />
</svg>
</button>
<!-- To render focus ring around entire input group when one of the inputs has keyboard focus, we need this: -->
<div class="spectrum-Datepicker-focusRing" role="presentation"></div>
</div>
<p/>

<div class="spectrum-InputGroup spectrum-InputGroup--quiet spectrum-Datepicker spectrum-Datepicker--range spectrum-Datepicker--datetimeRange" role="combobox" aria-expanded="false" aria-haspopup="dialog">
<input type="text" class="spectrum-Textfield spectrum-Textfield--quiet spectrum-InputGroup-field spectrum-Datepicker-startField" aria-invalid="false" placeholder="mm/dd/yyyy hh:mm a" name="start" value="">
<div class="spectrum-Datepicker--rangeDash"></div>
<input type="text" class="spectrum-Textfield spectrum-Textfield--quiet spectrum-InputGroup-field spectrum-Datepicker-endField" aria-invalid="false" placeholder="mm/dd/yyyy hh:mm a" name="end" value="">
<button type="button" class="spectrum-FieldButton spectrum-FieldButton--quiet" tabindex="-1" aria-expanded="false" aria-haspopup="dialog" aria-label="Calendar">
<svg class="spectrum-Icon spectrum-UIIcon-ChevronDownMedium spectrum-Dropdown-icon" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-ChevronDownMedium" />
</svg>
</button>
<!-- To render focus ring around entire input group when one of the inputs has keyboard focus, we need this: -->
<div class="spectrum-Datepicker-focusRing" role="presentation"></div>
</div>
60 changes: 60 additions & 0 deletions docs/inputgroup/datepicker-range.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Date Picker - Range
description: A date picker uses the input group component to display a field with a button next to it
markup: |
<div aria-invalid="false" class="spectrum-InputGroup spectrum-Datepicker spectrum-Datepicker--range" role="combobox" aria-expanded="false" aria-haspopup="dialog">
<input type="text" class="spectrum-Textfield spectrum-InputGroup-field spectrum-Datepicker-startField" placeholder="mm/dd/yyyy" name="start" value="">
<div class="spectrum-Datepicker--rangeDash"></div>
<input type="text" class="spectrum-Textfield spectrum-InputGroup-field spectrum-Datepicker-endField" placeholder="mm/dd/yyyy" name="end" value="">
<button type="button" class="spectrum-FieldButton" tabindex="-1" aria-expanded="false" aria-haspopup="dialog" aria-label="Calendar">
<svg class="spectrum-Icon spectrum-UIIcon-ChevronDownMedium spectrum-Dropdown-icon" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-ChevronDownMedium" />
</svg>
</button>
<!-- To render focus ring around entire input group when one of the inputs has keyboard focus, we need this: -->
<div class="spectrum-Datepicker-focusRing" role="presentation"></div>
</div>

<p/>

<div aria-invalid="true" class="spectrum-InputGroup spectrum-Datepicker spectrum-Datepicker--range is-invalid" role="combobox" aria-expanded="false" aria-haspopup="dialog">
<input type="text" class="spectrum-Textfield spectrum-InputGroup-field spectrum-Datepicker-startField" aria-invalid="true" placeholder="mm/dd/yyyy" name="start" value="">
<div class="spectrum-Datepicker--rangeDash"></div>
<input type="text" class="spectrum-Textfield spectrum-InputGroup-field spectrum-Datepicker-endField is-invalid" aria-invalid="true" placeholder="mm/dd/yyyy" name="end" value="">
<button type="button" class="spectrum-FieldButton is-invalid" tabindex="-1" aria-expanded="false" aria-haspopup="dialog" aria-label="Calendar">
<svg class="spectrum-Icon spectrum-UIIcon-ChevronDownMedium spectrum-Dropdown-icon" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-ChevronDownMedium" />
</svg>
</button>
<!-- To render focus ring around entire input group when one of the inputs has keyboard focus, we need this: -->
<div class="spectrum-Datepicker-focusRing" role="presentation"></div>
Copy link
Member

Choose a reason for hiding this comment

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

Mmmm, this can't be done with :before/:after? I don't see anything using those pseudo-elements right now.

Copy link
Member

Choose a reason for hiding this comment

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

@majornista oh, I see -- it's being selected with the sibling selector, so we can't use pseudo-elements. Perhaps, instead, we should be programmatically applying .is-focused to the outer .spectrum-Datepicker and using :focus-within (for futureproofing)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Only with additional javascript to check for .focus-ring className on a descendant element. And, we'd probably need an extra .focus-ring state, to distinguish between mouse a keyboard focus. With the added element, the style can be applied with pure CSS.

Copy link
Member

Choose a reason for hiding this comment

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

Got it, so we would need to know "is a child element keyboard focused?" in JavaScript, and a separate class for keyboard vs mouse focus. @GarthDB thoughts on this? This is the first component that has anything like this.

Copy link
Member

Choose a reason for hiding this comment

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

I prefer pure CSS for accessibility things like keyboard focus. It would be preferable to implement it with the same strategy as all the others, but I'm not seeing an obvious way to do that.
We could add something to the focus-ring polyfill, but that would kind of defeat the point of a standards-based polyfill.
The focus-withing strategy would be nice, it just means we're adding another polyfill requirement to focus. What would you prefer @lazd?

Copy link
Member

Choose a reason for hiding this comment

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

Though I would prefer the polyfill, I don't want to hold up this PR. I agree with your sentiments and suppose I'm fine with the current approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it, so we would need to know "is a child element keyboard focused?" in JavaScript, and a separate class for keyboard vs mouse focus. @GarthDB thoughts on this? This is the first component that has anything like this.

The Rating component has a similar issue with how the focus outline is applied to the wrapper element. Devon was somewhat resistant to the approach of evaluating for descendant input with .focus-ring. The difference for the Datepicker is that text inputs show blue border for mouse focus and border with box-shadow for keyboard focus.

</div>

<p/>

<div aria-disabled="true" class="spectrum-InputGroup spectrum-Datepicker spectrum-Datepicker--range is-disabled" role="combobox" aria-expanded="false" aria-haspopup="dialog">
<input type="text" class="spectrum-Textfield spectrum-InputGroup-field spectrum-Datepicker-startField" placeholder="mm/dd/yyyy" name="start" value="" disabled>
<div class="spectrum-Datepicker--rangeDash"></div>
<input type="text" class="spectrum-Textfield spectrum-InputGroup-field spectrum-Datepicker-endField" placeholder="mm/dd/yyyy" name="end" value="" disabled>
<button type="button" class="spectrum-FieldButton" disabled tabindex="-1" aria-label="Calendar">
<svg class="spectrum-Icon spectrum-UIIcon-ChevronDownMedium spectrum-Dropdown-icon" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-ChevronDownMedium" />
</svg>
</button>
<!-- To render focus ring around entire input group when one of the inputs has keyboard focus, we need this: -->
<div class="spectrum-Datepicker-focusRing" role="presentation"></div>
</div>

<p/>

<div class="spectrum-InputGroup spectrum-Datepicker spectrum-Datepicker--range spectrum-Datepicker--datetimeRange" role="combobox" aria-expanded="false" aria-haspopup="dialog">
<input type="text" class="spectrum-Textfield spectrum-InputGroup-field spectrum-Datepicker-startField" placeholder="mm/dd/yyyy hh:mm a" name="start" value="">
<div class="spectrum-Datepicker--rangeDash"></div>
<input type="text" class="spectrum-Textfield spectrum-InputGroup-field spectrum-Datepicker-endField" placeholder="mm/dd/yyyy hh:mm a" name="end" value="">
<button type="button" class="spectrum-FieldButton" tabindex="-1" aria-expanded="false" aria-haspopup="dialog" aria-label="Calendar">
<svg class="spectrum-Icon spectrum-UIIcon-ChevronDownMedium spectrum-Dropdown-icon" focusable="false" aria-hidden="true">
<use xlink:href="#spectrum-css-icon-ChevronDownMedium" />
</svg>
</button>
<!-- To render focus ring around entire input group when one of the inputs has keyboard focus, we need this: -->
<div class="spectrum-Datepicker-focusRing" role="presentation"></div>
majornista marked this conversation as resolved.
Show resolved Hide resolved
</div>
94 changes: 94 additions & 0 deletions src/inputgroup/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,23 @@
/* topdoc
{{ inputgroup/datepicker-quiet.yml }}
*/
/* topdoc
{{ inputgroup/datepicker-range.yml }}
*/
/* topdoc
{{ inputgroup/datepicker-range-quiet.yml }}
*/

:root {
/* Todo: move to DNA */
--spectrum-combobox-quiet-fieldbutton-border-radius: 0;
--spectrum-combobox-field-border-width-right: 0;
--spectrum-combobox-quiet-fieldbutton-padding-right: 0;
--spectrum-datepicker-input-width: calc(var(--spectrum-global-dimension-size-1600) - 2 * var(--spectrum-padding));
--spectrum-datepicker-datetime-input-width: calc(var(--spectrum-datepicker-input-width) + var(--spectrum-global-dimension-size-700) - var(--spectrum-global-dimension-static-font-size-100) / 2);
--spectrum-datepicker-range-dash-margin-left: calc(-0.5 * var(--spectrum-global-dimension-static-font-size-100));
--spectrum-datepicker-range-dash-padding-top: 0;
--spectrum-datepicker-range-dash-line-height: calc(var(--spectrum-textfield-height) - var(--spectrum-global-dimension-size-100));
}

.spectrum-InputGroup {
Expand All @@ -26,6 +37,7 @@
flex-direction: row;
flex-wrap: nowrap;
min-width: var(--spectrum-component-single-line-width);
border-radius: var(--spectrum-border-radius);

.spectrum-FieldButton {
padding: 0 var(--spectrum-dropdown-padding-x);
Expand All @@ -42,6 +54,7 @@
}

.spectrum-InputGroup--quiet {
border-radius: var(--spectrum-combobox-quiet-fieldbutton-border-radius);
.spectrum-FieldButton {
border-radius: var(--spectrum-combobox-quiet-fieldbutton-border-radius);

Expand All @@ -63,3 +76,84 @@
right: 0;
}
}

.spectrum-Datepicker--range {
border-radius: var(--spectrum-border-radius);
/* Input Group */
&.spectrum-InputGroup--quiet {
border-radius: var(--spectrum-combobox-quiet-fieldbutton-border-radius);
.spectrum-FieldButton {
border-radius: var(--spectrum-combobox-quiet-fieldbutton-border-radius);
}
}
/** Datetime Range **/
&.spectrum-Datepicker--datetimeRange {
/* Inputs */
.spectrum-InputGroup-field {
width: var(--spectrum-datepicker-datetime-input-width);
min-width: var(--spectrum-datepicker-datetime-input-width);
}
}
/* Inputs */
.spectrum-InputGroup-field {
width: var(--spectrum-datepicker-input-width);
min-width: var(--spectrum-datepicker-input-width);
flex: initial;
&.spectrum-Datepicker-startField {
border-right: 0;
padding-right: var(--spectrum-padding);
&.is-invalid,
&:invalid {
background-image: none;
padding-right: var(--spectrum-padding);
}
}
&.spectrum-Datepicker-endField {
border-left: 0;
border-radius: 0;
padding-left: var(--spectrum-padding);
}
}
/* Em dash */
.spectrum-Datepicker--rangeDash {
line-height: var(--spectrum-datepicker-range-dash-line-height);
padding-top: var(--spectrum-datepicker-range-dash-padding-top);
flex: initial;
width: 0;
z-index: 1;
&:before {
content: '—';
display: inline-block;
margin: 0 var(--spectrum-datepicker-range-dash-margin-left);
overflow: hidden;
text-align: center;
vertical-align: middle;
width: var(--spectrum-global-dimension-static-font-size-100);
}
}
/* Focus ring */
&.is-focused {
.spectrum-Datepicker-focusRing {
position: absolute;
border-radius: var(--spectrum-border-radius);
top: 0;
right: 0;
bottom: 0;
left: 0;
pointer-events: none;
}
}
&.spectrum-InputGroup--quiet {
&.is-focused {
.spectrum-Datepicker-focusRing {
border-radius: var(--spectrum-combobox-quiet-fieldbutton-border-radius);
top: auto;
}
}
.spectrum-Datepicker--rangeDash {
&:before {
margin-left: var(--spectrum-datepicker-range-dash-margin-left);
}
}
}
}
106 changes: 99 additions & 7 deletions src/inputgroup/skin.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
.spectrum-InputGroup {
&.is-focused {
&:not(.is-invalid) {
.spectrum-InputGroup-field:not(:disabled):not(.is-invalid) {
border-color: var(--spectrum-textfield-border-color-key-focus);
~ .spectrum-FieldButton {
border-color: var(--spectrum-textfield-border-color-key-focus);
}
}
}
}
&:hover {
.spectrum-InputGroup-field:not(:disabled):not(.is-invalid):not(:focus) {
&,
& ~ .spectrum-FieldButton {
&:not(.is-invalid):not(.is-focused) {
.spectrum-InputGroup-field:not(:disabled):not(.is-invalid) {
border-color: var(--spectrum-textfield-border-color-hover);
~ .spectrum-FieldButton {
border-color: var(--spectrum-textfield-border-color-hover);
}
&:focus {
border-color: var(--spectrum-textfield-border-color-key-focus);
~ .spectrum-FieldButton {
border-color: var(--spectrum-textfield-border-color-key-focus);
}
}
}
}
}
Expand Down Expand Up @@ -51,10 +69,9 @@
}
}

&:hover {
&:hover:not(.is-invalid) {
.spectrum-InputGroup-field:not(:disabled):not(.is-invalid):not(:focus) {
&,
& ~ .spectrum-FieldButton {
~ .spectrum-FieldButton {
border-color: var(--spectrum-textfield-quiet-border-color-hover);
}
}
Expand All @@ -63,7 +80,6 @@
.spectrum-InputGroup-field {
&.is-invalid,
&:invalid {
&,
~ .spectrum-FieldButton {
border-color: var(--spectrum-textfield-border-color-error);
}
Expand All @@ -86,3 +102,79 @@
}
}
}

.spectrum-Datepicker--range {
.spectrum-InputGroup-field {
&:focus-ring {
box-shadow: none !important;
}
&[disabled] {
~ .spectrum-Datepicker--rangeDash {
color: var(--spectrum-textfield-text-color-disabled);
}
}
}

/* Focus ring: When one of the inputs or the button has keyboard focus, render the focus ring border around the entire input group by styling an adjacent descendant element. */
:focus-ring {
majornista marked this conversation as resolved.
Show resolved Hide resolved
~ .spectrum-Datepicker-focusRing {
box-shadow: 0 0 0 1px var(--spectrum-dropdown-border-color-key-focus);
}
&:invalid,
&.is-invalid {
~ .spectrum-FieldButton {
box-shadow: 0 0 0 1px var(--spectrum-dropdown-border-color-error);
}
~ .spectrum-Datepicker-focusRing {
box-shadow: 0 0 0 1px var(--spectrum-dropdown-border-color-error);
}
}
}

&.is-invalid {
.spectrum-InputGroup-field {
border-color: var(--spectrum-dropdown-border-color-error) !important;
}

/* Focus ring: When one of the inputs or the button has keyboard focus, render the focus ring border around the entire input group by styling an adjacent descendant element. */
:focus-ring {
majornista marked this conversation as resolved.
Show resolved Hide resolved
~ .spectrum-Datepicker-focusRing {
box-shadow: 0 0 0 1px var(--spectrum-dropdown-border-color-error);
}
~ .spectrum-FieldButton {
border-color: var(--spectrum-dropdown-border-color-error);
box-shadow: 0 0 0 1px var(--spectrum-dropdown-border-color-error);
}
}
.spectrum-FieldButton {
border-color: var(--spectrum-dropdown-border-color-error);
&.is-invalid {
&:focus-ring {
border-color: var(--spectrum-dropdown-border-color-error);
box-shadow: 0 0 0 1px var(--spectrum-dropdown-border-color-error);
}
}
}
}
&.spectrum-InputGroup--quiet {
&.is-focused {
.spectrum-Datepicker-focusRing {
box-shadow: 0 0 0 1px var(--spectrum-dropdown-border-color-key-focus);
}
&.is-invalid {
.spectrum-FieldButton {
box-shadow: none;
border-color: var(--spectrum-dropdown-border-color-error);
&.is-invalid {
&:focus-ring {
box-shadow: 0 2px 0 0 var(--spectrum-dropdown-border-color-error);
}
}
}
.spectrum-Datepicker-focusRing {
box-shadow: 0 0 0 1px var(--spectrum-dropdown-border-color-error);
}
}
}
}
}
Loading