-
Couldn't load subscription status.
- Fork 1.5k
[CL-879] use tooltip on icon button #16576
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
base: main
Are you sure you want to change the base?
Changes from 27 commits
a979277
d587e36
ae4874f
e797a0b
ccaa6f7
dffc8e3
1249dc6
4960aab
f6ff777
c4043b7
f97b8f1
4611ed6
a2d9202
0b1638f
9091038
dcd8080
b7f454e
7d21320
6c89964
3ede3a6
b434f33
767443c
595cbb3
f5e8648
cfa9edc
81a6ff8
2ff37cb
1bdf199
307b0d2
e78c094
fdc6ec3
e5b6835
c3e8e4c
30ebc63
8d2345b
19c19ea
a107c0b
8558cc7
77efb1b
cdf5a00
86b5db9
6169661
62bd86a
6ba5ab6
c10b194
9add2f8
83cc425
4afd965
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,10 +1,11 @@ | ||
| <!-- eslint-disable-next-line tailwindcss/no-custom-classname --> | ||
| <div | ||
| class="bit-tooltip-container" | ||
| [attr.data-position]="tooltipData.tooltipPosition()" | ||
| [attr.data-visible]="tooltipData.isVisible()" | ||
| > | ||
| <div role="tooltip" class="bit-tooltip"> | ||
| <ng-content>{{ tooltipData.content() }}</ng-content> | ||
| @if (tooltipData.content()) { | ||
| <div | ||
| class="bit-tooltip-container" | ||
| [attr.data-position]="tooltipData.tooltipPosition()" | ||
| [attr.data-visible]="tooltipData.isVisible()" | ||
| > | ||
| <div role="tooltip" class="bit-tooltip" [id]="tooltipData.id()"> | ||
| <ng-content>{{ tooltipData.content() }}</ng-content> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,8 +8,9 @@ import { | |
| ElementRef, | ||
| Injector, | ||
| input, | ||
| effect, | ||
| signal, | ||
| model, | ||
| computed, | ||
| } from "@angular/core"; | ||
|
|
||
| import { TooltipPositionIdentifier, tooltipPositions } from "./tooltip-positions"; | ||
|
|
@@ -26,30 +27,36 @@ import { TooltipComponent, TOOLTIP_DATA } from "./tooltip.component"; | |
| "(mouseleave)": "hideTooltip()", | ||
BryanCunningham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "(focus)": "showTooltip()", | ||
| "(blur)": "hideTooltip()", | ||
| "[attr.aria-describedby]": "resolvedDescribedByIds()", | ||
| }, | ||
| }) | ||
| export class TooltipDirective implements OnInit { | ||
| private static nextId = 0; | ||
| /** | ||
| * The value of this input is forwarded to the tooltip.component to render | ||
| */ | ||
| readonly bitTooltip = input.required<string>(); | ||
| readonly bitTooltip = model<string>(); | ||
| /** | ||
| * The value of this input is forwarded to the tooltip.component to set its position explicitly. | ||
| * @default "above-center" | ||
| */ | ||
| readonly tooltipPosition = input<TooltipPositionIdentifier>("above-center"); | ||
|
|
||
| readonly isDescribedbyText = model<boolean>(false); | ||
|
||
|
|
||
| private isVisible = signal(false); | ||
| private overlayRef: OverlayRef | undefined; | ||
| private elementRef = inject(ElementRef); | ||
| private elementRef = inject<ElementRef<HTMLElement>>(ElementRef); | ||
| private overlay = inject(Overlay); | ||
| private viewContainerRef = inject(ViewContainerRef); | ||
| private injector = inject(Injector); | ||
| private positionStrategy = this.overlay | ||
| .position() | ||
| .flexibleConnectedTo(this.elementRef) | ||
| .withFlexibleDimensions(false) | ||
| .withPush(true); | ||
| private tooltipId = `bit-tooltip-${TooltipDirective.nextId++}`; | ||
| private currentDescribedByIds = | ||
| this.elementRef.nativeElement.getAttribute("aria-describedby") || null; | ||
|
|
||
| private tooltipPortal = new ComponentPortal( | ||
| TooltipComponent, | ||
|
|
@@ -62,20 +69,47 @@ export class TooltipDirective implements OnInit { | |
| content: this.bitTooltip, | ||
| isVisible: this.isVisible, | ||
| tooltipPosition: this.tooltipPosition, | ||
| id: signal(this.tooltipId), | ||
| }, | ||
| }, | ||
| ], | ||
| }), | ||
| ); | ||
|
|
||
| private destroyTooltip = () => { | ||
| this.overlayRef?.dispose(); | ||
| this.overlayRef = undefined; | ||
| this.isVisible.set(false); | ||
| }; | ||
|
|
||
| private showTooltip = () => { | ||
| if (!this.overlayRef) { | ||
| this.overlayRef = this.overlay.create({ | ||
| ...this.defaultPopoverConfig, | ||
| positionStrategy: this.positionStrategy, | ||
| }); | ||
|
|
||
| this.overlayRef.attach(this.tooltipPortal); | ||
| } | ||
| this.isVisible.set(true); | ||
| }; | ||
|
|
||
| private hideTooltip = () => { | ||
| this.isVisible.set(false); | ||
| this.destroyTooltip(); | ||
| }; | ||
|
|
||
| private resolvedDescribedByIds = computed(() => { | ||
| if (this.isDescribedbyText()) { | ||
| if (this.currentDescribedByIds) { | ||
| return `${this.currentDescribedByIds || ""} ${this.tooltipId}`; | ||
| } else { | ||
| return this.tooltipId; | ||
| } | ||
| } else { | ||
| return this.currentDescribedByIds; | ||
| } | ||
| }); | ||
|
|
||
| private computePositions(tooltipPosition: TooltipPositionIdentifier) { | ||
| const chosenPosition = tooltipPositions.find((position) => position.id === tooltipPosition); | ||
|
|
||
|
|
@@ -89,22 +123,11 @@ export class TooltipDirective implements OnInit { | |
| }; | ||
| } | ||
|
|
||
| setContent(text: string) { | ||
| this.bitTooltip.set(text); | ||
| } | ||
|
|
||
| ngOnInit() { | ||
| this.positionStrategy.withPositions(this.computePositions(this.tooltipPosition())); | ||
|
|
||
| this.overlayRef = this.overlay.create({ | ||
| ...this.defaultPopoverConfig, | ||
| positionStrategy: this.positionStrategy, | ||
| }); | ||
|
|
||
| this.overlayRef.attach(this.tooltipPortal); | ||
|
|
||
| effect( | ||
| () => { | ||
| this.positionStrategy.withPositions(this.computePositions(this.tooltipPosition())); | ||
| this.overlayRef?.updatePosition(); | ||
| }, | ||
| { injector: this.injector }, | ||
| ); | ||
| } | ||
| } | ||
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.
This is safe to remove?
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.
@willmartian As far as I can tell, yeah. We're still swallowing the click with our host directive. And, it's necessary to remove in order to apply tooltips to disabled buttons
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.
Probably scope creep for this ticket, but since we already have a team looking to use the tooltip on a button, we should make a story for it
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.
Added a story here