-
Notifications
You must be signed in to change notification settings - Fork 6
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
Add a customizable, slottable day component for calendars #745
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { Component, Element, h, JSX, State } from '@stencil/core'; | ||
import { Component, Element, h, JSX, Listen, State } from '@stencil/core'; | ||
import { IWeekElement, GuxCalendarDayOfWeek } from '../../gux-calendar.types'; | ||
import { asIsoDate, fromIsoDate } from '@utils/date/iso-dates'; | ||
import { | ||
|
@@ -32,6 +32,13 @@ export class GuxCalendar { | |
@State() | ||
private maxValue: Date; | ||
|
||
@Listen('guxdayselected') | ||
onDaySelected(event: CustomEvent<string>) { | ||
const selectedDate = fromIsoDate(event.detail); | ||
this.selectDate(selectedDate); | ||
event.stopPropagation(); | ||
} | ||
|
||
private locale: string = 'en'; | ||
|
||
private i18n: GetI18nValue; | ||
|
@@ -85,7 +92,7 @@ export class GuxCalendar { | |
} | ||
} | ||
|
||
private onDateClick(date: Date): void { | ||
private selectDate(date: Date): void { | ||
if (this.isInvalidDate(date)) { | ||
return; | ||
} | ||
|
@@ -116,21 +123,24 @@ export class GuxCalendar { | |
* Focus the focused date | ||
*/ | ||
private focusDate() { | ||
const target: HTMLTableCellElement = this.root.shadowRoot.querySelector( | ||
`.gux-content-date[data-date="${this.focusedValue.getTime()}"]` | ||
); | ||
const isoDateStr = asIsoDate(this.focusedValue); | ||
// Find the rendered element for the slot for the focused date | ||
const target: HTMLElement = this.root.shadowRoot | ||
.querySelector<HTMLSlotElement>(`slot[name="${isoDateStr}"]`) | ||
.assignedNodes({ flatten: true })[0] as HTMLElement; | ||
if (target) { | ||
target.focus(); | ||
} | ||
} | ||
|
||
private onKeyDown(event: KeyboardEvent): void { | ||
console.log('KEYDOWN', event.key); | ||
switch (event.key) { | ||
case ' ': | ||
break; | ||
case 'Enter': | ||
event.preventDefault(); | ||
this.onDateClick(this.getFocusedValue()); | ||
this.selectDate(this.getFocusedValue()); | ||
afterNextRenderTimeout(() => { | ||
this.focusDate(); | ||
}); | ||
|
@@ -302,7 +312,7 @@ export class GuxCalendar { | |
|
||
private renderContent(): JSX.Element { | ||
return ( | ||
<div> | ||
<div onKeyDown={e => void this.onKeyDown(e)}> | ||
<div class="gux-week-days"> | ||
{getWeekdays(this.locale, this.startDayOfWeek).map( | ||
day => (<div class="gux-week-day">{day}</div>) as JSX.Element | ||
|
@@ -314,37 +324,22 @@ export class GuxCalendar { | |
week => | ||
( | ||
<div class="gux-content-week"> | ||
{week.dates.map( | ||
day => | ||
( | ||
<div | ||
data-date={day.date.getTime()} | ||
onClick={() => this.onDateClick(day.date)} | ||
role="button" | ||
{week.dates.map(day => { | ||
const isoDateStr = asIsoDate(day.date); | ||
return ( | ||
<slot key={isoDateStr} name={isoDateStr}> | ||
<gux-day | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it should be, it's a JSX/Stencil feature, not a native one: https://stenciljs.com/docs/templating-jsx#dealing-with-children. We don't do a lot of removing/rearranging dates in the calendar, but I try to always add a |
||
day={isoDateStr} | ||
aria-current={day.selected ? 'true' : 'false'} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure if the |
||
tabindex={day.selected || day.focused ? '0' : '-1'} | ||
onKeyDown={e => void this.onKeyDown(e)} | ||
aria-disabled={day.disabled ? 'true' : 'false'} | ||
tabindex={day.selected || day.focused ? '0' : '-1'} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If a developer slots their own |
||
class={{ | ||
'gux-content-date': true, | ||
'gux-disabled': day.disabled, | ||
'gux-current-month': day.inCurrentMonth, | ||
'gux-selected': day.selected, | ||
'gux-current-date': day.isCurrentDate | ||
'gux-muted': !day.inCurrentMonth | ||
}} | ||
> | ||
<span class="gux-non-sr" aria-hidden="true"> | ||
{day.date.getDate()} | ||
</span> | ||
<span class="gux-sr-only"> | ||
<gux-date-beta | ||
datetime={day.date.toISOString()} | ||
format="long" | ||
></gux-date-beta> | ||
</span> | ||
</div> | ||
) as JSX.Element | ||
)} | ||
></gux-day> | ||
</slot> | ||
) as JSX.Element; | ||
})} | ||
</div> | ||
) as JSX.Element | ||
)} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor this can be removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will also look into why linting didn't catch this