Skip to content
2 changes: 0 additions & 2 deletions packages/calcite-components/src/components/action/action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,6 @@ export class Action extends LitElement implements InteractiveComponent {
disabled={disabled}
id={buttonId}
ref={this.buttonEl}
// tabIndex is required for the button to be focusable on click in safari.
tabIndex={disabled ? null : 0}
>
{buttonContent}
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,9 @@
max-inline-size: 1212px;
}

// prevents focus ring from showing when Shift key press succeed click on non-interactive area
.container {
@apply outline-none;
}

@include base-component();
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ declare global {
export class DatePicker extends LitElement {
//#region Static Members

static override shadowRootOptions = { mode: "open" as const, delegatesFocus: true };

Copy link
Copy Markdown
Contributor Author

@anveshmekala anveshmekala May 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delegatesFocus is causing issue in Safari to focus the first focusable element while clicking on non-interactive areas. date-picker-month-header/date-picker-month didn't enabled delegatesFocus, hence the focus shifts on to body element which is inconsistent with Chrome.

Tested alternate solution of adding delegatesFocus onto date-picker-header & date-picker-header-month which resolves the bug & enables focusing disabled chevrons (which is a common use case with min/max props). Additionally, stray clicks could focus day's similar to #6462.

Proposing to remove delegatesFocus here & users can leverage setFocus( ) method instead of focus( ). This isn't a BREAKING CHANGE because datePicker.focus( ) is not working as expected in date-picker since the start (https://codepen.io/anvesh-mekala/pen/XJJoKzQ goes back to 2.12.1 version).

Copy link
Copy Markdown
Member

@jcfranco jcfranco May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great breakdown. One more note, the recommended and supported way to focus our elements is to use setFocus and not focus.

Also, can you also double-check that blur and focus events occur as expected on date-picker? IIRC, delegatesFocus affects this in some cases. If so, this might be considered breaking.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing delegatestFocus did invoke blur( ) when user clicks on the non-interactive areas of date-picker. To counter this, we need to add a wrapper container in date-picker which renders descendant elements with shadowDOM and delegatesFocus='false'.

When delegatesFocus is enabled, any clicks on non-interactive areas should focus the first focusable element as per spec .In date-picker case descendants of date-picker didn't enabled delegatesFocus and safari is invoking a blur event.

Did some digging into HTML spec for delegatesFocus and it doesn't completely answer the use-case we have here with deep nested shadow child elements without delegatesFocus to understand if the issue is browser related as it fails only in Safari. One comment did catch the eye which outlines the proposed spec & click( ) behavior has some leeway due to implementation differences and dependency on User Agent definition of click focusable element .

After some 🕵️‍♂️ & discussions, adding a wrapper container in date-picker would help resolve this issue to register the boundaries of descendants in date-picker. Though this solution doesn't depend on delegatesFocus, the root cause is related to delegatesFocus specification of clicking non-interactive areas with descendants delegatesFocus set to false in Safari.

We could always add delegatesFocus on to descendant elements and it will resolve the current issue. Additionally, any click on non-interactive area will shift the focus to the closest element hence causing a focus shift which can hard to reason for end-user.

static override styles = styles;

//#endregion
Expand Down Expand Up @@ -625,7 +623,13 @@ export class DatePicker extends LitElement {

const startCalendarActiveDate = this.range ? this.activeStartDate : activeDate;

return <>{this.renderMonth(startCalendarActiveDate, this.maxAsDate, minDate, date, endDate)}</>;
return (
<>
<div ariaHidden={true} class="container" tabIndex={-1}>
{this.renderMonth(startCalendarActiveDate, this.maxAsDate, minDate, date, endDate)}
</div>
</>
);
}

/**
Expand Down
Loading