UNPKG

@gravatar-com/hovercards

Version:

Add profile hovercards to Gravatar images.

475 lines (321 loc) 19.1 kB
# Gravatar Hovercards [![npm](https://img.shields.io/npm/v/@gravatar-com/hovercards)](https://npm.im/@gravatar-com/hovercards) [![build](https://img.shields.io/github/actions/workflow/status/gravatar/hovercards/build-test.yml)](https://github.com/gravatar/hovercards/actions/workflows/build-test.yml) [![release](https://img.shields.io/github/actions/workflow/status/gravatar/hovercards/release.yml?label=release)](https://github.com/gravatar/hovercards/actions/workflows/release.yml) [![package size](https://img.shields.io/bundlephobia/minzip/@gravatar-com/hovercards?label=minzipped%20size)](https://bundlephobia.com/package/@gravatar-com/hovercards) [![downloads](https://img.shields.io/npm/dm/@gravatar-com/hovercards)](https://npmtrends.com/@gravatar-com/hovercards) [![downloads](https://img.shields.io/npm/dt/@gravatar-com/hovercards)](https://npmtrends.com/@gravatar-com/hovercards) Gravatar Hovercards is an easy-to-use library that brings [Gravatar](https://gravatar.com/) profiles to your website. It converts static [Gravatar images](#1-gravatar-images), or any element with the [`data-gravatar-hash` attribute](#2-elements-with-data-gravatar-hash-attribute) into interactive hovercards. <img src="https://github.com/gravatar/hovercards/assets/21308003/5fdc4602-6c26-46c5-a00d-bd3d4be0bf63" width="600" height="309" /> ## Table of Contents - [Installation](#installation) - [Vanilla JavaScript](#vanilla-javascript) - [Usage](#usage) - [API](#api) - [React](#react) - [React Component](#react-component) - [React Hook](#react-hook) - [TypeScript](#typescript) - [Translations](#translations) - [Contribute to Gravatar Hovercards](#contribute-to-gravatar-hovercards) ## Installation This Gravatar Hovercards library supports both Vanilla JavaScript (including [TypeScript](https://www.typescriptlang.org/)) and [React](https://react.dev/). Install it via [Yarn](https://yarnpkg.com/), [NPM](https://www.npmjs.com/), or directly include it via [UNPKG](https://unpkg.com/) CDN. ### Install with Yarn or NPM Add the package to your project: ```bash yarn add @gravatar-com/hovercards ``` or ```bash npm install @gravatar-com/hovercards ``` For React, also add `react` and `react-dom` (`v16.8.0` or above): ```bash yarn add react react-dom @gravatar-com/hovercards ``` ### Install with UNPKG For Vanilla JavaScript, import the library as shown below: ```html <!-- Import the hovercard styles --> <link rel="stylesheet" href="https://unpkg.com/@gravatar-com/hovercards@x.x.x/dist/style.css"> <!-- Import the hovercards library --> <script src="https://unpkg.com/@gravatar-com/hovercards@x.x.x" defer></script> <script> // The library is accessible as a global variable console.log( Gravatar ); </script> ``` For React, import the library as shown below: ```html <link rel="stylesheet" href="https://unpkg.com/@gravatar-com/hovercards@x.x.x/dist/style.css"> <!-- Ensure React and ReactDOM are imported before the library --> <script src="https://unpkg.com/react@x.x.x" defer></script> <script src="https://unpkg.com/react-dom@x.x.x" defer></script> <!-- Import the React hovercards library --> <script src="https://unpkg.com/@gravatar-com/hovercards@x.x.x/dist/index.react.umd.js" defer></script> <script> console.log( Gravatar ); </script> ``` > Replace `x.x.x` with the latest version number. Please refer to UNPKG's [documentation](https://unpkg.com/) for more information. ## Vanilla JavaScript ### Usage You can add hovercards to your page by either using existing Gravatar images, or by adding a data attribute to any element. #### 1. Gravatar Images Ensure your page includes Gravatar images. The URLs of these images should contain hashed email addresses. For more information, refer to the [gravatar images implementation guide](http://gravatar.com/site/implement/images/). For example: ```html <div id="container"> <img id="avatar-1" src="https://www.gravatar.com/avatar/<HASHED_EMAIL_ADDRESS>" alt="Gravatar Image"> <img id="avatar-2" src="https://www.gravatar.com/avatar/<HASHED_EMAIL_ADDRESS>" alt="Gravatar Image"> <!-- Image URL with specified parameters --> <img id="avatar-3" src="https://www.gravatar.com/avatar/<HASHED_EMAIL_ADDRESS>?s=250&d=retro&r=pg" alt="Gravatar Image"> </div> ``` These can be turned into hovercards: ```js import { Hovercards } from '@gravatar-com/hovercards'; // Import the hovercard styles import '@gravatar-com/hovercards/dist/style.css'; document.addEventListener( 'DOMContentLoaded', () => { // Start the hovercards feature with your preferred settings const hovercards = new Hovercards( { /* Options */ } ); // Make hovercards work on a specific Gravatar image hovercards.attach( document.getElementById( 'avatar-1' ) ); // Alternatively, make hovercards work on all Gravatar images within a specific container hovercards.attach( document.getElementById( 'container' ) ); // If you want hovercards on all Gravatar images across the entire page, use `document.body` as the target hovercards.attach( document.body ); // You can exclude certain Gravatar images from hovercards by using `ignoreSelector` hovercards.attach( document.body, { ignoreSelector: '.ignore img[src*="gravatar.com/avatar/"]' } ); } ); ``` #### 2. Elements with `data-gravatar-hash` Attribute Alternatively, use the `data-gravatar-hash` attribute to specify the Gravatar hash for any element. This will automatically be converted into an interactive hovercard. > Note: The data attributes takes priority over the image URL. For example: ```html <div id="container"> <div id="ref-1" data-gravatar-hash="<HASHED_EMAIL_ADDRESS>">@Meow</div> <div id="ref-2" data-gravatar-hash="<HASHED_EMAIL_ADDRESS>">@Woof</div> <!-- A hash with specified parameters --> <div id="ref-3" data-gravatar-hash="<HASHED_EMAIL_ADDRESS>?s=250&d=retro&r=pg">@Haha</div> </div> ``` To convert these elements into interactive hovercards: ```js import { Hovercards } from '@gravatar-com/hovercards'; import '@gravatar-com/hovercards/dist/styles.css'; document.addEventListener( 'DOMContentLoaded', () => { // Start the hovercards feature with your preferred settings const hovercards = new Hovercards( { /* Options */ } ); // Attach hovercards on a specific image hovercards.attach( document.getElementById( 'ref-1' ) ); // Attach to all images within a container hovercards.attach( document.getElementById( 'container' ) ); // Attach to all images on the page hovercards.attach( document.body ); } ); ``` ### API #### Options You can pass an object of options to the `Hovercards` constructor to customize the behavior of your hovercards. The following options are available: ##### `placement: string = 'right'` The placement of the hovercard relative to the target element. Possible values are `top`, `bottom`, `left`, `right`, `top-start`, `top-end`, `bottom-start`, `bottom-end`, `left-start`, `left-end`, `right-start`, and `right-end`. ##### `autoFlip: boolean = true` Determines whether the hovercard's placement should automatically flip when there is not enough display space. ##### `offset: number = 10` The offset of the hovercard relative to the target element, in pixels. ##### `delayToShow: number = 500` The delay in milliseconds before the hovercard is shown. ##### `delayToHide: number = 300` The delay in milliseconds before the hovercard is hidden. ##### `i18n: Record< string, string >` Translated text strings to use instead of the default English. ##### `additionalClass: string = ''` Additional class names to be added to the outermost element of the hovercard. This is useful for customizing the styling of the hovercard. ##### `myHash: string = ''` It enables personalized hovercard features for **the current user**. It allows displaying customized options like "Edit your profile" when the user's "about me" field is empty on their [Gravatar editing page](https://gravatar.com/profiles/edit). ##### `onQueryHovercardRef: ( ref: HTMLElement ) => HTMLElement` This callback function is triggered when the library queries a hovercard ref (or a Gravatar image), allowing you to customize the ref element. The function receives the ref element as an argument and should return the modified version of the element. ##### `onFetchProfileStart: ( hash: string ) => void` This callback function is triggered when the library starts fetching a Gravatar profile. It takes the Gravatar hash as a parameter. Note that this function is executed only once per Gravatar hash due to the caching mechanism. ##### `onFetchProfileSuccess: ( hash: string, profileData: ProfileData ) => void` This callback function is triggered when the library successfully fetches a Gravatar profile. It takes the Gravatar hash and the profile data as parameters. Note that this function is executed only once per Gravatar hash due to the caching mechanism. The `profileData` parameter is an object that contains the following properties: ```ts interface ProfileData { hash: string; preferredUsername: string; thumbnailUrl: string; displayName: string; currentLocation?: string; aboutMe?: string; accounts?: Record< 'url' | 'shortname' | 'iconUrl' | 'name', string >[]; } ``` ##### `onFetchProfileFailure: ( hash: string, error: Error ) => void` This callback function is triggered when the library fails to fetch a Gravatar profile. It takes the Gravatar hash and the error as parameters. Note this function is executed only once per Gravatar hash due to the caching mechanism. ##### `onHovercardShown: ( hash: string, hovercard: HTMLDivElement ) => void` This callback function is triggered when the hovercard is shown. It takes the Gravatar hash and the hovercard element as parameters. ##### `onHovercardHidden: ( hash: string, hovercard: HTMLDivElement ) => void` This callback function is triggered when the hovercard is hidden. It takes the Gravatar hash and the hovercard element as parameters. #### Methods The `Hovercards` class provides the following methods: ##### `(static) createHovercard( profileData: ProfileData, options?: { additionalClass?: string; myHash?: string, i18n?: Record< string, string > } ): HTMLDivElement` This method generates a hovercard element using the provided profile data. It accepts the `profileData` parameter, which represents the data needed to populate the hovercard, and an optional options object that can include properties such as [`additionalClass`](#additionalclass-string) and [`myHash`](#myhash-string). It's useful when you want to display static hovercards on your website. ```js import { Hovercards } from '@gravatar-com/hovercards'; const hovercard = Hovercards.createHovercard( { hash: '...', preferredUsername: '...', thumbnailUrl: '...', displayName: '...', currentLocation: '...', aboutMe: '...', accounts: [ { url: '...', shortname: '...', iconUrl: '...', name: '...', } ], } ); document.getElementById( 'container' ).appendChild( hovercard ); ``` ##### `attach( target: HTMLElement, options?: { dataAttributeName?: string; ignoreSelector?: string } ): void` This method attaches the hovercards to the specified target element, thereby enabling the hovercard functionality. It accepts the `target` parameter, which represents the target element to which the hovercards will be attached, and an optional options object that can include properties such as `dataAttributeName` and `ignoreSelector`. - `dataAttributeName` (default: `'gravatar-hash'`) - The name of the `data-*` attribute that contains the Gravatar hash. This option is useful when you want to use a custom attribute name instead of `data-gravatar-hash`. If you want to disable the [`data-*` attribute feature](#2-elements-with-data-gravatar-hash-attribute), you can set this option to an empty string. - `ignoreSelector` (default: `''`) - A query selector that specifies elements to be excluded from displaying hovercards. This option is useful when you want to prevent certain elements from triggering hovercards. > Note: Each `attach()` call automatically detaches hovercards from their current target before attaching them to the new target. ##### `detach(): void` This method detaches the hovercards from their current target element, thereby disabling the hovercard functionality. ## React This library offers a React component and a hook, their operation is similar to the [Vanilla JavaScript](#vanilla-javascript) version. ### React Component #### Usage Here is a basic example: ```jsx // Import the React component import { Hovercards } from '@gravatar-com/hovercards/react'; // Import the hovercard styles import '@gravatar-com/hovercards/dist/style.css'; function App() { // ... return ( <Hovercards> { /* Work with Gravatar images */ } <img src="https://www.gravatar.com/avatar/<HASHED_EMAIL_ADDRESS>" alt="Gravatar Image" /> <img src="https://www.gravatar.com/avatar/<HASHED_EMAIL_ADDRESS>" alt="Gravatar Image" /> { /* Work with elements having `data-gravatar-hash` attribute */ } <div data-gravatar-hash="<HASHED_EMAIL_ADDRESS>">@Meow</div> <div data-gravatar-hash="<HASHED_EMAIL_ADDRESS>">@Woof</div> </Hovercards> ); } ``` > Note: The component will create a `div` container element to wrap all the children. You can customize the container element by using the [`className`](#classname-string) or [`style`](#style-reactcssproperties) props. To attach hovercards to the whole page or a specific element, use the [`attach`](#attach-htmlelement) prop: ```jsx import { Hovercards } from '@gravatar-com/hovercards/react'; import '@gravatar-com/hovercards/dist/style.css'; function App() { // ... return ( <> <div> <img src="https://www.gravatar.com/avatar/<HASHED_EMAIL_ADDRESS>" alt="Gravatar Image" /> <img src="https://www.gravatar.com/avatar/<HASHED_EMAIL_ADDRESS>" alt="Gravatar Image" /> <img src="https://www.gravatar.com/avatar/<HASHED_EMAIL_ADDRESS>" alt="Gravatar Image" /> </div> { /* Attach hovercards to the entire page */ } <Hovercards attach={ document.body } /> </> ); } ``` #### Props The `Hovercards` component accepts the following props: ##### `attach?: HTMLElement` This prop specifies the target element to which the hovercards will be attached. It's useful when you want to attach hovercards to an entire page. ##### `dataAttributeName?: string = 'gravatar-hash'` This prop specifies the name of the `data-*` attribute that contains the Gravatar hash. It's useful when you want to use a custom attribute name instead of `data-gravatar-hash`. If you want to disable the [`data-*` attribute feature](#2-elements-with-data-gravatar-hash-attribute), you can set this prop to an empty string. ##### `ignoreSelector?: string = ''` This prop specifies a query selector that specifies elements to be excluded from displaying hovercards. It's useful when you want to prevent certain elements from triggering hovercards. ##### `className?: string` This prop allows you to specify class names to be added to the container element, which is created by the component to wrap all the children. ##### `style?: React.CSSProperties` This prop allows you to specify styles to be added to the container element, which is created by the component to wrap all the children. *For the remaining props, please refer to the [Options](#options) section.* ### React Hook #### Usage Here are some basic examples of how to use the React hook: ```jsx import { useEffect, useRef } from 'react'; // Import the React hook import { useHovercards } from '@gravatar-com/hovercards/react'; // Import the hovercard styles import '@gravatar-com/hovercards/dist/style.css'; function App() { const { attach } = useHovercards( { /* Options */ } ); const containerRef = useRef(); useEffect( () => { if ( containerRef.current ) { attach( containerRef.current ); } }, [ attach ] ); return ( <div ref={ containerRef }> { /* Work with Gravatar images */ } <img src="https://www.gravatar.com/avatar/<HASHED_EMAIL_ADDRESS>" alt="Gravatar Image" /> <img src="https://www.gravatar.com/avatar/<HASHED_EMAIL_ADDRESS>" alt="Gravatar Image" /> { /* Work with elements having `data-gravatar-hash` attribute */ } <div data-gravatar-hash="<HASHED_EMAIL_ADDRESS>">@Meow</div> <div data-gravatar-hash="<HASHED_EMAIL_ADDRESS>">@Woof</div> </div> ); } ``` > Note: When the component is unmounted, the hook will automatically detach the hovercards from the target element. You can also use the hook to create a custom component: ```jsx import sha256 from 'js-sha256'; import { useEffect, useRef } from 'react'; import { useHovercards } from '@gravatar-com/hovercards/react'; import '@gravatar-com/hovercards/dist/style.css'; // A custom Avatar component for convenience function Avatar( { email } ) { const { attach } = useHovercards(); const imgRef = useRef(); useEffect( () => { if ( imgRef.current ) { attach( imgRef.current ); } }, [ attach ] ); return ( <img ref={ imgRef } src={ `https://www.gravatar.com/avatar/${ sha256( email ) }` } alt="Gravatar Image" /> ); } ``` #### Options and Methods The hook accepts the same options and methods as the `Hovercards` class. Please refer to the [API](#api) section for further details. ## TypeScript This library is written in TypeScript and comes with type definitions. You can check the following files for the available types: - [For Vanilla JavaScript](https://github.com/gravatar/hovercards/blob/trunk/src/index.ts) - [For React](https://github.com/gravatar/hovercards/blob/trunk/src/index.react.ts) ## Translations A few items of text are used when displaying a hovercard. The library contains English by default, but you can supply your own translations through the use of the [`i18n`](#i18n-record-string-string) option. The following phrases are used: - `Edit your profile` - `View profile` - `Sorry, we are unable to load this Gravatar profile.` - `Sorry, we are unable to load this Gravatar profile. Please check your internet connection.` The `i18n` option is an object that maps from the English text to the language of your choice (even another English phrase, if you wish to change the text). ```js { 'Edit your profile': 'Modifier votre profil' } ``` ## Contribute to Gravatar Hovercards We welcome contributions to this project. Please follow the guidelines outlined in the [CONTRIBUTING.md](https://github.com/gravatar/hovercards/blob/trunk/CONTRIBUTING.md) file. ## License Gravatar Hovercards is licensed under [GNU General Public License v2 (or later)](https://github.com/gravatar/hovercards/blob/trunk/LICENSE.md).