Skip to main content

syncfusion-blazor-toolkit-tooltip

Implement Syncfusion Blazor Toolkit SfTooltip — hover/focus/click triggered informational text with positioning, arrow indicators, animation, and ARIA (role="tooltip", aria-describedby). USE FOR: hover help on icon buttons, keyboard-shortcut hints ("Ctrl+S"), brief explanatory text on hover/focus, automatic positioning, and rich content via `ContentTemplate`. DO NOT USE FOR: required user input or confirmations (use syncfusion-blazor-toolkit-dialog with `IsModal="true"`), forms or fields (use syncfusion-blazor-toolkit-inputs), or non-blocking progress overlays (use syncfusion-blazor-toolkit-notifications / SfSpinner).

Source facts

Repository
syncfusion/blazor-toolkit
Last source activity
August 24, 2026 at 11:40
Detected SKILL.md language
English
Stars
20
Forks
9

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
license
MIT
name
syncfusion-blazor-toolkit-tooltip
description
Implement Syncfusion Blazor Toolkit SfTooltip — hover/focus/click triggered informational text with positioning, arrow indicators, animation, and ARIA (role="tooltip", aria-describedby). USE FOR: hover help on icon buttons, keyboard-shortcut hints ("Ctrl+S"), brief explanatory text on hover/focus, automatic positioning, and rich content via `ContentTemplate`. DO NOT USE FOR: required user input or confirmations (use syncfusion-blazor-toolkit-dialog with `IsModal="true"`), forms or fields (use syncfusion-blazor-toolkit-inputs), or non-blocking progress overlays (use syncfusion-blazor-toolkit-notifications / SfSpinner).
metadata
{"author":"Syncfusion Inc","version":"1.0.0"}
# Syncfusion Blazor Toolkit: Tooltip (SfTooltip) `SfTooltip` displays contextual text or markup on hover, focus, or click. It's portal-rendered, polite to interaction, and never blocks the underlying page. ## Core Rules 1. **Default trigger is `Auto` (hover or focus)** — `OpensOn="OpensOn.Auto"`. Use `Hover` for mouse-only aesthetics, `Focus` for keyboard-only flows, `Click` for non-interactive triggers (`<p>`, `<span>`). 2. **Use `Content` for text, `ContentTemplate` for markup** — never wrap HTML strings in `Content`. Templates also accept `RenderFragment` so you can keep rich content inside the tooltip. 3. **Tooltip never blocks the page.** It traps no focus and dismisses on `Escape` automatically. Don't rely on it to *confirm* a destructive action. 4. **`@bind-Visible` is supported but rarely needed** — the hover/focus lifecycle handles visibility automatically. Use `@bind-Visible` only with `OpensOn="OpensOn.Custom"`. 5. **Wrap `disabled` triggers with a focusable wrapper** — `<SfButton Disabled="true">` doesn't fire mouse/focus events. Wrap with a `<span tabindex="0">` to attach the tooltip, or render a fallback explanation adjacent to the disabled control. 6. **Don't put custom focus traps in tooltips** — they defeat the WCAG `role="tooltip"` semantics. The trigger keeps focus. 7. **`Position` is one of 12 named slots** (TopLeft, TopCenter, …, BottomRight). Stick to center slots; corner slots collide more often. 8. **`Container` constrains the portal.** Pair with `WindowCollision="true"` to keep the tooltip on-screen near page edges. ## Minimal Example ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip Target="#saveBtn" Content="Save (Ctrl+S)" Position="TooltipPosition.TopCenter" OpensOn="OpensOn.Auto" ShowTipPointer="true"> <SfButton id="saveBtn">Save</SfButton> </SfTooltip> ``` For trigger composition (disabled control, Custom `OpensOn`, `ContentTemplate`) see the **Common Patterns** section below. ## When to Use Tooltip vs Dialog If you're unsure, read the cross-skill decision matrix first: [router/dialog-vs-tooltip-decision-matrix.md](../router/dialog-vs-tooltip-decision-matrix.md). ## Documentation and Navigation Guide | Need | Read | |---|---| | Setup, properties, all triggers, RTL, full examples | [references/tooltip-implementation.md](references/tooltip-implementation.md) | ## Common Patterns ### Pattern 1 — Help icon / keyboard shortcut ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip Target="#saveBtn" Content="Save (Ctrl+S)"> <SfButton id="saveBtn">Save</SfButton> </SfTooltip> ``` ### Pattern 2 — HTML content template ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip Position="TooltipPosition.BottomCenter" Target="#btn" WindowCollision="true" TargetContainer="#custom"> <ContentTemplate> <div class="tooltip-html"> <p>HTML inside a <strong>tooltip</strong>.</p> <SfButton Content="Inner button" /> </div> </ContentTemplate> <Target> <SfButton id="btn" Content="HTML Tooltip" /> </Target> </SfTooltip> ``` ### Pattern 3 — Disabled control with focusable wrapper ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip Target="#submitDisabledWrap" Content="Form is not valid"> <span id="submitDisabledWrap" tabindex="0"> <SfButton Disabled="true">Submit</SfButton> </span> </SfTooltip> ``` ### Pattern 4 — Programmatic Show / Hide (Custom mode) ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip @ref="tt" Content="Manually controlled" OpensOn="OpensOn.Custom"> <SfButton @onclick="@(() => tt.Show())">Show tooltip</SfButton> </SfTooltip> ``` ## Key Properties & Events | Group | Members | |---|---| | Content | `Content` (string/RenderFragment), `ContentTemplate` (RenderFragment); use `Content` for text, `ContentTemplate` for HTML | | Trigger | `Target` / `TargetSelector`, `OpensOn` (Auto/Hover/Focus/Click/Custom), `OpenDelay`/`CloseDelay` (ms) | | Position | `Position` (12-slot enum, default `TopCenter`), `TipPointerPosition`, `ShowTipPointer`, `WindowCollision`, `TargetContainer`, `Container`, `OffsetX`/`OffsetY`, `Sticky`, `MouseTrail` | | Animation | `Animation` (`TooltipAnimation`, default `Fade`) — pick exactly one `Effect` | | Events | `OnOpen`/`OnOpened` (before/after portal insert); `OnClose`/`OnClosed` (before/after portal remove) | | Methods (`@ref`) | `Show()` / `Hide()` / `Refresh()` / `DisposeAsync()` | ## Accessibility | Need | Implementation | |---|---| | `aria-describedby` on the trigger | Set automatically when `Target` resolves | | Keyboard focus | Trigger element receives focus; tooltip reads when focused | | Esc dismiss | Default | | Disabled buttons | Wrap in focusable `<span tabindex="0">` — see Pattern 3 | > ⚠️ Tooltips are **static** (`role="tooltip"`, not `role="alert"`). Don't rely on them for async announcements — use [SfSpinner](../syncfusion-blazor-toolkit-notifications/SKILL.md) for that. ## Decision Tree Use this routing table alongside the Don'ts below — the tree answers "which trigger / mode should I pick"; the Don'ts answer "what *not* to do". ``` Need hover help? ├─ On a focusable control? │ └─ Plain <SfTooltip> wraps the trigger directly ├─ On a disabled control? │ └─ Wrap in <span tabindex="0"> or render fallback copy ├─ On a non-focusable element (<p>)? │ └─ OpensOn="Click" + role="button" + tabindex="0" └─ Shows HTML or rich formatting? └─ <ContentTemplate> or Content="RenderFragment" ``` ## Don'ts | Anti-pattern | Symptom | Fix | |---|---|---| | Use `SfTooltip` for confirmation ("Are you sure?") | Tooltip can't block; user can click past it; both gestures succeed | Use `SfDialog` with `IsModal="true"` (load `syncfusion-blazor-toolkit-dialog`) | | `<SfButton Disabled="true">` wrapped directly | Tooltip never appears (disabled control fires no events) | Wrap in `<span tabindex="0">`; or render fallback copy adjacent to the disabled control | | Long content (paragraphs, tables) inside `Content` | Overflow + overflowed tooltip with broken scroll affordance | Use a popover or layout-bounded panel; tooltips are 1–4 lines | | `OpensOn="Click"` on a `<button>` trigger | Two interactive gestures compete — click action fires before tooltip opens | Use `OpensOn="Auto"` for buttons; reserve `Click` for non-button triggers (`<span>`, `<p>`) | | Two `Effect` values: `Fade` + `Slide` on same tooltip | Animation queue races; either _bad_ both render | Pick exactly one effect | | `Role="dialog"` / `role="alertdialog"` in `ContentTemplate` | Tooltip loses `role="tooltip"`; ARIA mis-announced as modal | Allow default `role="tooltip"`; for visual emphasis, use CSS not roles | | `Id` collision on `Target="#x"` when modal also `#x` | Tooltip finds the wrong node (modal backdrop); wrong arrow direction | Use unique IDs per page section | | `Container="body"` + `WindowCollision="true"` with custom scrollable parent | Tooltip overflows scroll container; disappears when parent scrolls | Either set `Container` to the scrollable parent, or accept that page-level scroll will hide the tooltip | | `OnOpen="async void OnOpen(...) "` | Exceptions silently escape the Blazor dispatcher | `OnOpen="async Task OnOpen(...)"` | ## Anti-Pattern Workflows ### Workflow 1 — Agent tries to put a tooltip on a disabled save button **Anti-pattern:** ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip Content="Please fill the form"> <SfButton Disabled="true">Save</SfButton> </SfTooltip> ``` **Fix:** ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <!-- Wrap disabled button in tab-able span; tooltip finds the wrapper --> <SfTooltip Content="Please fill the form" OpensOn="OpensOn.Auto"> <span tabindex="0" aria-disabled="true" class="disabled-wrapper"> <SfButton Disabled="true">Save</SfButton> </span> </SfTooltip> ``` Or — **preferred** — render the explanation *visibly* in the form validation summary instead. ### Workflow 2 — Agent wants long copy in the tooltip **Anti-pattern:** paragraphs and tables inside `Content`. Tooltips aren't scrollable; long content overflows visually. **Fix:** either break it down into multiple tooltips (one per concept), or delegate to a Popover/Popup. For help text needing richer layout, escalate to `SfDialog` with `IsModal="false"`: ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <!-- ❌ Tooltip overflow --> <SfTooltip Content="Click to start the workflow, then select the customer, then…"> <SfButton>?</SfButton> </SfTooltip> <!-- ✅ Link out to modal help --> <SfButton OnClick="@OpenHelp" CssClass="e-flat">?</SfButton> @code { private void OpenHelp() { /* render SfDialog IsModal="false" with full help */ } } ``` ### Workflow 3 — Agent sets both `Effect="Fade"` and `Effect="Slide"` via different syntaxes **Bad:** ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip Content="…" Animation="new TooltipAnimation { Effect = AnimationEffect.Fade, … }" /> <SfTooltip Content="…" Animation="@(new TooltipAnimation { Effect = AnimationEffect.Slide, … })" /> <!-- @ref+lifecycle uses the second; good luck having both render --> ``` **Correct:** one tooltip, one effect. Combine with `Duration`: ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip Content="…" Animation="@(new TooltipAnimation { Effect = AnimationEffect.Fade, Duration = 200 })"> <span>Target</span> </SfTooltip> ``` ### Workflow 4 — Agent wants to *prevent* focus when the trigger is a button **Bad:** ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip Content="Delete this" OpensOn="OpensOn.Hover"> <SfButton OnClick="Delete">Delete</SfButton> </SfTooltip> ``` User keyboard-tabs to button → tooltip won't show (`Hover` only fires on pointer enter). **Fix:** keep `OpensOn="Auto"` (default), or — if `Hover` was intentional — add a static `:focus` CSS style and roll your own focus announcement. ### Workflow 5 — Agent changes `Target` at runtime, expects tooltip to reposition **Bad:** ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip Target="@TargetId" Content="…"> <SfButton>@currentLabel</SfButton> </SfTooltip> @code { private string TargetId = ""; private void Move() { TargetId = "other"; } } ``` `Target` resolves once at mount. Changing it without `Refresh()` causes the arrow to point at the old location. **Fix:** ```razor @using Syncfusion.Blazor.Toolkit @using Syncfusion.Blazor.Toolkit.Popups <SfTooltip @ref="tt" Target="@TargetId" Content="…"> <SfButton>@currentLabel</SfButton> </SfTooltip> @code { private TooltipRef? tt; private void Move() { TargetId = "other"; tt?.Refresh(); } } ``` (Or — and this is the simpler route — use `<SfTooltip>` as a *wrapper* of the trigger rather than a `Target=` reference, so positioning follows the trigger DOM automatically.) silently ## Next Steps 1. **First tooltip:** read [tooltip-implementation.md](references/tooltip-implementation.md). 2. **Modal confirm / block UI:** exit this skill and load [syncfusion-blazor-toolkit-dialog](../dialog/SKILL.md). 3. **In doubt:** read [router/dialog-vs-tooltip-decision-matrix.md](../router/dialog-vs-tooltip-decision-matrix.md). **Demo:** Syncfusion Blazor Toolkit official demo at https://blazor.syncfusion.com/demos/toolkit/tooltip
View on GitHub