npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

use-accessible-block-link

v0.0.0

Published

A reusable react hook that preserves a components semantics to deliver visual blocks link user interfaces. Handles containing multiple buttons or anchor links.

Downloads

3

Readme

Semantic Block Links

useAccessibleBlockLink is a reusable react hook that preserves a components semantic accessibility to create a visual block link. This hook supports multiple links within the same block.

The problem we're solving for

When creating block links where there are semantic tags used inside an interactive element <a> or <button> we lose all semantic value we've placed inside that block solely to create larger visual click radius.

Example

<a href="..." title="...">
  <h2>...</h2>
  <ul>
    <li>
      <h3>...</h3>
      <p>...</h3>
    <li>
    ...
  </ul>
  <p></p>
</a>

The result of this when coupled with a lot of content is a poor accessiblity experience for all users who are not visual. This issue exacerbates itself when we mutiple this effect for user interface solutions Cards, Product Cards, wrapping selectable functionality and fully clickable table rows.

Our solution

// Create a ref to provide to the hook for what we want the main event of the block link to be
const mainEvent = useRef();

// Get back the `handleClick` event to set on the container or wrapper of our block link
const {handleClick} = useAccessibleBlockLink(mainEvent);

// Provide the click event on our block link wrapper
// Provide the mainEvent ref on the element we want non-interactive clicks to fallback to
return (
  <div onClick={handleClick}>
    <a ref={mainEvent} href="/home">
      Home
    </a>
    <p>description</p>
  </div>
);

Providing a react hook that requires a single ref to the interactive element we establish to be are block links main event. By placing the click handler the hook gives back on the wrapping block link element we create our block links boundaries.

The hook handles determining if the event is an interactive element or not. If the element is interactive we allow the native browersr to handle it. If the element is non-interactive we fallback to the event we have provided on our ref as our main event.

Usage

Below we have an example of a block link. This block link provides the new ref to the item we want to be the main event (Home). We get back the handleClickhandler that monitors if we are clicking a interactive or non-interactive element.

By placing the handleClick handler on the wrapping element it help determine whether or not we are firing a interactive or non-interactive element. It allows interactive elements to operate native to the browers behavior. When non-interactive elements are detected, it falls back to the event provided on the main event (mainEvent) ref.

<a> as main event example:

const BlockLink = () => {
  const mainEvent = useRef();

  const {handleClick} = useAccessibleBlockLink(mainEvent);

  return (
    <div onClick={handleClick}>
      <a ref={mainEvent} href="/home">
        Home
      </a>
      <p>description</p>
      <button type="button" onClick={() => {}}>
        secondary action
      </button>
    </div>
  );
};

The hook works interchangeably for <a> and <button> tags as the user sees fit. The solution also allows for as many nested interactive elements as the user wants.

<button> as main event example:

const BlockLink = () => {
  const mainEvent = useRef();

  const {handleClick} = useAccessibleBlockLink(mainEvent);

  return (
    <div onClick={handleClick}>
      <button
        ref={mainEvent}
        onClick={() => {
          location.assign('/home');
        }}
      >
        Home
      </button>
      <p>description</p>
      <a href="/secondary">secondary action</a>
    </div>
  );
};

Compatibility with React Router

Currently useAccessibleBlockLink is compatible with React Router. There isn't compliance yet with React Router's internal <Link> component. Users will need to use modify the history in React Router 5 using useHistory or useNavigate in React Router 6.

Contributors

This project wouldn't exist without the collaboration to resolve this issue. There is a vast future of potential to add to this existing solution. All Contributions are welcome! Please add yourself to our list when contributing. Please see our contribution guidelines.

Contribution Guide

Setup

  • All new features created should be a new branch off of this existing repo. All pull requests will be required to be reviewed and approved by one of our reviewers.
  • Once reviewed we will merge our pull requests using githubs merge process directly to our main branch.
  • If the pull request warrants a release we can follow our release process.

Releases

  • This project uses semvar and runs on yarn. To upgrade please use yarn publish the next appropriate package number.
  • Before commiting your release be sure to run yarn && yarn typeCheck && yarn test. We first want to confirm depedencies. Then run our local TypeScript checking. Lastly we run our tests to confirm our package is in full working order.
  • All new features and bug fixes are to be accompanied by a new test to confirm behavior.

Found a bug?

Please create an issue an using the Github issue template.

Provide:

  • A path to recreate the bug.
  • An example of the code either:
    • A Pull Request demonstrating the issue.
    • CodeSandbox or Github repository with clear example of the issue.