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

react-shorten

v1.1.5

Published

React Read More base and web (HTML) component

Downloads

625

Readme

React Shorten

npm downloads npm npm

Features

  • Base ReadMore component that can be used both in React DOM (Web) and in React Native to truncate text (it also allows showing more or less text).
  • Component ReadMoreWeb that can be used directly in react-dom, only requiring the length to truncate and the text itself, removing the need to handle the expanded state of the base component.
  • The truncation is based on the number of characters and allows limiting React components children length (string), even if the top children are not a string (this allows, for example, the input "text" to be a react code instead of requiring it to be a plain string).

IMPORTANT

The truncation is done traversing the children of the ReadMore component from top to bottom, from start to end, traversing the children of those components until reaching the leaves, that can be either strings or components without children.

This means that the text can be scattered across several components, but must be in the children property of those components (and not in a custom property like text or something else).

All descendants that generate text to be displayed should be able to be reached traversing only the children props of the descendants of the ReadMore component.

The descendants of the ReadMore component can have other props other than children as long as they don't display text.


Install

npm install react-shorten

Quickstart

The next examples will use the following styled ReadMore web component:

import { ReadMoreWeb } from 'react-shorten';
import React from 'react';

const StyledReadMore: React.FC<{
    truncate?: number;
    children: React.ReactNode;
}> = ({ truncate, children }) => (
    <ReadMoreWeb
        truncate={truncate}
        showMoreText="Show more"
        showLessText="Show less"
        className="read-more-btn"
    >
        {children}
    </ReadMoreWeb>
);

and the following css:

.read-more-btn {
    display: inline;
    padding: 0;
    margin: 0;
    font-size: 1rem;
    color: rgb(80, 154, 223);
    background: none;
    border: none;
    cursor: pointer;
}

.link {
    color: rgb(26, 210, 243);
}
  • Small Text: when the text has less characters than the limit required to truncate, the entire text is shown.
const SmallText = () => (
    <StyledReadMore truncate={110}>Lorem ipsum dolor sit amet.</StyledReadMore>
);
  • Large Text: when the text has more characters than the limit required to truncate, the text is truncated, showing an ellipsis after where it was truncated (this is defined in the ReadMoreWeb component, but can be done differently if using the ReadMore base component directly), and a Show more button styled as a text that expands the text when clicked. After the text is expanded, it shows a Show less button to collapse the text again.
const LargeText = () => (
    <StyledReadMore truncate={110}>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
        ullamcorper, odio eu aliquam ultricies, enim sapien aliquet arcu, quis
        aliquam diam massa eu nisl. Sed vitae nunc eget nunc ullamcorper
        aliquet. Sed euismod, nisl eget aliquam ultricies, justo nisl aliquet
        nunc, quis aliquam diam massa eu nisl. Sed vitae nunc eget nunc
        ullamcorper aliquet. Sed euismod, nisl eget aliquam ultricies, justo
        nisl aliquet nunc, quis aliquam diam massa eu nisl. Sed vitae nunc eget
        nunc ullamcorper aliquet. Sed euismod, nisl eget aliquam ultricies,
        justo nisl aliquet nunc, quis aliquam diam massa eu nisl. Sed vitae nunc
        eget nunc ullamcorper aliquet. Sed euismod, nisl eget aliquam ultricies,
        justo nisl aliquet nunc, quis aliquam diam massa eu nisl. Sed vitae nunc
        eget nunc ullamcorper aliquet. Sed euismod, nisl eget aliquam ultricies,
        justo nisl aliquet nunc, quis aliquam diam massa eu nisl. Sed vitae nunc
        eget nunc ullamcorper aliquet. Sed euismod, nisl eget aliquam ultricies,
        justo nisl aliquet nunc, quis aliquam diam massa eu nisl. Sed vitae nunc
        eget nunc ullamcorper aliquet. Sed euismod, nisl eget aliquam ultricies,
        justo nisl aliquet nunc, quis aliquam diam massa eu nisl. Sed vitae nunc
        eget nunc ullamcorper aliquet. Sed euismod, nisl eget aliquam ultricies,
        justo nisl aliquet nunc, quis aliquam diam massa eu nisl. Sed vitae nunc
        eget nunc ullamcorper aliquet. Sed euismod, nisl eget aliquam ultricies,
        justo nisl aliquet nunc, quis aliquam diam massa eu nisl.
    </StyledReadMore>
);
  • Text with HTML (pure react code): when the text has HTML, the printed text is truncated correctly at the point in which it would exceed the limit defined, even if it's not a direct child of the ReadMore component (as long as the entire text can be reached through the children property of the descendants of the ReadMore component).
const HtmlText = () => (
    <StyledReadMore truncate={110}>
        Lorem ipsum dolor sit amet,{' '}
        <i>
            <u>
                consectetur adipiscing elit. Sed ullamcorper, odio eu aliquam
                ultricies, enim sapien aliquet arcu, quis aliquam diam massa eu
                nisl. Sed vitae nunc eget nunc ullamcorper aliquet.
            </u>
        </i>{' '}
        Sed euismod, nisl eget aliquam ultricies, justo nisl aliquet nunc, quis
        aliquam diam massa eu nisl. Sed vitae nunc eget nunc ullamcorper
        aliquet.
    </StyledReadMore>
);
  • Text with links (pure react code): when the text has a link (anchor), it will work the same way as any other HTML defined as the text/children to be truncated (it's a specific case of the previous example).
const LinkText = () => (
    <StyledReadMore truncate={110}>
        Lorem ipsum dolor sit amet,{' '}
        <a href="http://localhost:3000" className="link">
            consectetur adipiscing elit. Sed ullamcorper, odio eu aliquam
            ultricies, enim sapien aliquet arcu, quis aliquam diam massa eu
            nisl. Sed vitae nunc eget nunc ullamcorper aliquet.
        </a>{' '}
        Sed euismod, nisl eget aliquam ultricies, justo nisl aliquet nunc, quis
        aliquam diam massa eu nisl. Sed vitae nunc eget nunc ullamcorper
        aliquet.
    </StyledReadMore>
);

Custom Web ReadMore Component

You can create a custom web component, instead of using the one provided by this library, if you want more customization.

You only need to make sure to handle the expanded state (this can be done in a simple useState) and (optionally, but recommended) buttons to show more and less content.

The following code is the implementation of the ReadMoreWeb component of this library. It can be used as a reference when implementing a custom component:

import { ReadMore } from 'react-shorten';
import React, { CSSProperties } from 'react';

export interface ReadMoreWebProps {
    truncate: number | undefined;
    showMoreText?: React.ReactNode;
    showLessText?: React.ReactNode;
    className?: string;
    style?: CSSProperties;
    children: React.ReactNode;
}

export const ReadMoreWeb: React.FC<ReadMoreWebProps> = ({
    truncate,
    showMoreText,
    showLessText,
    className,
    style,
    children,
}) => {
    const [expanded, setExpanded] = React.useState(false);

    const onShowMore = React.useCallback(() => setExpanded(true), []);

    const onShowLess = React.useCallback(() => setExpanded(false), []);

    return (
        <ReadMore
            truncate={truncate}
            expanded={expanded}
            showMore={
                <>
                    {'... '}
                    <button
                        onClick={onShowMore}
                        className={className}
                        style={style}
                    >
                        {showMoreText ?? 'Show more'}
                    </button>
                </>
            }
            showLess={
                <>
                    {' '}
                    <button
                        onClick={onShowLess}
                        className={className}
                        style={style}
                    >
                        {showLessText ?? 'Show less'}
                    </button>
                </>
            }
        >
            {children}
        </ReadMore>
    );
};

export default ReadMoreWeb;

Native ReadMore Component

This library does not provides a native component (so as to not have react-native as a dependency), but it can be easily created just like the web/html example above, just changing the buttons to native components like Pressable (or even Text) with onPress or another press/tap event handler of your preference.

The following code is the implementation of the ReadMoreNative component in the react-native demo. It can be used as a reference when implementing a native component:

import React from 'react';
import { ReadMore } from 'react-shorten';
import type { StyleProp, TextStyle } from 'react-native';
import { Text } from 'react-native';

interface ReadMoreNativeProps {
    truncate: number | undefined;
    showMoreText?: React.ReactNode;
    showLessText?: React.ReactNode;
    style?: StyleProp<TextStyle>;
    btnStyle?: StyleProp<TextStyle>;
    children: React.ReactNode;
}

const ReadMoreNative: React.FC<ReadMoreNativeProps> = ({
    truncate,
    showMoreText,
    showLessText,
    style,
    btnStyle,
    children,
}) => {
    const [expanded, setExpanded] = React.useState(false);

    const onShowMore = React.useCallback(() => setExpanded(true), []);

    const onShowLess = React.useCallback(() => setExpanded(false), []);

    return (
        <ReadMore
            truncate={truncate}
            expanded={expanded}
            showMore={
                <Text style={style}>
                    {'... '}
                    <Text onPress={onShowMore} style={btnStyle}>
                        {showMoreText ?? 'Show more'}
                    </Text>
                </Text>
            }
            showLess={
                <Text style={style}>
                    {' '}
                    <Text onPress={onShowLess} style={btnStyle}>
                        {showLessText ?? 'Show less'}
                    </Text>
                </Text>
            }
        >
            {children}
        </ReadMore>
    );
};

export default ReadMoreNative;

Truncated text with content inside the last tag

You can define the text to show after a truncated text inside the last tag (instead of outside it) with the endTruncate property.

For example, if the truncated text ends with a link, and you define endTruncate="...", the truncated link will end with ... as part of the link, instead of outside it.

See section Truncated text with content inside the last tag in the demo.

Demos

You can see a live web (react-dom) demo here and a react-native demo here.