diff --git a/src/components/calendar/bl-calendar.css b/src/components/calendar/bl-calendar.css index 3c2cc5a0..94198b95 100644 --- a/src/components/calendar/bl-calendar.css +++ b/src/components/calendar/bl-calendar.css @@ -142,3 +142,23 @@ .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; +} + +/* 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/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`
+### Disabled Dates With Tooltip + +You can render tooltips on disabled dates via `dayRenderer`. This example disables specific dates and shows a tooltip explaining why. + + + + {(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) => { + 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` + `; + }} +
+
+ ## 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.