Giter VIP home page Giter VIP logo

collapsed's Introduction

๐Ÿ™ˆ react-collapsed (useCollapse)

CI npm bundle size (version) npm version Netlify Status

A React hook for creating accessible expand/collapse components. Animates the height using CSS transitions from 0 to auto.

Features

  • Handles the height of animations of your elements, auto included!
  • You control the UI - useCollapse provides the necessary props, you control the styles and the elements.
  • Accessible out of the box - no need to worry if your collapse/expand component is accessible, since this takes care of it for you!
  • No animation framework required! Simply powered by CSS animations
  • Written in TypeScript

Demo

See the demo site!

CodeSandbox demo

Installation

$ npm i react-collapsed

Usage

Simple Usage

import React from 'react'
import { useCollapse } from 'react-collapsed'

function Demo() {
  const { getCollapseProps, getToggleProps, isExpanded } = useCollapse()

  return (
    <div>
      <button {...getToggleProps()}>
        {isExpanded ? 'Collapse' : 'Expand'}
      </button>
      <section {...getCollapseProps()}>Collapsed content ๐Ÿ™ˆ</section>
    </div>
  )
}

Control it yourself

import React, { useState } from 'react'
import { useCollapse } from 'react-collapsed'

function Demo() {
  const [isExpanded, setExpanded] = useState(false)
  const { getCollapseProps, getToggleProps } = useCollapse({ isExpanded })

  return (
    <div>
      <button
        {...getToggleProps({
          onClick: () => setExpanded((prevExpanded) => !prevExpanded),
        })}
      >
        {isExpanded ? 'Collapse' : 'Expand'}
      </button>
      <section {...getCollapseProps()}>Collapsed content ๐Ÿ™ˆ</section>
    </div>
  )
}

API

const { getCollapseProps, getToggleProps, isExpanded, setExpanded } =
  useCollapse({
    isExpanded: boolean,
    defaultExpanded: boolean,
    collapsedHeight: 0,
    easing: string,
    duration: number,
    onTransitionStateChange: func,
  })

useCollapse Config

The following are optional properties passed into useCollapse({ }):

Prop Type Default Description
isExpanded boolean undefined If true, the Collapse is expanded
defaultExpanded boolean false If true, the Collapse will be expanded when mounted
collapsedHeight number 0 The height of the content when collapsed
easing string cubic-bezier(0.4, 0, 0.2, 1) The transition timing function for the animation
duration number undefined The duration of the animation in milliseconds. By default, the duration is programmatically calculated based on the height of the collapsed element
onTransitionStateChange function no-op Handler called with at each stage of the transition animation
hasDisabledAnimation boolean false If true, will disable the animation
id string | number undefined Unique identifier used to for associating elements appropriately for accessibility.

What you get

Name Description
getCollapseProps Function that returns a prop object, which should be spread onto the collapse element
getToggleProps Function that returns a prop object, which should be spread onto an element that toggles the collapse panel
isExpanded Whether or not the collapse is expanded (if not controlled)
setExpanded Sets the hook's internal isExpanded state

Alternative Solutions

  • react-spring - JavaScript animation based library that can potentially have smoother animations. Requires a bit more work to create an accessible collapse component.
  • react-animate-height - Another library that uses CSS transitions to animate to any height. It provides components, not a hook.

FAQ

When I apply vertical padding to the component that gets getCollapseProps, the animation is janky and it doesn't collapse all the way. What gives?

The collapse works by manipulating the height property. If an element has vertical padding, that padding expandes the size of the element, even if it has height: 0; overflow: hidden.

To avoid this, simply move that padding from the element to an element directly nested within in.

// from
<div {...getCollapseProps({style: {padding: 20}})}
  This will do weird things
</div>

// to
<div {...getCollapseProps()}
  <div style={{padding: 20}}>
    Much better!
  </div>
</div>

collapsed's People

Contributors

adrienharnay avatar amaxalov avatar baybara-pavel avatar bertyhell avatar dependabot[bot] avatar gaearon avatar github-actions[bot] avatar kostia1st avatar renovate[bot] avatar roginfarrer avatar swrobel avatar titozzz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

collapsed's Issues

No longer compatible with React < 18.

Issue

The changes introduced in 3.4.0 to add support for the new useId hook in React 18 while maintaining backwards compatibility don't seem to be working as intended. At least not when using Webpack. In an app using Create React App v5 (Webpack v5) and React 17, the following compilation error occurs:

Failed to compile.

Attempted import error: 'useId' is not exported from 'react' (imported as 'e').
ERROR in ./node_modules/react-collapsed/dist/react-collapsed.esm.js 49:6-13
export 'useId' (imported as 'e') was not found in 'react' (possible exports: Children, Component, Fragment, Profiler, PureComponent, StrictMode, Suspense, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, cloneElement, createContext, createElement, createFactory, createRef, forwardRef, isValidElement, lazy, memo, useCallback, useContext, useDebugValue, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState, version)

webpack compiled with 1 error
No issues found.

Other folks are having the same issue. If you look at the compiled code in the dist/ directory (react-collapsed.esm.js as downloaded from npm), it starts with import*as e from"react"; and later calls y=e.useId.

Discussion

I don't know yet why the workaround mentioned in the 3.4.0 pull request works for material-ui and not in this project. Perhaps there is a key difference in how the two projects are distributed.

[Request] Respond to height updates during animations

As said in #28, animating and changing height at the same time is not working properly. Do you think this is fixable, or this is by design from that library and cannot change?

Do you need a reproduction?

Thank you so much for the lib and your time :)

hasDisabledAnimation isn't `false` by default

    "react-collapsed": "4.0.2",

After updating to this version, for whatever reason, there's no animation unless I explicitly apply

    hasDisabledAnimation: false,

While documentation says it should have already been false by default

Remove raf dependency

rAF is pretty well-supported by the browsers now. Moreover, from what I recall, React requires it since version 16. Can we remove the polyfilled package dependency? It brings in raf, which brings in performance-now, which brings in a process polyfill. All of this seems unnecessary.

Media query collapsed

Couldn't find a way to make the dropdown component closed on mobile and open on the desktop without transition.

It works as I expected on mobile, but due to update from useEffect, there's transition on desktop as it's set to open

  const [isExpanded, setisExpanded] = useState<boolean>(false);
  const { getCollapseProps, getToggleProps } = useCollapse({
    isExpanded,
    defaultExpanded: false,
  });

  useEffect(() => {
    if (window.innerWidth > 700) {
      setisExpanded(true);
    }
  }, []);

With this code above, there's a transition on desktop when component mounts

Screen.Recording.2023-01-28.at.08.04.24.mov

can we replace useEffectAfterMount

Hello Sir, thanks a lot for this awesome hook. I was going through the code on the weekend and tried it locally.
Recently I saw this awesome talk by David Goodbye, useEffect - David Khourshid - https://www.youtube.com/watch?v=bGzanfKVFeU, especially the from 15:00, can we replace the useEffectAfterMount with the following -

function toggle() {
    const nextState = !isExpanded;
    setExpanded(nextState);
    if (nextState) {
      requestAnimationFrame(() => {
        onExpandStart();
        mergeStyles({
          willChange: "height",
          display: "block",
          overflow: "hidden",
        });

        requestAnimationFrame(() => {
          const height = getElementHeight(el);
          mergeStyles({
            transition: `height ${duration}ms ${easing}`,
            height,
          });
        });
      });
    } else {
      requestAnimationFrame(() => {
        onCollapseStart();
        const height = getElementHeight(el);
        mergeStyles({
          transition: `height ${duration}ms ${easing}`,
          willChange: "height",
          height,
        });

        requestAnimationFrame(() => {
          mergeStyles({
            height: "0px",
            overflow: "hidden",
          });
        });
      });
    }
  }

And inside the getToggleProps, we can use the toggle function like so -

  onClick: disabled ? noop : callAll(onClick, () => toggle()),

What are your thoughts on this ? Can you please try this and check all the ssr, ssg stuff. Thanks

SSR usage - prevent initially display if not expanded by default

Hi.
I use next.js
On first render I see my collapse content opened before styles was applied.
To fix that, I need to manually setup like this one

    // defaultExpanded is prop from parent component
 
    const { getCollapseProps, getToggleProps, isExpanded } = useCollapse({
      defaultExpanded,
    });

    const { style, ...restCollapseProps } = getCollapseProps();

    const ssrCollapseProps = {
      style: { display: !defaultExpanded ? 'none' : undefined, ...style },
      ...restCollapseProps,
    };

Why just not to do this internally?
For uncontrolled version - as I did above (check defaultExpanded)
For controlled - similar way (check isExpanded)

Many thanks for awesome lib!

OffsetHeight vs ScrollHeight

Hi.
I have a problem with content that have that type of layout

<section {...ssrCollapseProps}>
 <div>
   <div style={{ marginRight: '-15px', marginBottom: '-15px' }}>
      <div style={{ marginRight: '15px', marginBottom: '15px' }}>1</div>
      <div style={{ marginRight: '15px', marginBottom: '15px' }}>2</div>
   </div>
 </div>
</section>

Section will have

  • scrollHeight: expected height + 15px
  • offsetHeight: expected height

Because of this, for this type of content we have a jump.
Possible fix

  • Add prop that force usage offsetHeight instead of scrollHeight

Why can such a layout be encountered and nothing can be done about it?
In our project, for example, this layout is used as fallback for gap property which was added to support only in safari 14.1 (and mobile safari 14.5) and we want to support users in earlier versions. Also similar styles can be found in components such as Row from bootstrap which uses the same approach for more support.

Many thanks!

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update dependency @types/node to v16.18.97
  • chore(deps): update dependency @types/styled-components to v5.1.34
  • chore(deps): update dependency @types/testing-library__jest-dom to v5.14.9
  • chore(deps): update dependency typescript to v4.9.5
  • chore(deps): update dependency @babel/core to v7.24.5
  • chore(deps): update dependency @testing-library/jest-dom to v5.17.0
  • chore(deps): update dependency cypress to v12.17.4
  • chore(deps): update dependency parcel to v2.12.0
  • chore(deps): update dependency prettier to v2.8.8
  • chore(deps): update dependency tslib to v2.6.2
  • chore(deps): update dependency tsup to v6.7.0
  • chore(deps): update jest monorepo (@types/jest, jest-environment-jsdom)
  • chore(deps): update react monorepo to v18.3.1 (@types/react, @types/react-dom, react)
  • fix(deps): update dependency @changesets/cli to v2.27.1
  • fix(deps): update dependency eslint to v8.57.0
  • fix(deps): update dependency turbo to v1.13.3
  • chore(deps): update dependency @types/testing-library__jest-dom to v6
  • chore(deps): update dependency cypress to v13
  • chore(deps): update dependency node to v20 (node, @types/node)
  • chore(deps): update dependency np to v10
  • chore(deps): update dependency prettier to v3
  • chore(deps): update dependency styled-components to v6
  • chore(deps): update dependency vite to v5
  • chore(deps): update pnpm to v9
  • chore(deps): update testing-library monorepo (major) (@testing-library/cypress, @testing-library/jest-dom, @testing-library/react)
  • fix(deps): update dependency buffer to v6
  • fix(deps): update dependency eslint to v9
  • fix(deps): update dependency eslint-config-airbnb-typescript to v18
  • fix(deps): update dependency eslint-config-prettier to v9
  • fix(deps): update dependency eslint-plugin-html to v8
  • fix(deps): update dependency eslint-plugin-prettier to v5
  • fix(deps): update typescript-eslint monorepo to v7 (major) (@typescript-eslint/eslint-plugin, @typescript-eslint/parser)
  • ๐Ÿ” Create all rate-limited PRs at once ๐Ÿ”

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/main.yml
  • actions/checkout v4
  • pnpm/action-setup v2
  • actions/setup-node v3
.github/workflows/release.yml
  • actions/checkout v4
  • pnpm/action-setup v2
  • changesets/action c2918239208f2162b9d27a87f491375c51592434
npm
example/package.json
  • react ^18
  • react-dom ^18
  • @types/react ^18
  • @types/react-dom ^18
  • parcel ^2.8.2
  • typescript ^4.9
internal/build/package.json
  • tsup ^6.5.0
internal/eslint-config-collapsed/package.json
  • @typescript-eslint/eslint-plugin ^5.57.1
  • @typescript-eslint/parser ^5.57.1
  • eslint ^8.38.0
  • eslint-config-airbnb ^19.0.4
  • eslint-config-airbnb-typescript ^17.0.0
  • eslint-config-prettier ^8.8.0
  • eslint-config-rogin 1.0.0
  • eslint-plugin-html ^7.1.0
  • eslint-plugin-import ^2.27.5
  • eslint-plugin-jsx-a11y ^6.7.1
  • eslint-plugin-prettier ^4.2.1
  • eslint-plugin-react ^7.32.2
  • eslint-plugin-react-hooks ^4.6.0
internal/tsconfig/package.json
package.json
  • @changesets/cli ^2.25.2
  • @types/node ^16.7.13
  • buffer ^5.5.0
  • eslint ^8.0.0
  • np ^6.4.0
  • prettier ^2.3.2
  • process ^0.11.10
  • turbo ^1.8.8
  • typescript ^4.9
  • pnpm 7.30.3
packages/core/package.json
  • tiny-warning ^1.0.3
  • @testing-library/jest-dom ^5.16.0
  • @types/testing-library__jest-dom ^5.14.5
  • @types/jest ^27.0.2
  • @types/node ^16.7.13
  • jest ^29.3.1
  • jest-environment-jsdom ^29.3.1
  • ts-jest ^29.0.3
  • tslib ^2.4.1
  • tsup ^6.5.0
packages/react-collapsed/package.json
  • tiny-warning ^1.0.3
  • @babel/core ^7.8.4
  • @babel/eslint-parser ^7.15.4
  • @babel/preset-react ^7.14.5
  • @cypress/vite-dev-server ^5.0.0
  • @storybook/addon-a11y ^6.5.11
  • @storybook/addon-actions ^6.5.11
  • @storybook/addon-essentials ^6.5.11
  • @storybook/addon-links ^6.5.11
  • @storybook/builder-vite ^0.4.2
  • @storybook/react ^6.5.11
  • @testing-library/cypress ^8.0.7
  • @testing-library/jest-dom ^5.16.0
  • @testing-library/react ^13.4.0
  • @types/jest ^27.0.2
  • @types/node ^16.7.13
  • @types/react ^18
  • @types/react-dom ^18
  • @types/styled-components ^5.0.1
  • @types/testing-library__jest-dom ^5.14.5
  • @types/testing-library__react ^10.2.0
  • @vitejs/plugin-react ^2.2.0
  • babel-loader ^8.2.2
  • cypress ^12.9.0
  • jest ^29.3.1
  • jest-environment-jsdom ^29.3.1
  • np ^6.4.0
  • prettier ^2.3.2
  • react ^18
  • react-docgen-typescript-loader ^3.7.1
  • react-dom ^18
  • styled-components ^5.2.0
  • ts-jest ^29.0.3
  • tslib ^2.4.1
  • tsup ^6.5.0
  • typescript ^4.9
  • vite ^3.2.4
  • react ^16.9.0 || ^17 || ^18
  • react-dom ^16.9.0 || ^17 || ^18
packages/react/package.json
  • tiny-warning ^1.0.3
  • @babel/core ^7.8.4
  • @babel/eslint-parser ^7.15.4
  • @babel/preset-react ^7.14.5
  • @cypress/vite-dev-server ^5.0.0
  • @storybook/addon-a11y ^6.5.11
  • @storybook/addon-actions ^6.5.11
  • @storybook/addon-essentials ^6.5.11
  • @storybook/addon-links ^6.5.11
  • @storybook/react ^6.5.11
  • @testing-library/cypress ^8.0.7
  • @testing-library/jest-dom ^5.16.0
  • @testing-library/react ^13.4.0
  • @types/jest ^27.0.2
  • @types/node ^16.7.13
  • @types/react ^18
  • @types/react-dom ^18
  • @types/styled-components ^5.0.1
  • @types/testing-library__jest-dom ^5.14.5
  • @types/testing-library__react ^10.2.0
  • @vitejs/plugin-react ^2.2.0
  • babel-loader ^8.2.2
  • cypress ^12.9.0
  • jest ^29.3.1
  • jest-environment-jsdom ^29.3.1
  • np ^6.4.0
  • prettier ^2.3.2
  • react ^18
  • react-docgen-typescript-loader ^3.7.1
  • react-dom ^18
  • styled-components ^5.2.0
  • ts-jest ^29.0.3
  • tslib ^2.4.1
  • tsup ^6.5.0
  • typescript ^4.9
  • vite ^3.2.4
  • react ^18
  • react-dom ^18
nvm
.nvmrc
  • node v16

  • Check this box to trigger a request for Renovate to run again on this repository

Toggle button inside collapsible content

Hello, I'm trying to have the toggle button inside the content that will be collapsed, but I can't seem to be able to get it to work...

Would you mind helping me to get it to work as intended? ... Here's a quick look at how it should look in both states:

Expanded
Shot 2020-09-26 at 12 32 32

Collapsed
Shot 2020-09-26 at 12 32 43

Thanks in advance ๐Ÿ™

Accordion mode

Could you please add an example of making Accordion mode using useCollapse in proper way. My example works but without animation as Accordion component re-renders every time activeItem state changes. My example:

export const Accordion = ({ data }) => {
	const [activeItem, setActiveItem] = useState(0);

	const onToggle = (index) => {
		const value = index === activeItem ? activeItem : index;
		setActiveItem(value);
	};

	const AccordionItem = ({ item, index, isOpen, onToggle }) => {
		const { getCollapseProps, getToggleProps, isExpanded } = useCollapse({ isExpanded: isOpen });

		return (
			<div className="accordion">
				<header
					className={`accordion-header ${isExpanded ? "active" : ""}`}
					{...getToggleProps({
						onClick: onToggle,
					})}>
					<IconChevronRight />
					<span>{item.heading}</span>
				</header>
				<div {...getCollapseProps()}>
					<main className="accordion-main">
						{item.content.map((content, i) => (
							<AccordionContent content={content} key={i} />
						))}
					</main>
				</div>
				<div className={`img ${isExpanded ? "active" : ""}`}>
					<img src={item.image.url} alt={item.image.alt} />
				</div>
			</div>
		);
	};

	return (
		<>
			{data.map((item, index) => (
				<AccordionItem item={item} index={index} key={index} isOpen={activeItem === index} onToggle={() => onToggle(index)} />
			))}
		</>
	);
};

Read more effect

Is there a way to make a read more affect (possibly by making collapsed height prop a percentage)?

Cannot easily use in react class

I'd like to use this library without converting all of my react classes to functional components. Hooks must be called from React function components, or from custom hooks.

So it would be nice to be able to use the HOC way:

function withCollapse(Component) {
  return function WrappedComponent(props) {
    const collapseProps = useCollapse({});
    return <Component {...props}  {...collapseProps} />;
  }
}

v3.2 can no longer be imported

v3.2 can no longer be imported.

import useCollapse from 'react-collapsed'

When building a next.js 11 app you get the following error:

 > Build error occurred
 Error [ERR_INVALID_PACKAGE_TARGET]: Invalid "exports" main target "dist/react-collapsed.modern.js" defined in the package config node_modules/react-collapsed/package.json; targets must start with "./"

It looks like the wrong dist file is selected, it should probably be node_modules/react-collapsed/dist/react-collapsed.js

Mac OS Safari comes with default CSS

It works fine on Chrome, IOS Safari, iPad Safari, but on mac OS safari has some default CSS styling with a white background and rounded borders.
footer

Show one collapsible at a time

First of all thank you so much to all the maintainers and contributors for such an awesome package.

I wanted to ask if there is any way to show one collapsible at a time?

New version doesn't toggle

I've tried to migrate to the new version here razzeee/website@cbde5bc

But it seems like I'm missing something, as clicking the toggle buttons does nothing. In fact it seems like all properties end up undefined or as empty functions.

[Question] A way to control the state of the nested collapse component

I need to reset the state of the nested collapse components everytime the outer component is collapsed, i.e. when I open the outer component, all the nested components are always collapsed.

My attempt: https://codesandbox.io/s/busy-morse-v965k
The problem is that isOpen is stale, and I cannot call toggleOpen only for blocks that are currently open.

Is there a workaround for this? If no, I believe this can be solved by adding close() (and open()) callbacks along with toggleOpen().

Should @babel/runtime be a dev dependency?

I noticed running yarn add react-collapsed also adds @babel/runtime to yarn.lock which is probably only required in dev.

Any specific reason as to why it's included in dependencies?

add `disabled` config option (for a11y)

Would be great if there was an option to disable the animation for accessibility support, particularly prefers-reduced-motion:

import React from 'react'
import useCollapse from 'react-collapsed'
import { useReduceMotion } from 'react-reduce-motion'

function Demo() {
  const reduceMotion = useReduceMotion()
  const { getCollapseProps, getToggleProps, isExpanded } = useCollapse({ disabled: reduceMotion })

  return (
    <div>
      <button {...getToggleProps()}>
        {isExpanded ? 'Collapse' : 'Expand'}
      </button>
      <section {...getCollapseProps()}>Collapsed content ๐Ÿ™ˆ</section>
    </div>
  )
}

Infinite animation

My collapsed block has top and bottom padding. When i collapsed it - block height increases indefinitely (in animation loop). Looks like it increases by collapsed block height + padding every second.

Sources for the website?

Hi, nice lib, does the netlify site have a public repo as well? The code examples look broken.

image

Horizontal expand/collapse?

Thanks for the great library! I've been using it all over in one of my projects.

I was wondering, would it be complex to add a horizontal (width) based collapse effect?

I'm thinking of a sidebar expanding/collapsing.

If you're interested, I could have a look at creating a PR (if I find the time ๐Ÿ˜… ); but before I do I'd love to hear if you'd even consider merging a feature like that and if you have any requirements/pointers regarding code.

Regards, Niels

v3 Launch to-do list

  • Update readme to reflect latest instead of next
  • Write release notes -- what's new
  • Blog post on 1) measuring element with and without box-sizing: border-box, or 2) adopting TypeScript

Since switching to createRoute (concurrent React), inline styles are sometimes not updated

Hello,

Since switching to React 18 and react-dom/client's createRoute, when I try to open the Collapse (passing isExpanded: true to getCollapseProps) after the first render the inline styles don't get updated: https://gyazo.com/9c552baad3819a12908c12a85288e223. I need to set isExpanded to false, and then to true for the inline styles to be correct.

I don't have this issue with React.render (non-concurrent React API).

Thanks in advance and have a great day!

New Feature: Introduce Hooks

It would be great to use this component using hooks in React 16.8.1.

Some things that can be done as part of this:

  • Internal rewrite using them (maybe?)
  • Context based approach (i.e <Collapse> becomes a context.Provider)
  • Expose useToggle and useCollapsible hooks to get the props for the toggle button and the collapsible container respectively (naming TBD)

Dealing with changing heights

Hi there.

I'm trying to use react-collapsed on an element that has a changing height. Its children are dynamically mounted and only display their content when some data is fetched.

As react-collapsed sets a height in px on the element it is expanding, some of the content that is loading inside that element is being cut off.

From the docs it isn't immediately apparent to me how I make sure that the height of the element is auto after expanding it. Is there any way to do this?

Thanks in advance!

โ€“ Nick

Incorrect peer dependency

Running into build error deploying to Cloudflare.

[email protected]" has incorrect peer dependency "react@^16.8 || ^17".

Tried downgrading react-version, got:

Error: Next.js requires react >= 18.2.0 to be installed.
[email protected]" has incorrect peer dependency "react@^18.2.0".

Use expand on a Table cell on react

I am doing this code

const ListRestaurantTable=(props)=>{
    console.log(props)
    const header_table={
        number:"number",
        name:"Name Restaurant",
        category: "Category",
        action: "Action"
    }
    return(
        <div>
            <table className="table">
                <thead>
                <tr>
                    <th scope="col">{header_table.number}</th>
                    <th scope="col">{header_table.name}</th>
                    <th scope="col">{header_table.category}</th>
                    <th scope="col">{header_table.action}</th>
                </tr>
                </thead>
                <tbody>
                {typeof(props.props)!='undefined'? props.props.map((onerestaurant)=>{
                    return (
                        <tr key={onerestaurant.id}>
                            <th>{onerestaurant.id }</th>
                            <td><Collapsible onerestaurant={onerestaurant}/></td>
                            <td>{onerestaurant.attributes.categoryrestaurants.data[0].attributes.name}</td>
                            <td><DeleteRestaurant props={`${onerestaurant.id}`}/></td>
                        </tr>)}):"nodata"
                }}

                </tbody>
            </table>
        </div>
    )


}
function Collapsible(data) {
    const { getCollapseProps, getToggleProps, isExpanded } = useCollapse();
    const categoriesrestaurant=data.onerestaurant.attributes.categoryrestaurants.data.map((onecategory)=> onecategory.attributes.name)

    return (
        <div className="collapsible">
            <div className="header" {...getToggleProps()}>
                {isExpanded ? 'Collapse '+' '+data.onerestaurant.attributes.name : data.onerestaurant.attributes.name}
            </div>
            <div {...getCollapseProps()}>

                {data.onerestaurant.attributes.description}<br/><br/>

            </div>

        </div>
    );
}

But I when I did click to expand I need to keep on Column boundaries . How I can do that ?

`type=button` discards custom css in Safari

The type=button added by getToggleProps removes my custom styles such as background-color.
Adding a [vendor-prefix-]appearance: none does not change that behavior for me.

Work-arounds: Using a styled <button> tag instead to apply getToggleProps to doesn't work if there are more buttons inside the collapsible and leads to a dom validation issue about nesting buttons inside buttons.
(Additionally declaring a button tag as display: flex does not make it assume full width in Safari even though it should.)

I haven't found out what type=button would help with beyond what the aria role already solves. Could it be removed from the getToggleProps?

During first run all ID's are equal, which is against HTML5 WCAG 2.1 A 4.1.1

Looking at the source code, the initial random value of collapsed components is 0. When rendering multiple collapse component they all share the same ID, which is against HTML5 WCAG 2.1 A 4.1.1.

<div id="react-collapsed-panel-0"></div>

Should the unique ID be set at initialization of the hook, instead of with useEffect after mounting?

If the height is changed from the outside while the open/close process has never been executed, it will not synchronize.

If it is initially open and a change occurs that changes the internal height, react-collapsed will not reflect the change.
After the second time, the height is correctly recognized as normal.

Reproducing URL:
https://stackblitz.com/edit/react-ts-23bci9?file=App.tsx

Pressing the "+1" button does not change the height of the item, so the item is not fully displayed.
If you press the "Toggle" button once, the height will always be updated, with all items displayed.

I'm assuming this behavior is probably a bug, not a specification. But I don't know much about it.
I am not sure if this is the scope of react-collapsed too.

defaultExpanded value has no effect.

Scroll to top option?

When clicked on any element to expand the view, and if the element is at the bottom of the screen, the user has no indication that the view has expanded (I've included part of the blue in the screenshot, but if its not there, you don't realise this change, part of user experience). Providing a scroll to top could help this scenario
Screenshot 2019-12-19 11 36 20
Screenshot 2019-12-19 11 36 32

No animation when using controlled version

When using the controlled version of the hook, the animation doesn't work any more

Expected
Given the following code:

{() => {
        const [activeItem, setActiveItem] = React.useState();

        const onToggle = (item) => {
            const value = (item === activeItem) ? undefined : item;
            setActiveItem(value)
        }

        const Item = ({ title = 'heading', children = <p>some text</p>, open = false, onToggle}) => {
            const [getCollapseProps, getToggleProps] = useCollapse({isOpen: open});

            return (
                <>
                    <h1 {...getToggleProps({onClick: onToggle})}>
                        {title} {open ? '-' : '+'}
                    </h1>
                    <div {...getCollapseProps()}>
                        {children}
                    </div>
                </>
            );
        }

        let step;
        return (
            <div>
                {[1,2,3,4].map(item => (
                    <Item title={`Item ${item}`} open={activeItem === item} onToggle={() => onToggle(item)}>{`Item ${item} contents`}</Item>
                ))}
            </div>
        )
    }}

When an item heading is clicked, i expect open item to close with an animation.

Actual

The open item closes without animation, and the clicked item opens without animation.

Safari 13 support, or at least graceful error handling?

Currently, in Safari 13 react-collapsed generates an error

TypeError: mediaQueryList.addEventListener is not a function. 
(In 'mediaQueryList.addEventListener("change", listener)', 'mediaQueryList.addEventListener' is undefined)

I seem to have managed to track it down to

function usePrefersReducedMotion() {
  const [prefersReducedMotion, setPrefersReducedMotion] = useState2(false);
  useEffect3(() => {
    const mediaQueryList = window.matchMedia(QUERY);
    setPrefersReducedMotion(mediaQueryList.matches);
    const listener = (event) => {
      setPrefersReducedMotion(event.matches);
    };
    mediaQueryList.addEventListener("change", listener);
    return () => {
      mediaQueryList.removeEventListener("change", listener);
    };
  }, []);
  return prefersReducedMotion;
}

Inconsistent, unexpected flashing at the end of animations

This bug is hard to reproduce. I think the easiest way is to set up a demo with a short duration and spam the toggle button.

Example of bug

Another way is to slow the animation way down and try to time hitting the toggle right when then transition should finish. Instead of reversing the transition, the collapse will flash.

I think this has to due with the setState called onTransitionEnd and the re-updating the component. However I've been unsuccessful in debugging precisely where and why this bug is happening.

How to work with multiple elements?

import React from 'react'
import useCollapse from 'react-collapsed'

function Demo() {

  return (
    ["a", "b", "c"].map((value, index) => (
    <div>
      <button {...getToggleProps()}>
        {isExpanded ? 'Collapse' : 'Expand'}
      </button>
      <section {...getCollapseProps()}>{`${index} - ${value}`}</section>
    </div>
  )
)}

thanks.

Issues with SSR / Next.JS

Thanks for such a helpful project and for keeping it tiny! Love it.

when server side rendering - there's a mismatch between generated ids. It's a pretty common issue.

Prop `id` did not match. Server: "react-collapsed-toggle-200" Client: "react-collapsed-toggle-0" ]

Similar components reset the generated ids. It'd be great if you could provide a way to do so. Thanks!

Bump minimum react version

We should probably be able to bump the minimum react version from 16.8 to 17 due to no breaking changes from reacts side. Currently I get warnings when trying to use this library in a project using react 17.

I could create a PR and test if you want?

Add configuration for both in and out transitions

Currently the API calls for transition properties (easing, duration, delay) that applies to both in and out transitions. To make this more versatile, allow users to configure different transition properties for in and out transitions.

Currently I'm thinking props that can either take a string, or an object with keys.

easing="ease-in-out"

// or

easing={{
  in: 'ease'
  out: 'ease-out'
}}

On click issue

Hello,

I am using the collapsible to hide and expand a table but the table does not expand until I click twice.
What can be done please?

Thank you

inline styling not working

It would be nice to be able to add individual CSS properties dynamically, but this does not work:

<div style={{position: "absolute"}} {...getCollapseProps()}>

This works, but I can't set CSS properties dynamically:

CSS:

.myClassName {
    position: absolute;
}

JS:

<div className="myClassName" {...getCollapseProps()}>

Anyways, thank you for developing this component!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.