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

@phun-ky/speccer

v9.1.19

Published

A script to annotate, show spacing specs and to display typography information in documentation/website on HTML elements

Downloads

361

Readme

@phun-ky/speccer

logo

A zero dependency package to highlight elements

Commitizen friendly PRs Welcome SemVer 2.0 npm version issues license size npm GitHub Repo stars codecov

Image of speccer

About

Speccer was originally created to make it easier to document components in a design system, but you can use it to whatever you like, if you are in the need to highlight any element!

npm i @phun-ky/speccer

See demo here: https://codepen.io/phun-ky/pen/xaOrYX

API

Go here to read the full API documentation.

Usage

Typescript

Types can be found in @phun-ky/speccer/dist/speccer.d.ts.

ESM

Either import and run the required functions:

import '@phun-ky/speccer/dist/speccer.min.css';
import speccer from '@phun-ky/speccer';

// do stuff
speccer();

Script

Or place these script and link tags in your web page:

<link rel="stylesheet" href="../path/to/speccer.min.css" />
<script src="../path/to/speccer.js"></script>

Or with a CDN:

<link
  rel="stylesheet"
  href="https://unpkg.com/@phun-ky/speccer/dist/speccer.min.css"
/>
<script src="https://unpkg.com/@phun-ky/speccer/dist/speccer.js"></script>

And then follow the steps below to display the specifications you want :)

React

If you use React, you can use an effect like this:

import React, { useEffect } from 'react';
import PropTypes from 'prop-types';

import debounce from './lib/debounce';
import '@phun-ky/speccer/dist/speccer.min.css';

const Component = () => {
  let speccerEventFunc;

  useEffect(async () => {
    const { default: speccer } = await import('@phun-ky/speccer');

    speccer();

    speccerEventFunc = debounce(function () {
      speccer();
    }, 300);

    window.addEventListener('resize', speccerEventFunc);
    return () => {
      window.removeEventListener('resize', speccerEventFunc);
    };
  }, []);

  return <div />;
};

export default Component;

Advanced usage

If you want to control speccer a bit more, you have some options. Apply one of these attributes to the script element for different types of initialization:

<script src="../speccer.js" data-<manual|instant|dom|lazy></script>

Or with a CDN:

<script src="https://unpkg.com/@phun-ky/speccer/dist/speccer.js" data-<manual|instant|dom|lazy></script>

| Tag | Description | | -------------- | ------------------------------------------------------------------- | | data-manual | Makes window.speccer() available to be used when you feel like it | | data-instant | fires off speccer() right away | | data-dom | Waits for DOMContentLoaded | | data-lazy | Lazy loads speccer() per specced element |

If no attribute is applied, it will default to data-dom, as in, it will initialize when DOMContentLoaded is fired.

Lazy

If you're importing speccer instead of with a script tag, you can use the following approach to apply lazy loading:

import { dissect, ElementDissectionResult } from "https://esm.sh/@phun-ky/speccer";

/**
 * Function to dissect an HTML element
 * @param {Element} target - The element to be dissected
 * @returns {Promise<ElementDissectionResult>} Promise that resolves with the dissection result
 */
const dissectElement = (target: Element): Promise<ElementDissectionResult> => {
  return dissect.element(target);
};

/**
 * Callback function for IntersectionObserver
 * @param {IntersectionObserverEntry[]} entries - Array of entries being observed
 * @param {IntersectionObserver} observer - The IntersectionObserver instance
 * @returns {Promise<void>} Promise that resolves when element dissection is complete
 */
const intersectionCallback: IntersectionObserverCallback = async (entries, observer) => {
  entries.forEach(async (entry) => {
    if (entry.intersectionRatio > 0) {
      await dissectElement(entry.target);
      observer.unobserve(entry.target);
    }
  });
};

// Creating IntersectionObserver instance with the callback
const dissectElementObserver = new IntersectionObserver(intersectionCallback);

/**
 * Function to observe elements using IntersectionObserver
 * @param {Element} el - The element to be observed
 */
const observeElement = (el: Element): void => {
  dissectElementObserver.observe(el);
};

// Observing elements with the specified data attribute
document.querySelectorAll('[data-anatomy-section]').forEach((el) => {
  observeElement(el);
});

Features

Element spacing

Image of speccer

In your component examples, use the following attribute:

<div data-speccer class="..."></div>

This will display the element and all of it's children padding and margin.

Element dimensions

Image of speccer

In your component examples, use the following attribute:

<div
  data-speccer-measure="[height right|left] | [width top|bottom]"
  class="..."
></div>

Where height and width comes with placement flags. Default for height is left, default for width is top.

Subtle measure

Image of subtle option for measure

You can also give a more subtle touch to the measure elements.

<div data-speccer-measure="height left subtle" class="..."></div>

This will give a dashed border.

Highlight the anatomy of an element

Image of speccer

In your component examples, use the following attribute. Remember to use the data-anatomy-section as an attribute on a parent element to scope the marking.

<div data-anatomy-section>
  <div
    data-anatomy="outline [full|enclose][curly] [left|right|top|bottom]"
    class="..."
  ></div>
</div>

This will place a pin to the outline of the element. Default is top.

Subtle anatomy

Image of subtle option for anatomy

You can also give a more subtle touch to the anatomy elements.

<div data-anatomy-section>
  <div data-anatomy="outline top subtle" class="..."></div>
</div>

Curly brackets

You can use curly brackets with the curly tag in data-anatomy along side outline full to provide a more sleek look to the style.

[!NOTE]
Only works with outline full

The curly brackets are made with SVG paths, and it is required to have the following snippet on your page for it to render:

<svg
  class="ph-speccer"
  viewBox="0 0"
  id="ph-speccer-svg"
  xmlns="http://www.w3.org/2000/svg"
>
  <path
    class="ph-speccer path original"
    id="ph-speccer-path"
    fill="none"
    stroke-width="1"
    stroke="currentColor"
  />
</svg>

This will give a dashed border, and a more subtle pin style.

Element typography

Image of typography speccer

In your component examples, use the following attribute.

<div data-speccer-typography="[left|right|top|bottom]" class="...">
  Some text
</div>

This will place a box to display typography information. Default is left.

Mark elements

Alt text

This will mark the given elements.

In your component examples, use the following attribute.

<div data-speccer-mark …>…</div>

A11y notation

With speccer, you can also display accessibility notation, like Accessibility Bluelines:

Prior art: Jeremy Elder

Tab stops

Screenshot of speccer a11y tab stops in use

If you want to display tab stops, append data-speccer-a11y-tabstops as an attribute to the container you want to display the tab stops in.

Landmarks and regions

Screenshot of speccer a11y landmarks in use

If you want to display landmarks and regions, append data-speccer-a11y-landmark as an attribute to the container you want to display the landmarks and regions in.

Keys and shortcut

Screenshot of speccer a11y shortcuts in use

If you want to display the shortcut with keys used for elements, use data-speccer-a11y-shortcut="<shortcut>" on the element that uses this shortcut:

<button type="button" data-speccer-a11y-shortcut="ctrl + s">Save</button>

Customization

Screenshot of speccer in a dark mode example

Allthough the styling works nicely with dark mode, you can use the provided CSS variables to customize the look and feel. If more control is needed, you can use CSS overrides :)

.ph-speccer.speccer {
  --ph-speccer-color-padding: rgba(219, 111, 255, 0.4);
  --ph-speccer-color-padding-hover: #db6fff;
  --ph-speccer-color-margin: rgba(255, 247, 111, 0.4);
  --ph-speccer-color-margin-hover: #fff76f;
  --ph-speccer-color-text-light: #fff;
  --ph-speccer-color-text-dark: #333;
  --ph-speccer-color-contrast: #ff3aa8;
  --ph-speccer-spacing-color: var(--ph-speccer-color-contrast);
  --ph-speccer-measure-color: #f00;
  --ph-speccer-pin-color: var(--ph-speccer-color-contrast);
  --ph-speccer-typography-background-color: #fff;
  --ph-speccer-typography-color-property: #3f85f2;
  --ph-speccer-typography-color-text: #57575b;
  --ph-speccer-typography-color-value: var(--ph-speccer-color-contrast);
  --ph-speccer-depth-opacity-400: 0.4;
  --ph-speccer-font-family: 'Menlo for Powerline',
    'Menlo Regular for Powerline', 'DejaVu Sans Mono', Consolas, Monaco,
    'Andale Mono', 'Ubuntu Mono', monospace;
  --ph-speccer-font-size: 12px;
  --ph-speccer-line-height: 12px;
  --ph-speccer-pin-size: 24px;
  --ph-speccer-pin-space: 48px;
  --ph-speccer-line-width: 1px;
  --ph-speccer-line-width-negative: -1px;
  --ph-speccer-measure-size: 8px;
}

Contributing

If you want to contribute, please read the CONTRIBUTING.md and CODE_OF_CONDUCT.md

Sponsor me

I'm an Open Source evangelist, creating stuff that does not exist yet to help get rid of secondary activities and to enhance systems already in place, be it documentation or web sites.

The sponsorship is an unique opportunity to alleviate more hours for me to maintain my projects, create new ones and contribute to the large community we're all part of :)

Support me with GitHub Sponsors.