Skip to content

Commit e3fd3e1

Browse files
committed
feat(datepicker): set up input for date range picker
Sets up the UI and most of the boilerplate that we'll need for the input that is associated with a date range picker. Doesn't include any interactions with the datepicker itself yet.
1 parent 2ce2dbc commit e3fd3e1

File tree

8 files changed

+429
-1
lines changed

8 files changed

+429
-1
lines changed

src/dev-app/datepicker/datepicker-demo.html

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,28 @@ <h2>Datepicker with custom header extending the default header</h2>
169169
<mat-datepicker #customHeaderNgContentPicker [calendarHeaderComponent]="customHeaderNgContent"></mat-datepicker>
170170
</mat-form-field>
171171
</p>
172+
173+
<h2>Range picker</h2>
174+
<p>
175+
<mat-form-field>
176+
<mat-label>Enter a date range</mat-label>
177+
<mat-date-range-input startPlaceholder="Start date" endPlaceholder="End date"></mat-date-range-input>
178+
<mat-datepicker-toggle matSuffix></mat-datepicker-toggle>
179+
</mat-form-field>
180+
</p>
181+
182+
<p>
183+
<mat-form-field appearance="fill">
184+
<mat-label>Enter a date range</mat-label>
185+
<mat-date-range-input startPlaceholder="Start date" endPlaceholder="End date"></mat-date-range-input>
186+
<mat-datepicker-toggle matSuffix></mat-datepicker-toggle>
187+
</mat-form-field>
188+
</p>
189+
190+
<p>
191+
<mat-form-field appearance="outline">
192+
<mat-label>Enter a date range</mat-label>
193+
<mat-date-range-input startPlaceholder="Start date" endPlaceholder="End date"></mat-date-range-input>
194+
<mat-datepicker-toggle matSuffix></mat-datepicker-toggle>
195+
</mat-form-field>
196+
</p>

src/material/datepicker/BUILD.bazel

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ ng_module(
1919
assets = [
2020
":datepicker-content.css",
2121
":datepicker-toggle.css",
22+
":date-range-input.css",
2223
":calendar-body.css",
2324
":calendar.css",
2425
] + glob(["**/*.html"]),
@@ -71,6 +72,12 @@ sass_binary(
7172
deps = ["//src/cdk/a11y:a11y_scss_lib"],
7273
)
7374

75+
sass_binary(
76+
name = "date_range_input_scss",
77+
src = "date-range-input.scss",
78+
deps = ["//src/material/core:core_scss_lib"],
79+
)
80+
7481
ng_test_library(
7582
name = "unit_test_sources",
7683
srcs = glob(
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<div
2+
class="mat-date-range-input-container"
3+
cdkMonitorSubtreeFocus
4+
(cdkFocusChange)="_handleFocusChange($event)">
5+
<div class="mat-date-range-input-start-wrapper">
6+
<input
7+
class="mat-date-range-input-inner"
8+
[placeholder]="startPlaceholder"
9+
[disabled]="disabled"
10+
[id]="id"
11+
[attr.aria-labelledby]="_ariaLabelledBy"
12+
[attr.aria-describedby]="_ariaDescribedBy"
13+
[attr.aria-required]="required || null"
14+
(input)="_noopInputHandler()"
15+
#start>
16+
<span
17+
class="mat-date-range-input-mirror"
18+
aria-hidden="true">{{_getInputMirrorValue(start)}}</span>
19+
</div>
20+
21+
<span class="mat-date-range-input-separator">{{separator}}</span>
22+
23+
<div class="mat-date-range-input-end-wrapper">
24+
<input
25+
class="mat-date-range-input-inner"
26+
[placeholder]="endPlaceholder"
27+
[disabled]="disabled"
28+
[attr.aria-labelledby]="_ariaLabelledBy"
29+
[attr.aria-describedby]="_ariaDescribedBy"
30+
[attr.aria-required]="required || null"
31+
#end>
32+
</div>
33+
</div>
34+
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
@import '../core/style/vendor-prefixes';
2+
3+
$mat-date-range-input-separator-spacing: 4px;
4+
$mat-date-range-input-part-max-width: calc(50% - #{$mat-date-range-input-separator-spacing});
5+
6+
// Host of the date range input.
7+
.mat-date-range-input {
8+
display: block;
9+
width: 100%;
10+
}
11+
12+
// Inner container that wraps around all the content.
13+
.mat-date-range-input-container {
14+
display: flex;
15+
align-items: center;
16+
}
17+
18+
// Text shown between the two inputs.
19+
.mat-date-range-input-separator {
20+
margin: 0 $mat-date-range-input-separator-spacing;
21+
}
22+
23+
// Underlying input inside the range input.
24+
.mat-date-range-input-inner {
25+
// Reset the input so it's just a transparent rectangle.
26+
font: inherit;
27+
background: transparent;
28+
color: currentColor;
29+
border: none;
30+
outline: none;
31+
padding: 0;
32+
margin: 0;
33+
vertical-align: bottom;
34+
text-align: inherit;
35+
-webkit-appearance: none;
36+
width: 100%;
37+
38+
// Remove IE's default clear and reveal icons.
39+
&::-ms-clear,
40+
&::-ms-reveal {
41+
display: none;
42+
}
43+
}
44+
45+
// We want the start input to be flush against the separator, no matter how much text it has, but
46+
// the problem is that inputs have a fixed width. We work around the issue by implementing an
47+
// auto-resizing input that stretches based on its text, up to a point. It works by having
48+
// a relatively-positioned wrapper (`.mat-date-range-input-start-wrapper` below) and an absolutely-
49+
// positioned `input`, as well as a `span` inside the wrapper which mirrors the input's value and
50+
// placeholder. As the user is typing, the value gets mirrored in the span which causes the wrapper
51+
// to stretch and the input with it.
52+
.mat-date-range-input-mirror {
53+
// Disable user selection so users don't accidentally copy the text via ctrl + A.
54+
@include user-select(none);
55+
56+
// Hide the element so it doesn't get read out by screen
57+
// readers and it doesn't show up behind the input.
58+
visibility: hidden;
59+
60+
// Text inside inputs never wraps so the one in the span shouldn't either.
61+
white-space: nowrap;
62+
display: inline-block;
63+
64+
// Prevent the container from collapsing. Make it more
65+
// than 1px so the input caret doesn't get clipped.
66+
min-width: 2px;
67+
}
68+
69+
// Wrapper around the start input. Used to facilitate the auto-resizing input.
70+
.mat-date-range-input-start-wrapper {
71+
position: relative;
72+
overflow: hidden;
73+
max-width: $mat-date-range-input-part-max-width;
74+
75+
input {
76+
position: absolute;
77+
top: 0;
78+
left: 0;
79+
}
80+
}
81+
82+
// Wrapper around the end input that makes sure that it has the proper size.
83+
.mat-date-range-input-end-wrapper {
84+
flex-grow: 1;
85+
max-width: $mat-date-range-input-part-max-width;
86+
}
87+
88+
.mat-form-field-type-mat-date-range-input .mat-form-field-infix {
89+
// Bump the default width slightly since it's somewhat cramped with two inputs and a separator.
90+
width: 200px;
91+
}

0 commit comments

Comments
 (0)