Skip to content

Instantly share code, notes, and snippets.

@ilio
Last active July 19, 2018 21:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ilio/be3881457a52d04df1b497407fc0d2b8 to your computer and use it in GitHub Desktop.
Save ilio/be3881457a52d04df1b497407fc0d2b8 to your computer and use it in GitHub Desktop.
Material Design calendar range select. Result: https://jsfiddle.net/jsbot/cygtdLj3/13/
const Day = ({value, className})=> (
<div className={"day"+(className? ' ' + className: '')}>
<div className="selected" />
<div className="secondary" />
<div className="value">{value}</div>
</div>
);
class Calendar extends React.Component {
state = {
weekDays:[],
dates: []
}
getFirstDayOfWeek = () => {
if(Number.isInteger(this.props.firstDayOfWeek)){
return this.props.firstDayOfWeek;
}
return 0;
}
componentDidMount() {
const weekDayNames = ['S', 'M', 'T', 'W', 'T', 'F', 'S']
const weekDays = [];
for (let i = 0; i < 7; i++) {
weekDays.push({ id: i, name: weekDayNames[(i + this.getFirstDayOfWeek()) % 7] });
}
const dates = [];
for(let i=0; i< 50; i++) {
dates.push({id: i, name: i})
}
const classes = {
0: 'selected-first',
1: 'selected',
2: 'selected-last',
4: 'secondary-first',
5: 'secondary-last',
6: 'secondary-first',
7: 'secondary-last',
8: 'selected-first',
9: 'selected secondary-first',
10: 'selected-last secondary',
11: 'secondary-last',
12: 'selected-first',
13: 'selected',
14: 'selected-first secondary-last',
15: 'selected-first selected-last',
16: 'secondary-first secondary-last',
17: 'selected-last secondary-last',
18: 'selected-first secondary-first',
19: 'selected-first selected-last secondary-first secondary-last',
20: 'selected-last secondary-first',
21: 'today',
22: 'today selected-first selected-last secondary-first secondary-last',
23: 'today secondary-first secondary-last',
}
this.setState({weekDays, dates, classes});
}
render(){
return (
<div className="calendar">
{this.state.weekDays.map(weekDay => {
return <Day key={weekDay.id} value={weekDay.name} className="dayName"/>
})}
{this.state.dates.map(weekDay => {
return <Day key={weekDay.id} value={weekDay.name} className={this.state.classes[weekDay.id]}/>
})}
</div>
)
}
}
class App extends React.Component {
render() {
return (
<Calendar date={new Date()}/>
)
}
}
ReactDOM.render(<App />, document.querySelector("#app"))
$cellSize: 30;
$columnSpacing: 10;
$rowSpacing: 0;
$fontSize: 8px;
$selectedColor: rgba(0, 118, 255, 0.2);
$secondaryColor: #fce8b2;
$cellWidth: $cellSize + $columnSpacing;
$cellHeight: $cellSize;
$correction: ($cellWidth - $cellHeight) / 2;
.calendar {
display: inline-grid;
grid-template-columns: repeat(7, #{$cellWidth}px);
/*background-color: #ddd;*/
grid-row-gap: #{$rowSpacing}px;
align-items: stretch;
text-align: center;
font-family: Roboto, sans-serif;
font-size: $fontSize;
font-weight: 400;
-webkit-font-smoothing: antialiased;
.day {
/*background-color: magenta;*/
height: #{$cellHeight}px;
line-height: #{$cellHeight}px;
z-index: 0;
width: #{$cellHeight}px;
margin-left: auto;
margin-right: auto;
}
.day.selected .selected,
.day.selected-first .selected,
.day.selected-last .selected {
content: '';
background-color: $selectedColor;
width: #{$cellWidth}px;
height: #{$cellHeight}px;
display: block;
position: absolute;
z-index: -1;
/*opacity: .5;*/
}
.day.secondary .secondary,
.day.secondary-first .secondary,
.day.secondary-last .secondary {
content: '';
background-color: $secondaryColor;
width: #{$cellWidth}px;
height: #{$cellHeight}px;
display: block;
position: absolute;
z-index: -2;
}
.day.selected .selected,
.day.secondary .secondary {
margin-left: #{-$correction}px;
}
.day.selected-first .selected,
.day.secondary-first .secondary {
border-top-left-radius: #{$cellHeight/2}px #{$cellHeight/2}px;
border-bottom-left-radius: #{$cellHeight/2}px #{$cellHeight/2}px;
width: #{$cellHeight+$correction}px;
margin-left: 0;
}
.day.selected-last .selected,
.day.secondary-last .secondary {
border-top-right-radius: #{$cellHeight/2}px #{$cellHeight/2}px;
border-bottom-right-radius: #{$cellHeight/2}px #{$cellHeight/2}px;
width: #{$cellHeight+$correction}px;
margin-left: #{-$correction}px;
}
.day.selected-first.selected-last .selected,
.day.secondary-first.secondary-last .secondary {
width: #{$cellHeight}px;
margin-left: 0;
}
.day.selected-first .value,
.day.selected-last .value {
border-radius: 50%;
background-color: #0076ff;
color: white
}
.day.today .value {
border-radius: 50%;
border: 1px solid black;
width: #{$cellHeight - 2}px;
height: #{$cellHeight - 2}px;
}
}
<div id="app"></div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment