From 8796a1dd07e49362796301e3ac4f04e8d89850e4 Mon Sep 17 00:00:00 2001 From: tolgaucar Date: Fri, 17 Oct 2025 14:43:51 +0300 Subject: [PATCH 1/4] fix(calendar): enable custom day renderer tooltips on disabled dates - Fix disabled date tooltip bug where custom day renderers with interactive elements (e.g., tooltips) didn't work on disabled dates - Add special container for disabled dates with custom renderers to allow pointer events - Maintain proper button disabled state for accessibility - Add CSS styles for .disabled-day-container and .custom-day-content - Add comprehensive test coverage for the fix Fixes #1071 --- src/components/calendar/bl-calendar.css | 15 ++++++++ src/components/calendar/bl-calendar.test.ts | 39 +++++++++++++++++++++ src/components/calendar/bl-calendar.ts | 21 +++++++++++ 3 files changed, 75 insertions(+) diff --git a/src/components/calendar/bl-calendar.css b/src/components/calendar/bl-calendar.css index 3c2cc5a0..709b3254 100644 --- a/src/components/calendar/bl-calendar.css +++ b/src/components/calendar/bl-calendar.css @@ -142,3 +142,18 @@ .calendar-text { font: var(--bl-font-title-3-regular); } + +.disabled-day-container { + position: relative; + display: inline-block; +} + +.custom-day-content { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + pointer-events: auto; + z-index: 1; +} diff --git a/src/components/calendar/bl-calendar.test.ts b/src/components/calendar/bl-calendar.test.ts index 4c7f4f8c..9c6d682a 100644 --- a/src/components/calendar/bl-calendar.test.ts +++ b/src/components/calendar/bl-calendar.test.ts @@ -667,5 +667,44 @@ describe("bl-calendar", () => { expect(strongTag).to.exist; expect(strongTag?.textContent).to.not.be.empty; }); + + it("should render custom day content for disabled dates in special container", async () => { + const dayRendererWithTooltip = (date: Date) => html`${date.getDate()}
Custom tooltip
`; + const disabledDate = new Date(2023, 0, 15); + + element = await fixture(html``); + element._calendarMonth = 0; + element._calendarYear = 2023; + await element.updateComplete; + + const dayWrappers = element.shadowRoot?.querySelectorAll(".day-wrapper"); + let disabledDayWrapper: Element | null = null; + + // Find the disabled day wrapper + dayWrappers?.forEach(wrapper => { + const button = wrapper.querySelector("bl-button"); + + if (button?.hasAttribute("disabled")) { + const buttonId = button.getAttribute("id"); + + if (buttonId === disabledDate.getTime().toString()) { + disabledDayWrapper = wrapper; + } + } + }); + + expect(disabledDayWrapper).to.exist; + const disabledDayContainer = disabledDayWrapper!.querySelector(".disabled-day-container"); + + expect(disabledDayContainer).to.exist; + + const customDayContent = disabledDayContainer!.querySelector(".custom-day-content"); + + expect(customDayContent).to.exist; + + const tooltip = customDayContent!.querySelector("bl-tooltip"); + + expect(tooltip).to.exist; + }); }); }); diff --git a/src/components/calendar/bl-calendar.ts b/src/components/calendar/bl-calendar.ts index 5fe7e4b8..bc15b733 100644 --- a/src/components/calendar/bl-calendar.ts +++ b/src/components/calendar/bl-calendar.ts @@ -446,6 +446,27 @@ export default class BlCalendar extends DatepickerCalendarMixin { "disabled-day": isDisabledDay, }); + // For disabled days with custom renderer that might contain tooltips, + // wrap in a container that can receive pointer events + if (isDisabledDay && this.dayRenderer) { + return html`
+
+ + ${date.getDate()} + +
${this.dayRenderer(date)}
+
+
`; + } + return html`
Date: Mon, 20 Oct 2025 16:06:31 +0300 Subject: [PATCH 2/4] docs(datepicker): add Disabled Dates With Tooltip story demonstrating dayRenderer on disabled dates --- .../datepicker/bl-datepicker.stories.mdx | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/components/datepicker/bl-datepicker.stories.mdx b/src/components/datepicker/bl-datepicker.stories.mdx index 44bfd1f8..ad720ffe 100644 --- a/src/components/datepicker/bl-datepicker.stories.mdx +++ b/src/components/datepicker/bl-datepicker.stories.mdx @@ -152,6 +152,39 @@ You can set min date or max date for the datepicker. +### Disabled Dates With Tooltip + +You can render tooltips on disabled dates via `dayRenderer`. This example disables specific dates and shows a tooltip explaining why. + + + + {() => { + const disabledDates = [ + new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() + 2), + new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() + 5), + ]; + const isDisabled = (d) => disabledDates.some(x => x.getFullYear() === d.getFullYear() && x.getMonth() === d.getMonth() && x.getDate() === d.getDate()); + const dayRenderer = (date) => html` + + ${date.getDate()} +
+ ${isDisabled(date) ? 'This date is disabled' : 'Available date'} +
+
+ `; + return html` + + `; + }} +
+
+ ## RTL Support The datepicker component supports RTL (Right-to-Left) text direction. You can enable RTL mode by setting the `dir` attribute and `lang` attribute on a parent element or the `html` tag. From 741802ebd72fa220f1dd58ff3fcccce93532a79c Mon Sep 17 00:00:00 2001 From: tolgaucar Date: Mon, 20 Oct 2025 18:46:09 +0300 Subject: [PATCH 3/4] docs(datepicker): wire Disabled Dates With Tooltip story to Controls and parse disabledDates string via stringToDateArray --- .../datepicker/bl-datepicker.stories.mdx | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/components/datepicker/bl-datepicker.stories.mdx b/src/components/datepicker/bl-datepicker.stories.mdx index ad720ffe..20cf0fa5 100644 --- a/src/components/datepicker/bl-datepicker.stories.mdx +++ b/src/components/datepicker/bl-datepicker.stories.mdx @@ -2,6 +2,7 @@ import { html } from "lit"; import { ArgsTable, Canvas, Meta, Story } from "@storybook/addon-docs"; import { ifDefined } from "lit/directives/if-defined.js"; import { unsafeHTML } from "lit/directives/unsafe-html.js"; +import { stringToDateArray } from "../../utilities/string-to-date-converter"; - - {() => { - const disabledDates = [ - new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() + 2), - new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() + 5), - ]; + + {(args) => { + const disabledDates = typeof args.disabledDates === 'string' + ? stringToDateArray(args.disabledDates) + : (args.disabledDates || []); + const isDisabled = (d) => disabledDates.some(x => x.getFullYear() === d.getFullYear() && x.getMonth() === d.getMonth() && x.getDate() === d.getDate()); + const dayRenderer = (date) => html` ${date.getDate()} @@ -172,15 +183,15 @@ You can render tooltips on disabled dates via `dayRenderer`. This example disabl
`; + return html` - `; + >`; }} From 21bb2bbfeef14c4ba97ed326dfabf85463075748 Mon Sep 17 00:00:00 2001 From: tolgaucar Date: Wed, 22 Oct 2025 14:02:47 +0300 Subject: [PATCH 4/4] docs(datepicker): show tooltip only for disabled days and add Controls for tooltip text --- src/components/calendar/bl-calendar.css | 5 ++++ .../datepicker/bl-datepicker.stories.mdx | 24 ++++++++++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/components/calendar/bl-calendar.css b/src/components/calendar/bl-calendar.css index 709b3254..94198b95 100644 --- a/src/components/calendar/bl-calendar.css +++ b/src/components/calendar/bl-calendar.css @@ -157,3 +157,8 @@ pointer-events: auto; z-index: 1; } + +/* Ensure disabled overlay content visually matches disabled button */ +.disabled-day-container .custom-day-content { + color: var(--bl-color-neutral-lighter); +} diff --git a/src/components/datepicker/bl-datepicker.stories.mdx b/src/components/datepicker/bl-datepicker.stories.mdx index 20cf0fa5..d09c3cd9 100644 --- a/src/components/datepicker/bl-datepicker.stories.mdx +++ b/src/components/datepicker/bl-datepicker.stories.mdx @@ -164,8 +164,9 @@ You can render tooltips on disabled dates via `dayRenderer`. This example disabl type: 'single', label: 'Disabled Dates With Tooltip', placeholder: 'Select a date', - // Allow editing from Controls as comma-separated dates + // Controls: comma-separated dates string disabledDates: `${new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() + 2)}, ${new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() + 5)}`, + disabledTooltipText: 'This date is disabled', }} > {(args) => { @@ -175,14 +176,19 @@ You can render tooltips on disabled dates via `dayRenderer`. This example disabl const isDisabled = (d) => disabledDates.some(x => x.getFullYear() === d.getFullYear() && x.getMonth() === d.getMonth() && x.getDate() === d.getDate()); - const dayRenderer = (date) => html` - - ${date.getDate()} -
- ${isDisabled(date) ? 'This date is disabled' : 'Available date'} -
-
- `; + const dayRenderer = (date) => { + if (isDisabled(date)) { + // Only disabled days have tooltip; trigger is an invisible overlay to avoid duplicating numbers + return html` + + +
${args.disabledTooltipText}
+
+ `; + } + // Non-disabled days should render the day number normally + return html`${date.getDate()}`; + }; return html`