Another React component for using Utterances ๐ฎ on your website!
- Rewritten
client.js
code using React API directly in the component. - Written fully in TypeScript.
- Build for both CommonJS and ES Module.
- Named exports only.
- Customization options.
- Placeholder when the component is loading.
- Event handler (
onLoad
,onError
) support.
- react-utterances-client
My main motivation is to resolve the bug that I encountered when using utterance-react-component
.
utterance-react-component
loads the script https://utteranc.es/client.js
and passes the props to that script. The problem is the component will have the same bugs as client.js
and at the point I am writing this still exists.
Refer to utterances issue #624 and utterances-component issue #393.
So, I took client.js
, rewrote that using React API, and made it into a React component.
npm install react-utterances-client
yarn add react-utterances-client
Recommended to specify a version tag like this for installation from the repository like below for stability.
npm install github:mddanish00/react-utterances-client#vX.X.X
yarn add react-utterances-client@github:mddanish00/react-utterances-client#vX.X.X
Check out the repository tags list here.
Remove #vX.X.X
to fetch the latest changes from the main
branch. Beware of instability!
import { Utterances } from 'react-utterances-client';
const Comments = () => {
return (
<Utterances
repo="people/example-project"
theme="github-dark"
issueTerm="title"
/>
);
};
You just need to specify the repository that you will be using its issues for comments.
The repository you want to use must:
- The repository is set to Public.
- The utterances app is installed on the repository.
- Make sure Issues is turned on if your repository is a fork.
After that, you can specify your theme or just omit theme
prop to use the default theme and decide on issue mapping with your current page.
For this, it is better to read Blog Post โ๏ธ Issue Mapping
on the official site for a more details explanation of the options.
You can only use one of the below props for this:
- For
pathname
,url
,title
,og:title
or specific terms, you need to useissueTerm
prop. - For
issueNumber
, you need to provide the issue number toissueNumber
prop.
import * as React from 'react';
import { Utterances } from 'react-utterances-client';
const Comments = () => {
const handleLoad = React.useCallback((e)=>{
console.log('Component is loaded!')
}, []);
return (
<Utterances
repo="people/example-project"
theme="github-dark"
issueTerm="title"
onLoad={handleLoad}
/>
);
};
Only two event handlers can be used right now:
- onLoad: When this component finishes loading.
- onError: When this component throws errors.
This will be attached to the iframe onLoad
and onError
.
The e
will be passed down to the event handler.
This feature is experimental. It need more feedback from the users. It may be removed in later versions.
import { Utterances } from 'react-utterances-client';
const Comments = () => {
return (
<Utterances
repo="people/example-project"
issueTerm="title"
tokenStorage="session"
/>
);
};
Every time the user logs in to their GitHub account on the Utterances site, this component will keep the token in the redirected URL into localStorage. The problem with this is the Utterances don't provide any way to log out of the account from the site.
Also, based on my reading on the Utterances project code, the token has a 1-year expiry date.
So, I added an option to keep the token in SessionStorage instead. LocalStorage will survive when the site or tab closes but SessionStorage will auto-delete them. This is a better approach in my opinion.
The component will still set the storage to LocalStorage by default.
Recommended to create a way for the user to clear Login data like a button. Like this.
import { Utterances } from 'react-utterances-client';
const Comments = () => {
return (
<>
<button onClick={()=>localStorage.removeItem('utterances-session')}>
Clear Login Data
</button>
<Utterances
repo="people/example-project"
issueTerm="title"
tokenStorage="session"
/>
</>
);
};
This feature is experimental. It need more feedback from the users. It may be removed in later versions.
import { Utterances } from 'react-utterances-client';
const Comments = () => {
return (
<Utterances
repo="people/example-project"
issueTerm="title"
placeholder={true}
/>
);
};
Placeholder is a component that will display when the Utterances component is loading. You need to enable this feature explicitly to use it. You can even provide your own Placeholder Component through placeholder
prop.
This prop will set
loading
prop toeager
regardless what you set.
import { Utterances } from 'react-utterances-client';
const Comments = () => {
return (
<Utterances
repo="people/example-project"
theme="gruvbox-dark"
issueTerm="title"
iframeClassName="text-light"
containerStyle={{ background: '#282828'}}
/>
);
};
List of themes that are available for use with Utterances:
- github-light
- github-dark
- preferred-color-scheme
- github-dark-orange
- icy-dark
- dark-blue
- photon-dark
- boxy-light
- gruvbox-dark
For preferred color scheme
, it will depend on your OS's dark mode settings. If disabled, github-light
. If enabled, github-dark
.
You can see the Theme preview on the official site. Also, available in Comments Demo.
This component exposes the className
prop and style
prop for both Container div (containerClassName
, containerStyle
) and iframe (iframeClassName
, iframeStyle
). This opens up the possibility when customizing the appearance of the component.
For example, you can use the containerStyle
prop to customize the container background.
Or, pass Bootstrap classes like text-light
or bg-primary
to containerClassName
prop.
Or, you Emotion css
function and pass the generated className to the containerClassName
prop.
Go wild!
import { Utterances, UtterancesProps } from 'react-utterances-client';
Types of Utterances
component props are also accessible via UtteranceProps
if you want to use it for some reason.
Name | Type | Required / Default | Description |
---|---|---|---|
repo | ${string}/${string} |
required | Comments respository for use with this component. |
label | string | "" |
Label that will be assigned to issues created by Utterances. |
theme | Theme | github-light |
Theme that will be used by Utterances. |
issueTerm | Term or string[] | required if issueNumber undefined |
Mapping the current page with terms like page URL, page title, OpenGraph title, page pathname or even your own list of terms. This prop cannot be used with issueNumber. |
issueNumber | number | required if issueTerm undefined |
Mapping the current page with a specific issue number in the repository. This prop cannot be used with issueTerm. |
loading | lazy or eager | lazy |
Indicates when the browser should load this component. In this case, you want to modify the default behaviour for some reason. |
onLoad | (e) => void | undefined |
Event callback when this component finish loading. |
onError | (e) => void | undefined |
Event callback when this component throw errors. |
tokenStorage | local or session |
local |
Browser Storage that you want to use to keep your token. session to sessionStorage, local to LocalStorage. |
placeholder | boolean or React.ReactElement | false |
Placeholder when this component is still loading. You can disable, or enable it with a default placeholder or provide your own placeholder component. This also will force loading prop to eager regardless what you set. |
containerClassName | string | undefined |
ClassName of the Utterances iframe container. |
iframeClassName | string | undefined |
ClassName of the Utterances iframe. |
containerStyle | React.CSSProperties | {} |
Style of the Utterances iframe container. |
iframeStyle | React.CSSProperties | {} |
Style of the Utterances iframe. |
Star this project if it is useful for you.
Also, consider buying me a coffee!
We need to break down what client.js
does.
- Processing the provided props
- Collect attributes from the page that the script loaded from
- And, finally, construct the URL based on those information and load iframe with that URL.
As the name implies, the client.js
is just a client. And so is this component.
I will implement everything that client.js
can do and also any future updates for client.js
. I also will consider any suggestions that will improve the component itself.
I can fix it if something is wrong with the client functions above.
But if you want new features and have problems with Utterances itself, you have better luck in posting your issues in the Utterances repository instead.
This project is licensed under the MIT license.
Some of the functions in this library are based on the original client.ts in the Utterances repository that is licensed under the MIT license.
The types of the project are taken and modified from TomokiMiyauci/utterance-component repository that is licensed under the MIT license.
Icon SVG that is used as the demo icon, ๐ฎ is a part of the googlefonts/noto-emoji(https://github.com/googlefonts/noto-emoji) project that is licensed under the Apache License 2.0.
The dev-only hook, useUtterancesSession
is based on useLocalStorage
and useSessionStorage
hooks from @uidotdev/usehooks project that is licensed under the MIT license.