Skip to content

Commit ae5011f

Browse files
Make calendar tabbable
1 parent 0f70036 commit ae5011f

File tree

3 files changed

+98
-81
lines changed

3 files changed

+98
-81
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Changelog
22

33
## Next
4-
- Use `rem` for sizing the `DatePicker`
5-
- Make the `DatePicker` slightly larger
4+
- Use `rem` for sizing the DatePicker
5+
- Make the DatePicker slightly larger
6+
- Make the calendar tabbable
67
- Fix styling issue for languages with long month names
78

89
## 1.3.0 - 2021 Jan 4

src/lib/DatePicker.svelte

Lines changed: 90 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@
137137
e.preventDefault()
138138
}
139139
function keydown(e: KeyboardEvent) {
140+
if ((e.target as HTMLElement)?.tagName === 'SELECT') {
141+
return
142+
}
143+
140144
if (e.key === 'ArrowUp') {
141145
updateValue((value) => {
142146
value.setDate(value.getDate() - 7)
@@ -164,94 +168,95 @@
164168
}
165169
</script>
166170

167-
<div class="date-time-picker" on:focusout tabindex="-1" on:keydown|self={keydown}>
168-
<div class="top">
169-
<div class="page-button" tabindex="-1" on:click={() => setMonth(month - 1)}>
170-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
171-
><path
172-
d="M5 3l3.057-3 11.943 12-11.943 12-3.057-3 9-9z"
173-
transform="rotate(180, 12, 12)"
174-
/></svg
175-
>
171+
<div class="date-time-picker" on:focusout tabindex="0" on:keydown={keydown}>
172+
<div class="tab-container" tabindex="-1">
173+
<div class="top">
174+
<div class="page-button" tabindex="-1" on:click={() => setMonth(month - 1)}>
175+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
176+
><path
177+
d="M5 3l3.057-3 11.943 12-11.943 12-3.057-3 9-9z"
178+
transform="rotate(180, 12, 12)"
179+
/></svg
180+
>
181+
</div>
182+
<div class="dropdown month">
183+
<select bind:value={month} on:keydown={monthKeydown}>
184+
{#each iLocale.months as monthName, i}
185+
<option
186+
disabled={new Date(year, i, getMonthLength(year, i), 23, 59, 59, 999) < min ||
187+
new Date(year, i) > max}
188+
value={i}>{monthName}</option
189+
>
190+
{/each}
191+
</select>
192+
<!--
193+
Here we have use `select.dummy-select` for showing just the <select> button. This
194+
is to style the <select> button without affecting the menu popup
195+
- `option { color: initial }` causes invisible menu in dark mode on Firefox
196+
- `option { color: initial; background-color: initial }` causes invisible menu in Chrome
197+
- `select { background-color: $bg; color: $text }` causes white scrollbar in dark mode on Firefox
198+
-->
199+
<select class="dummy-select" tabindex="-1">
200+
{#each iLocale.months as monthName, i}
201+
<option value={i} selected={i === month}>{monthName}</option>
202+
{/each}
203+
</select>
204+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
205+
><path d="M6 0l12 12-12 12z" transform="rotate(90, 12, 12)" /></svg
206+
>
207+
</div>
208+
<div class="dropdown year">
209+
<select bind:value={year} on:keydown={yearKeydown}>
210+
{#each years as v}
211+
<option value={v}>{v}</option>
212+
{/each}
213+
</select>
214+
<!-- style <select> button without affecting menu popup -->
215+
<select class="dummy-select" tabindex="-1">
216+
{#each years as v}
217+
<option value={v} selected={v === year}>{v}</option>
218+
{/each}
219+
</select>
220+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
221+
><path d="M6 0l12 12-12 12z" transform="rotate(90, 12, 12)" /></svg
222+
>
223+
</div>
224+
<div class="page-button" tabindex="-1" on:click={() => setMonth(month + 1)}>
225+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
226+
><path d="M5 3l3.057-3 11.943 12-11.943 12-3.057-3 9-9z" /></svg
227+
>
228+
</div>
176229
</div>
177-
<div class="dropdown month">
178-
<select bind:value={month} on:keydown={monthKeydown}>
179-
{#each iLocale.months as monthName, i}
180-
<option
181-
disabled={new Date(year, i, getMonthLength(year, i), 23, 59, 59, 999) < min ||
182-
new Date(year, i) > max}
183-
value={i}>{monthName}</option
184-
>
185-
{/each}
186-
</select>
187-
<!--
188-
Here we have use `select.dummy-select` for showing just the <select> button. This
189-
is to style the <select> button without affecting the menu popup
190-
- `option { color: initial }` causes invisible menu in dark mode on Firefox
191-
- `option { color: initial; background-color: initial }` causes invisible menu in Chrome
192-
- `select { background-color: $bg; color: $text }` causes white scrollbar in dark mode on Firefox
193-
-->
194-
<select class="dummy-select" tabindex="-1">
195-
{#each iLocale.months as monthName, i}
196-
<option value={i} selected={i === month}>{monthName}</option>
197-
{/each}
198-
</select>
199-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
200-
><path d="M6 0l12 12-12 12z" transform="rotate(90, 12, 12)" /></svg
201-
>
230+
<div class="header">
231+
{#each Array(7) as _, i}
232+
{#if i + iLocale.weekStartsOn < 7}
233+
<div class="header-cell">{iLocale.weekdays[iLocale.weekStartsOn + i]}</div>
234+
{:else}
235+
<div class="header-cell">{iLocale.weekdays[iLocale.weekStartsOn + i - 7]}</div>
236+
{/if}
237+
{/each}
202238
</div>
203-
<div class="dropdown year">
204-
<select bind:value={year} on:keydown={yearKeydown}>
205-
{#each years as v}
206-
<option value={v}>{v}</option>
207-
{/each}
208-
</select>
209-
<!-- style <select> button without affecting menu popup -->
210-
<select class="dummy-select" tabindex="-1">
211-
{#each years as v}
212-
<option value={v} selected={v === year}>{v}</option>
239+
{#each Array(6) as _, weekIndex}
240+
<div class="week">
241+
{#each calendarDays.slice(weekIndex * 7, weekIndex * 7 + 7) as calendarDay}
242+
<div
243+
class="cell"
244+
on:click={() => selectDay(calendarDay)}
245+
class:disabled={!dayIsInRange(calendarDay, min, max)}
246+
class:selected={calendarDay.month === month && calendarDay.number === dayOfMonth}
247+
class:other-month={calendarDay.month !== month}
248+
>
249+
<span>{calendarDay.number}</span>
250+
</div>
213251
{/each}
214-
</select>
215-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
216-
><path d="M6 0l12 12-12 12z" transform="rotate(90, 12, 12)" /></svg
217-
>
218-
</div>
219-
<div class="page-button" tabindex="-1" on:click={() => setMonth(month + 1)}>
220-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
221-
><path d="M5 3l3.057-3 11.943 12-11.943 12-3.057-3 9-9z" /></svg
222-
>
223-
</div>
224-
</div>
225-
<div class="header">
226-
{#each Array(7) as _, i}
227-
{#if i + iLocale.weekStartsOn < 7}
228-
<div class="header-cell">{iLocale.weekdays[iLocale.weekStartsOn + i]}</div>
229-
{:else}
230-
<div class="header-cell">{iLocale.weekdays[iLocale.weekStartsOn + i - 7]}</div>
231-
{/if}
252+
</div>
232253
{/each}
233254
</div>
234-
{#each Array(6) as _, weekIndex}
235-
<div class="week">
236-
{#each calendarDays.slice(weekIndex * 7, weekIndex * 7 + 7) as calendarDay}
237-
<div
238-
class="cell"
239-
on:click={() => selectDay(calendarDay)}
240-
class:disabled={!dayIsInRange(calendarDay, min, max)}
241-
class:selected={calendarDay.month === month && calendarDay.number === dayOfMonth}
242-
class:other-month={calendarDay.month !== month}
243-
>
244-
<span>{calendarDay.number}</span>
245-
</div>
246-
{/each}
247-
</div>
248-
{/each}
249255
</div>
250256

251257
<style lang="sass">
252258
.date-time-picker
253259
display: inline-block
254-
outline: none
255260
color: var(--date-picker-foreground, #000000)
256261
background: var(--date-picker-background, #ffffff)
257262
user-select: none
@@ -262,6 +267,13 @@
262267
border: 1px solid rgba(103, 113, 137, 0.3)
263268
border-radius: 3px
264269
box-shadow: 0px 2px 6px rgba(#000000,0.08), 0px 2px 6px rgba(#000000,0.11)
270+
outline: none
271+
transition: all 80ms cubic-bezier(0.4, 0.0, 0.2, 1)
272+
&:focus-visible
273+
border-color: var(--date-picker-highlight-border, #0269f7)
274+
box-shadow: 0px 0px 0px 2px var(--date-picker-highlight-shadow, rgba(#0269f7, 0.4))
275+
.tab-container
276+
outline: none
265277
.top
266278
display: flex
267279
justify-content: center

src/routes/_prop.svelte

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323
{:else if typeof value === 'boolean'}
2424
<input type="checkbox" bind:checked={value} />
2525
{:else if value instanceof Date}
26-
<DateInput bind:value />
26+
<DateInput
27+
bind:value
28+
min={new Date(new Date().getFullYear() - 20, 0)}
29+
max={new Date(new Date().getFullYear() + 5, 0)}
30+
/>
2731
{:else if value instanceof Object}
2832
<textarea type="text" bind:value={jsonValue} on:input={jsonInput} />
2933
{:else}

0 commit comments

Comments
 (0)