diff --git a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.scss b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..0d887e7f5a8cb0084e62b7303e30852afa51d081 --- /dev/null +++ b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.scss @@ -0,0 +1,4 @@ +// This class set position for tooltip arrow +.tooltip::before { + left: calc(50% - 0.5rem - var(--before-left)); +} diff --git a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts index 8fcf84b82b3af30908a7d27d1700deca0775b781..5a0799bd51743670c4e8b3a496dbb7881e011e8b 100644 --- a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts +++ b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts @@ -28,19 +28,21 @@ import { TooltipPosition } from './tooltip.directive'; @Component({ selector: 'ods-tooltip', imports: [NgClass], - template: `<p - class="fixed z-[100] animate-fadeIn cursor-default rounded bg-ozggray-900 px-3 py-2 text-sm text-whitetext before:absolute before:left-[calc(50%-0.5rem)] before:size-0 before:border-l-[0.5rem] before:border-r-[0.5rem] before:border-l-transparent before:border-r-transparent before:content-[''] dark:bg-white" + template: `<span + class="tooltip fixed z-[100] animate-fadeIn cursor-default rounded bg-ozggray-900 px-3 py-2 text-sm text-whitetext before:absolute before:border-l-[0.5rem] before:border-r-[0.5rem] before:border-l-transparent before:border-r-transparent dark:bg-white" [ngClass]="class" [class.visible]="show" [class.invisible]="!show" [style.left]="left + 'px'" [style.top]="top + 'px'" + [style.--before-left.px]="leftOffset" [attr.id]="id" role="tooltip" > {{ text }} - </p>`, + </span>`, styles: [':host {@apply contents}'], + styleUrl: './tooltip.component.scss', standalone: true, }) export class TooltipComponent { @@ -49,6 +51,9 @@ export class TooltipComponent { top: number = 0; show: boolean = false; id: string; + class: string; + leftOffset: number; + set position(value: TooltipPosition) { if (value === TooltipPosition.ABOVE) { this.class = @@ -58,5 +63,4 @@ export class TooltipComponent { this.class = 'mt-2 -translate-x-1/2 before:-top-2 before:border-b-[0.5rem] before:border-b-ozggray-900 dark:before:border-b-white'; } - class: string; } diff --git a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts index 23883077082480868b01a12f9c0e4438d91a4b39..de83c4be1b6d6dec14390b7d127d2535af366ab0 100644 --- a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts +++ b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts @@ -58,6 +58,8 @@ export class TooltipDirective implements AfterViewInit, OnDestroy { tooltipId: string; attachedToFocused: boolean = false; position: TooltipPosition; + // Used to keep tooltip inside of viewport + leftOffset: number = 0; public viewContainerRef: ViewContainerRef = inject(ViewContainerRef); public elementRef: ElementRef<HTMLElement> = inject(ElementRef); @@ -114,9 +116,10 @@ export class TooltipDirective implements AfterViewInit, OnDestroy { const { left, right, top, bottom } = this.elementRef.nativeElement.getBoundingClientRect(); this.checkViewportVisibility(); - this.componentRef.instance.left = (right + left) / 2; + this.componentRef.instance.left = (right + left) / 2 + this.leftOffset; this.componentRef.instance.top = this.getTopPosition(top, bottom, this.position, this.attachedToFocused); this.componentRef.instance.position = this.position; + this.componentRef.instance.leftOffset = this.leftOffset; this.componentRef.instance.show = true; } @@ -136,10 +139,27 @@ export class TooltipDirective implements AfterViewInit, OnDestroy { this.position = this.tooltipPosition; } + setLeftOffset(tooltipWidth: number, parentRect: DOMRect, windowWidth: number): void { + const { left, right } = parentRect; + + if (tooltipWidth / 2 > left) { + this.leftOffset = tooltipWidth / 2 - left; + return; + } + + if (tooltipWidth / 2 > right) { + // TODO + return; + } + + this.leftOffset = 0; + } + checkViewportVisibility(): void { - const tooltipHeight: number = this.componentRef.location.nativeElement.children[0].getBoundingClientRect().height; + const { width, height } = this.componentRef.location.nativeElement.children[0].getBoundingClientRect(); const parentRect: DOMRect = this.elementRef.nativeElement.getBoundingClientRect(); - this.setAutoPosition(tooltipHeight, parentRect, window.innerHeight); + this.setLeftOffset(width, parentRect, window.innerWidth); + this.setAutoPosition(height, parentRect, window.innerHeight); } setAriaAttribute(describedBy: boolean): void {