Ways to Remove Focus from a Button in Blazor/C# by Triggering the Escape Key without JavaScript

I am in the process of developing a tooltip feature within the Blazor framework. The main goal I have is to make the tooltip disappear when the escape key is pressed while focusing on the button.

Currently, I have successfully implemented this feature using the provided code. However, it involves JavaScript, which I would like to avoid if possible.

This is my current approach:

@inject IJSRuntime JSRuntime

<button @onclick="ToggleTooltip">test</button>
<div role="tooltip" @ref="tooltip" tabindex="0" @onkeydown="CloseTooltip">
  Password Rules:
</div>
<p>test</p>

@code {
  ElementReference tooltip;
  bool showTooltip = false;

  void ToggleTooltip()
  {
    showTooltip = !showTooltip;
    if (showTooltip)
    {
      tooltip.FocusAsync();
    }
  }

  async Task CloseTooltip(KeyboardEventArgs e)
  {
    if (e.Key == "Escape")
    {
      showTooltip = false;
      await JSRuntime.InvokeVoidAsync("Blurred", tooltip);
      await InvokeAsync(StateHasChanged);
    }
  }
}

<script>
  window.Blurred = function(element) {
  element.blur();
};
</script>

<style>
  * {
    margin: 0;
    padding: 0;
  }

  [role="tooltip"] {
    margin-top: .75rem;
    display: none;
    position: absolute;
    background: black;
    color: white;
  }

  [role="tooltip"]:before {
    margin-top: -7px;
    content: "";
    border: 7px solid transparent;
    border-bottom-color: #000;
    border-top-width: 0;
    position: absolute;
  }

  button:hover + [role="tooltip"],
  button:focus + [role="tooltip"],
  [role="tooltip"]:focus {
    display: block;
  }
</style>

Answer №1

From my perspective, it is advisable to manage the display conditions of your elements using components' flags/booleans rather than relying on CSS pseudo-classes like hover/focus.

Here is a suggested approach:

@page "/"

<button @onclick="ToggleTooltip" @onmouseover="ShowTooltip" @onmouseout="HideTooltip">test</button>

@if (stickyTooltip || showTooltip)
{
    <div role="tooltip" @ref="tooltip" tabindex="0" @onkeydown="CloseTooltip">
    Password Rules:
    </div>
}

<p>test</p>

@code {
    
  private bool showTooltip = false;
  private bool stickyTooltip = false;

  ElementReference tooltip;

  private async Task ToggleTooltip()
  {
    stickyTooltip = !stickyTooltip;

    if (stickyTooltip)
    {
        await InvokeAsync(StateHasChanged);
        await Task.Delay(1); // Allow it to re-render
        
        try
        {
            await tooltip.FocusAsync();
        }
        catch(Exception){}
    }
  }

  private async Task ShowTooltip()
  {
    showTooltip = true;

    await InvokeAsync(StateHasChanged);
    await Task.Delay(1); // Allow it to re-render

    try
    {
        await tooltip.FocusAsync();
    }
    catch(Exception){}
  }

  private void HideTooltip()
  {
    showTooltip = false;
  }

  private void CloseTooltip(KeyboardEventArgs e)
  {
    if (e.Key == "Escape")
    {
      showTooltip = false;
      stickyTooltip = false;
    }
  }
}

<style>
  * {
    margin: 0;
    padding: 0;
  }

  [role="tooltip"] {
    margin-top: .75rem;
    position: absolute;
    background: black;
    color: white;
  }

  [role="tooltip"]:before {
    margin-top: -7px;
    content: "";
    border: 7px solid transparent;
    border-bottom-color: #000;
    border-top-width: 0;
    position: absolute;
  }
</style>

The implementation appears to align with your objectives, but there are some considerations. For instance, pressing the Escape key will only work if the tooltip is in focus. If you make the tooltip sticky and click elsewhere, the Escape key may not trigger the tooltip's keydown event.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Matching start and end of CSS selectors using regex

If I have elements with a title attribute like the examples below, how can I select the div with the title custom-marker-wqs-tailrace bbu-l2 using a CSS regex selector? <div title="custom-marker-awlr-tailrace bbu-l2"></div> <div ti ...

Unlocking a thread: The process of freeing up a thread

My program currently has 20 threads running simultaneously but after a while, it starts to slow down significantly. I'm wondering if there is something specific I should be doing with these tasks such as freeing them or handling them in a different wa ...

Encountering a 500 Internal Error in ASP.net API While Utilizing Async Await During Ongoing Process

I am encountering a situation with my web API controller that uses the async await pattern to call external APIs. Sometimes the external API takes up to an hour to respond, resulting in a 500 Internal Server Error with a Content-length Message. Despite t ...

What could be causing my background image to not display properly?

I am struggling with applying a background image to a button on my web page. Despite using the code provided, the background image does not show up. Can someone help me understand why this is happening? Check out this demo: https://jsfiddle.net/p7octep1/ ...

How to correctly position a modal in a React application using CSS

Currently, I am working on integrating the react-modal NPM library into a React Typescript project. The issue I am facing is that the modal occupies the entire width of the screen by default, with padding included. My goal is to have it display as a small ...

Incorporating a NuGet package containing essential references into an existing core project with outdated dependencies

Currently I am in the process of developing a .NET standard package that incorporates version 2.1.1 of the Microsoft.AspNetCore.Http nuget package. After successfully adding this nuget package to a test core project with the same version, everything worke ...

"Utilizing flex-box to create a hover effect for child elements

I am attempting to create a grid caret with a top and bottom caret that displays a grey area when the user hovers over each side. <div class="control-wrap"> <div class="caret-wrap"> <span class="caret">▲</span> </div&g ...

JQuery is capable of hiding a div using the .hide() method but is unable to reveal it using the

I am currently working on a basic webpage that includes a question and a set of radio buttons. Depending on the option selected by the user, the question will be hidden and either a correct or incorrect message will be displayed, both of which are initiall ...

The transition between backgrounds is malfunctioning

I want to create a smooth transition effect for changing the background of an element within a setInterval function. Currently, the background changes immediately, but I would like it to transition over a period of time. var act = true; setInterval(func ...

Spot the columns generated by CSS and incorporate a new column using JavaScript

Exploring a column newspaper-like layout has led me to wonder if there is a way to use CSS or JavaScript to identify columns (or column breaks) and dynamically insert content between them with JavaScript. The concept involves having a layout with 100% hei ...

Adjusting the columns of two tables when one table is held in place

My dilemma involves managing two tables: In the scenario, Table 1 remains fixed in place serving as a header that is always visible. Meanwhile, Table 2 acts as the data table. I am not a fan of fixed widths for my tables; I prefer them to dynamically adj ...

What is the best way to remove input focus when clicked away?

I am in the process of developing an application using next js, and I need assistance with designing a search field. The primary functionality I am looking to implement is displaying search suggestions when the user starts typing, but hiding them when the ...

Issue with the rendering of Label, TextBox, and RequiredFieldValidator web controls after customization

Recently, I developed a custom web control that includes a Label, TextBox, and RequiredFieldValidator. This was achieved by creating a new class called Field which inherits from Table Control. namespace WebHRIS.Controls { public class Field : Table ...

Developing asynchronous tasks in ASP.NET Web API for sending email messages

I am encountering significant performance issues in my application, and I have identified that the root cause lies in the email sending process. How can I resolve this issue so that the method RegisterUser returns without waiting for the email to be sent? ...

Puzzling blank area found beneath the form component

There seems to be some extra space at the bottom of a form when it's placed inside a div. How can we remove that unwanted space? In examples from stack overflow, the extra space is not visible in the code snippets provided. However, it appears elsewh ...

Adding static files to your HTML page with node.js

This is not a question about using express.static() In my application, I have multiple pages that share the same JS and CSS dependencies. Instead of adding <script> or <link> tags to every single page, I'm looking for a way to include the ...

Apply a specific style conditionally using Angular's ng-repeat directive

Currently, I am utilizing ng-repeat to iterate through a list of divs and manually adding items to the JSON that is rendering these divs. My goal is to position the last div that I add in the JSON at the location where the mouse cursor is, while keeping th ...

Issue with Bootsrap 4 Dropdown Menu Displaying Incomplete Links

There seems to be an issue with the Bootstrap 4 dropdown menu not displaying all the links. Please refer to the image below: https://i.sstatic.net/ZS2t2.png The dropdown menu is not showing beyond the red band. I can't seem to figure out what I&apos ...

Adjust the size of the child div to fit the remaining space within the parent div

I'm dealing with a situation where there are two child divs inside a parent div. The first child div takes up 32% of the width, while the second child div takes up 68% of the width. If I were to set the display of the first child div to "none", how ca ...

Show an Unordered List in a Horizontal Orientation

I'm having trouble getting my Subnav list to display horizontally. Can anyone offer a solution to this issue? http://jsfiddle.net/nategines/9bued/10/ ...