Skip to content
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

feat(Tooltip): can use 'parent' as the activator when inside a container #2297

Merged
merged 3 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions docs/Masa.Blazor.Docs/Examples/components/tooltips/Activator.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div class="text-center d-flex align-center justify-space-around">
<MButton Id="tooltip-activator-id">
ID as activator
<MTooltip Activator="#tooltip-activator-id"
Text="Tooltip"/>
</MButton>

<MButton Class="tooltip-activator-css-selector">
CSS selector as activator
<MTooltip Activator=".tooltip-activator-css-selector"
Text="Tooltip"/>
</MButton>

<MButton>
Parent as activator
<MTooltip Activator="parent" Text="Tooltip"/>
</MButton>
</div>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"props": {
"activator": "Specifies a CSS selector as the activator element; use `parent` to set the activator as the parent element",
"allowOverflow": "Removes overflow re-positioning for the content",
"attach": "Specifies which DOM element that this component should detach to.String can be any valid querySelector and Object can be any valid Node. This will attach to the root (MApp)[/components/apps] component by default.",
"contentClass": "Applies a custom class to the detached element. This is useful because the content is moved to the beginning of the (MApp)[/components/apps] component (unless the `Attach` prop is provided) and is not targettable by classes passed directly on the component.",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"props": {
"activator": "指定CSS选择器作为激活器的元素;使用`parent`将激活器设置为父元素",
"allowOverflow": "移除内容的溢出重新定位",
"attach": "指定此组件应该与哪个 DOM 元素分离。to.String 可以是任何有效的 querySelector,对象可以是任何有效的 Node。这将默认挂载到根节点 (MApp)[/components/apps]。",
"contentClass": "将自定义类应用于分离的元素。这很有用,因为内容被移动到 (MApp)[/components/apps] 组件的开头(除非提供了 `Attach` 属性),并且不被直接作为目标传递到组件上的类。",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ Tooltips can wrap any element.

### Props

#### Activator {released-on=v1.9.0}

In addition to specifying an activator element using `ActivatorContent`, you can also use the `Activator` property to specify a CSS selector as the activator. `parent` is a predefined selector that points to the parent element.

<masa-example file="Examples.components.tooltips.Activator"></masa-example>

#### Alignment

A tooltip can be aligned to any of the four sides of the activator element.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ related:

### 属性 {#props}

#### 触发器 {#activator released-on=v1.9.0}

除了使用 `ActivatorContent` 指定触发器元素外,还可以使用 `Activator` 属性指定CSS选择器作为触发器。`parent` 是预定义的指向父元素的选择器。

<masa-example file="Examples.components.tooltips.Activator"></masa-example>

#### 对齐 {#alignment}

提示可以对齐到激活器元素的四个侧面。
Expand All @@ -29,4 +35,4 @@ related:

可使用 `@bind-Value` 编程性修改提示可见性。

<masa-example file="Examples.components.tooltips.Visibility"></masa-example>
<masa-example file="Examples.components.tooltips.Visibility"></masa-example>
6 changes: 4 additions & 2 deletions src/Masa.Blazor.JS/src/interop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import throttle from "just-throttle";
import { parseDragEvent, parseMouseEvent, parseTouchEvent, touchEvents } from "./events/EventType";
import { registerExtraEvents } from "./events/index";
import registerRippleObserver from "./ripple";
import { canUseDom, getBlazorId, getDom, getElementSelector, IN_BROWSER } from "./utils/helper";
import {
canUseDom, getActivator, getBlazorId, getDom, getElementSelector, IN_BROWSER
} from "./utils/helper";

window.onload = function () {
registerExtraEvents();
Expand Down Expand Up @@ -1050,7 +1052,7 @@ export function getMenuableDimensions(hasActivator, activatorSelector, isDefault
};

if (hasActivator) {
var activator = document.querySelector(activatorSelector);
var activator = getActivator(activatorSelector)
dimensions.activator = measure(activator, isDefaultAttach)
dimensions.activator.offsetLeft = activator.offsetLeft
if (!isDefaultAttach) {
Expand Down
7 changes: 3 additions & 4 deletions src/Masa.Blazor.JS/src/mixins/activatable.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { getActivator } from "utils/helper";

import { parseMouseEvent } from "../events/EventType";
import Delayable from "./delayable";

Expand Down Expand Up @@ -32,10 +34,7 @@ class Activatable extends Delayable {
) {
super(openDelay, closeDelay, dotNetHelper);

const activator = document.querySelector(activatorSelector);
if (activator) {
this.activator = activator as HTMLElement;
}
this.activator = getActivator(activatorSelector);

this.disabled = disabled;
this.openOnClick = openOnClick;
Expand Down
21 changes: 21 additions & 0 deletions src/Masa.Blazor.JS/src/utils/helper.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const activator_parent_prefix = "$parent.";

export const IN_BROWSER = typeof window !== 'undefined'

export function addOnceEventListener (
Expand Down Expand Up @@ -211,4 +213,23 @@ export function convertToUnit (str: string | number | null | undefined, unit = '
} else {
return `${Number(str)}${unit}`
}
}

export function getActivator(selector: string): HTMLElement | null {
if (selector.startsWith(activator_parent_prefix)) {
const parentSelector = selector.replace(activator_parent_prefix, "");
const parentElement = document.querySelector(parentSelector)?.parentElement;
if (!parentElement) {
return null;
}

// special case for MButton component
if (parentElement.classList.contains('m-btn__content')) {
return parentElement.parentElement as HTMLElement;
}

return parentElement;
} else {
return document.querySelector(selector);
}
}
18 changes: 9 additions & 9 deletions src/Masa.Blazor/Mixins/Activatable/MActivatableBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Masa.Blazor.Mixins.Activatable;
public class MActivatableBase : MToggleable, IActivatableJsCallbacks
{
[Inject]
private ActivatableJsModule? Module { get; set; }
private ActivatableJsModule? ActivatableJSModule { get; set; }

[Parameter]
public bool Disabled
Expand Down Expand Up @@ -48,17 +48,17 @@ public bool OpenOnFocus
{ "aria-expanded", IsActive }
};

protected string ActivatorId => _activatorId ??= $"_activator_{Guid.NewGuid()}";
internal string ActivatorId => _activatorId ??= $"_activator_{Guid.NewGuid()}";

public string ActivatorSelector => Activator ?? $"[{ActivatorId}]";
public string ActivatorSelector => Activator == "parent" ? $"$parent.{Ref.GetSelector()}" : (Activator ?? $"[{ActivatorId}]");

protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);

if (firstRender)
{
await Module!.InitializeAsync(this);
await ActivatableJSModule!.InitializeAsync(this);
}
}

Expand Down Expand Up @@ -100,7 +100,7 @@ protected override void OnValueChanged(bool value)

private void ResetActivatorEvents()
{
_ = Module?.ResetEvents();
_ = ActivatableJSModule?.ResetEvents();
}

public virtual Task HandleOnClickAsync(MouseEventArgs args)
Expand All @@ -117,7 +117,7 @@ public async Task SetActive(bool val)

protected void UpdateActiveInJS(bool val)
{
_ = Module?.SetActive(val);
_ = ActivatableJSModule?.SetActive(val);
}

protected virtual void RunDirectly(bool val)
Expand All @@ -127,16 +127,16 @@ protected virtual void RunDirectly(bool val)

protected void RegisterPopupEvents(string selector, bool closeOnContentClick)
{
_ = Module?.RegisterPopup(selector, closeOnContentClick);
_ = ActivatableJSModule?.RegisterPopup(selector, closeOnContentClick);
}

protected void ResetPopupEvents(bool closeOnContentClick)
{
_ = Module?.ResetPopupEvents(closeOnContentClick);
_ = ActivatableJSModule?.ResetPopupEvents(closeOnContentClick);
}

protected void ResetDelay()
{
_ = Module?.ResetDelay(OpenDelay, CloseDelay);
_ = ActivatableJSModule?.ResetDelay(OpenDelay, CloseDelay);
}
}
2 changes: 1 addition & 1 deletion src/Masa.Blazor/Mixins/Menuable/MMenuable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ protected double ComputedTop

protected double AbsoluteYOffset => PageYOffset - RelativeYOffset;

protected bool HasActivator => ActivatorContent != null || ExternalActivator;
protected bool HasActivator => ActivatorContent != null || Activator is not null || ExternalActivator;

protected virtual string? DefaultAttachSelector => default;

Expand Down
2 changes: 1 addition & 1 deletion src/Masa.Blazor/wwwroot/js/chunks/helper.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/Masa.Blazor/wwwroot/js/chunks/helper.js.map

Large diffs are not rendered by default.

Loading
Loading