Skip to content

Commit da1d1ca

Browse files
mmalerbajelbourn
authored andcommitted
fix(datepicker): use 3 rows to display months of year (consistent with internal mocks) (#5427)
fixes #5202
1 parent ed2ece9 commit da1d1ca

File tree

7 files changed

+43
-24
lines changed

7 files changed

+43
-24
lines changed

src/lib/datepicker/calendar-body.html

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,28 @@
33
aria-hidden because we don't want it to be read out as one of the weeks in the month.
44
-->
55
<tr *ngIf="_firstRowOffset < labelMinRequiredCells" aria-hidden="true">
6-
<td class="mat-calendar-body-label" [attr.colspan]="numCols" >{{label}}</td>
6+
<td class="mat-calendar-body-label"
7+
[attr.colspan]="numCols"
8+
[style.paddingTop.%]="50 * cellAspectRatio / numCols"
9+
[style.paddingBottom.%]="50 * cellAspectRatio / numCols">
10+
{{label}}
11+
</td>
712
</tr>
813

914
<!-- Create the first row separately so we can include a special spacer cell. -->
1015
<tr *ngFor="let row of rows; let rowIndex = index" role="row">
1116
<!--
1217
We mark this cell as aria-hidden so it doesn't get read out as one of the days in the week.
18+
The aspect ratio of the table cells is maintained by setting the top and bottom padding as a
19+
percentage of the width (a variant of the trick described here:
20+
https://www.w3schools.com/howto/howto_css_aspect_ratio.asp).
1321
-->
1422
<td *ngIf="rowIndex === 0 && _firstRowOffset"
1523
aria-hidden="true"
1624
class="mat-calendar-body-label"
17-
[attr.colspan]="_firstRowOffset">
25+
[attr.colspan]="_firstRowOffset"
26+
[style.paddingTop.%]="50 * cellAspectRatio / numCols"
27+
[style.paddingBottom.%]="50 * cellAspectRatio / numCols">
1828
{{_firstRowOffset >= labelMinRequiredCells ? label : ''}}
1929
</td>
2030
<td *ngFor="let item of row; let colIndex = index"
@@ -25,7 +35,10 @@
2535
[class.mat-calendar-body-active]="_isActiveCell(rowIndex, colIndex)"
2636
[attr.aria-label]="item.ariaLabel"
2737
[attr.aria-disabled]="!item.enabled || null"
28-
(click)="_cellClicked(item)">
38+
(click)="_cellClicked(item)"
39+
[style.width.%]="100 / numCols"
40+
[style.paddingTop.%]="50 * cellAspectRatio / numCols"
41+
[style.paddingBottom.%]="50 * cellAspectRatio / numCols">
2942
<div class="mat-calendar-body-cell-content"
3043
[class.mat-calendar-body-selected]="selectedValue === item.value"
3144
[class.mat-calendar-body-today]="todayValue === item.value">

src/lib/datepicker/calendar-body.scss

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
$mat-calendar-body-label-padding-start: 5% !default;
2-
$mat-calendar-body-label-translation: -6px !default;
2+
// We don't want the label to jump around when we switch between month and year views, so we use
3+
// the same amount of padding regardless of the number of columns. We align the header label with
4+
// the one third mark of the first cell, this was chosen somewhat arbitrarily to make it look
5+
// roughly like the mock. Half way is too far since the cell text is center aligned.
6+
$mat-calendar-body-label-side-padding: 33% / 7 !default;
37
$mat-calendar-body-cell-min-size: 32px !default;
4-
$mat-calendar-body-cell-size: 100% / 7 !default;
58
$mat-calendar-body-cell-content-margin: 5% !default;
69
$mat-calendar-body-cell-content-border-width: 1px !default;
710

811
$mat-calendar-body-min-size: 7 * $mat-calendar-body-cell-min-size !default;
9-
$mat-calendar-body-cell-padding: $mat-calendar-body-cell-size / 2 !default;
1012
$mat-calendar-body-cell-content-size: 100% - $mat-calendar-body-cell-content-margin * 2 !default;
1113

1214

@@ -15,20 +17,17 @@ $mat-calendar-body-cell-content-size: 100% - $mat-calendar-body-cell-content-mar
1517
}
1618

1719
.mat-calendar-body-label {
18-
padding: $mat-calendar-body-cell-padding 0
19-
$mat-calendar-body-cell-padding $mat-calendar-body-cell-padding;
2020
height: 0;
2121
line-height: 0;
22-
transform: translateX($mat-calendar-body-label-translation);
2322
text-align: left;
23+
padding-left: $mat-calendar-body-label-side-padding;
24+
padding-right: $mat-calendar-body-label-side-padding;
2425
}
2526

2627
.mat-calendar-body-cell {
2728
position: relative;
28-
width: $mat-calendar-body-cell-size;
2929
height: 0;
3030
line-height: 0;
31-
padding: $mat-calendar-body-cell-padding 0;
3231
text-align: center;
3332
outline: none;
3433
cursor: pointer;
@@ -53,13 +52,13 @@ $mat-calendar-body-cell-content-size: 100% - $mat-calendar-body-cell-content-mar
5352

5453
border-width: $mat-calendar-body-cell-content-border-width;
5554
border-style: solid;
56-
border-radius: 50%;
55+
56+
// Choosing a value clearly larger than the height ensures we get the correct capsule shape.
57+
border-radius: 999px;
5758
}
5859

5960
[dir='rtl'] {
6061
.mat-calendar-body-label {
61-
padding: 0 $mat-calendar-body-cell-padding 0 0;
62-
transform: translateX(-$mat-calendar-body-label-translation);
6362
text-align: right;
6463
}
6564
}

src/lib/datepicker/calendar-body.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ export class MdCalendarBody {
6868
/** The cell number of the active cell in the table. */
6969
@Input() activeCell = 0;
7070

71+
/**
72+
* The aspect ratio (width / height) to use for the cells in the table. This aspect ratio will be
73+
* maintained even as the table resizes.
74+
*/
75+
@Input() cellAspectRatio = 1;
76+
7177
/** Emits when a new value is selected. */
7278
@Output() selectedValueChange = new EventEmitter<number>();
7379

src/lib/datepicker/calendar.scss

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
$mat-calendar-padding: 8px !default;
22
$mat-calendar-header-divider-width: 1px !default;
33
$mat-calendar-controls-vertical-padding: 5%;
4-
// We want to indent to the middle of the first tile. There are 7 tiles, so 100% / 7 / 2.
5-
// Then we back up a little bit since the text in the cells is center-aligned.
6-
$mat-calendar-controls-start-padding: calc(100% / 14 - 22px);
7-
// Same as above, but on other side for arrows.
8-
$mat-calendar-controls-end-padding: calc(100% / 14 - 22px);
4+
// We use the same padding as the month / year label, but subtract 16px since there is padding
5+
// between the edge of the button and the text. This ensures that the button text lines up with
6+
// the month / year label text.
7+
$mat-calendar-controls-side-margin: calc(33% / 7 - 16px);
8+
99
$mat-calendar-arrow-size: 5px !default;
1010
$mat-calendar-arrow-disabled-opacity: 0.5 !default;
1111

@@ -32,8 +32,7 @@ $mat-calendar-next-icon-transform: translateX(-2px) rotate(45deg);
3232

3333
.mat-calendar-controls {
3434
display: flex;
35-
padding: $mat-calendar-controls-vertical-padding $mat-calendar-controls-end-padding
36-
$mat-calendar-controls-vertical-padding $mat-calendar-controls-start-padding;
35+
margin: $mat-calendar-controls-vertical-padding $mat-calendar-controls-side-margin;
3736
}
3837

3938
.mat-calendar-spacer {

src/lib/datepicker/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import {NgModule} from '@angular/core';
1010
import {MdMonthView} from './month-view';
1111
import {CommonModule} from '@angular/common';
12-
import {StyleModule, OverlayModule, A11yModule} from '../core';
12+
import {A11yModule, OverlayModule, StyleModule} from '../core';
1313
import {MdCalendarBody} from './calendar-body';
1414
import {MdYearView} from './year-view';
1515
import {MdDatepicker, MdDatepickerContent} from './datepicker';

src/lib/datepicker/year-view.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<table class="mat-calendar-table">
22
<thead class="mat-calendar-table-header">
3-
<tr><th class="mat-calendar-table-header-divider" colspan="7"></th></tr>
3+
<tr><th class="mat-calendar-table-header-divider" colspan="4"></th></tr>
44
</thead>
55
<tbody md-calendar-body
66
role="grid"
@@ -10,6 +10,8 @@
1010
[todayValue]="_todayMonth"
1111
[selectedValue]="_selectedMonth"
1212
[labelMinRequiredCells]="2"
13+
[numCols]="4"
14+
[cellAspectRatio]="4 / 7"
1315
[activeCell]="_dateAdapter.getMonth(activeDate)"
1416
(selectedValueChange)="_monthSelected($event)">
1517
</tbody>

src/lib/datepicker/year-view.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export class MdYearView<D> implements AfterContentInit {
108108

109109
let monthNames = this._dateAdapter.getMonthNames('short');
110110
// First row of months only contains 5 elements so we can fit the year label on the same row.
111-
this._months = [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10, 11]].map(row => row.map(
111+
this._months = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]].map(row => row.map(
112112
month => this._createCellForMonth(month, monthNames[month])));
113113
}
114114

0 commit comments

Comments
 (0)