Giter Site home page Giter Site logo

daviferreira / react-sanfona Goto Github PK

View Code? Open in Web Editor NEW
242.0 5.0 64.0 5.13 MB

Accessible react accordion component

Home Page: https://daviferreira.github.io/react-sanfona

License: MIT License

JavaScript 100.00%
react accordion collapsible accessibility

react-sanfona's Introduction

react-sanfona

NPM info

Travis build status Depfu

React accordion component

giphy 1

Usage

Install via NPM:

npm install react-sanfona

Then:

import { Accordion, AccordionItem } from 'react-sanfona';



  render() {
    return (
      <Accordion>
        {[1, 2, 3, 4, 5].map(item => {
          return (
            <AccordionItem title={`Item ${item}`} expanded={item === 1}>
              <div>
                {`Item ${item} content`}
              </div>
            </AccordionItem>
          );
        })}
      </Accordion>
    );
  }

options / PropTypes

Accordion

Property Type Description Default
allowMultiple Boolean Allow multiple items to be open at the same time. false
isHovered Boolean Allow expanding an element after the mouse hovers an item. false
openNextAccordionItem Boolean Opens the next accordion item after the previous one is closed. Defaults first one as active and applies for each accordion item except the last one. false
className String Custom classname applied to root element null
style Object Inline styles applied to root element null
onChange Function Triggered when component updates and passes new state as an argument null
rootTag String Custom HTML tag used for root element 'div'
duration Number Open/close transition duration in milliseconds 300
easing String Open/close transition easing 'ease'

AccordionItem

Property Type Description Default
title String/ Object Text or Object to display in header. null
expanded Boolean If item body should be expanded or not false
onExpand Function Callback for when item is expanded null
onClose Function Callback for when item closes null
className String Custom classname applied to root item element null
bodyClassName String Custom classname applied to the accordion item body null
expandedClassName String Custom classname applied when accordion is expanded null
titleClassName String Custom classname applied to accordion item header text null
disabled Boolean If item should be disabled or not false
disabledClassName String Custom classname applied to accordion item header text when item is disabled null
rootTag String Custom HTML tag used for root element 'div'
titleTag String Custom HTML tag used for title element 'h3'
bodyTag String Custom HTML tag used for body element 'div'
duration Number Open/close transition duration in milliseconds 300
easing String Open/close transition easing 'ease'
slug String Slug key to allow indexing by a string

Styling with classnames

Classname Targets
react-sanfona Accordion container
react-sanfona-item AccordionItem container
react-sanfona-item-expanded AccordionItem container when expanded
react-sanfona-item-title AccordionItem header text
react-sanfona-item-body AccordionItem body container
react-sanfona-item-body-wrapper AccordionItem body children wrapper
react-sanfona-item-disabled AccordionItem is disabled

development

npm install

npm start // served on localhost:8080

npm test

react-sanfona's People

Contributors

akiroz avatar brukh avatar clemsos avatar daviferreira avatar dependabot[bot] avatar depfu[bot] avatar elg0nz avatar ghburman avatar greenkeeperio-bot avatar kachkaev avatar leonascimento avatar luckyraul avatar maxnowack avatar murzvo avatar psimyn avatar reergymerej avatar wamujlb 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

react-sanfona's Issues

Issue with transitions on Safari

I faced some weird animations on Safari 8.0.8 with MacOS. Digging into the DOM did show me that there is a max-height value for accordion-item-body which is adding up to something close to 100px on my click and then less than a second changes back to none. Any ideas?

accordion-bug

allow setting activeItems by title

a) allow either index or title. Simple, but could mean an item called '0' and one with index 0 both selected
b) prop for activeItems to use index or title
c) convert activeItems to list of objects

Manually expand Accordion Item

Is there a way to manually expand an Accordion item?
I am actually using redux. And I tried doing something like

<AccordionItem expanded={someBoolean} onExpand={expandingCallback}>
   {categorisedArray}
</AccordionItem>

where someBoolean comes from the redux state.

Now when I click one of the elements from categorised array, the accordion item gets closed even though the value of someBoolean is true in the state. My goal is to preserve the state of the accordion i.e. before clicking an element from the array, if an accordion was opened, I want it to stay opened after the page re renders.

I am trying to find a function or some tag that will help me to manually expand the accordion on receiving the props. Something like this.showItem(). Or any other way of achieving the main purpose will do too.

Thanks.

allowMultiple=false doesn't prevent array of activeItems

Probably similar to #51

Example:

<Accordion allowMultiple={false} activeItems={[0,1,2]}>
</Accordion>
  • When the page first loads then 0, 1, 2 are expanded
  • Click item 1 it will close and others (multiple) will remain open
  • Click item 1 again it will re-open, and then the others will close

Possible solutions:

  • warn/error if passing an array when allowMultiple is false
  • grab the first entry, ignore rest of array
  • don't worry about it this isn't a very serious issue

Form elements ...

Is there a way to not have the accordion not close when I am clicking on form elements like a select option? Every time I click a header to open up and there is a select option element inside the content container, I try to click on it and the accordion then closes.

Getting Uncaught Invariant Violation in console warning

Hi,
I tried to use react-sanfona in my project but, getting the bellow warning in browser console

You're trying to render a component to the document using server rendering but the checksum was invalid. This usually means you rendered a different component type or props on the client from the one on the server, or your render() methods are impure

I followed the example that is in demo folder.
can you please let me know how to resolve this?

Trouble defaulting to closed Accordion with form components in AccordionItem

Right now I just have a single AccordionItem:

<Accordion style={STYLES.search} activeItems={-1}>
    <AccordionItem title='Search Form'>
        <SearchForm />
    </AccordionItem>
</Accordion>

I added the activeItems={-1} and it renders closed as expected. The problem is, when I expand it and click on a form component (right now there is only a single text field), it closes immediately. If I remove the activeItems={-1}, it renders opened, but I am able to click on the text field without the AccordionItem closing.

I am using version 0.1.0.

Only one AccordionItem will error.

after updating package v0.4.0 to latest accordion stop working

if i use this code. Note only one item. it throws the error.

<Accordion className="Accordion">
    <AccordionItem
        titleClassName="Accordion-title"
        bodyClassName="Accordion-body"
        expandedClassName="is-expanded"
        title={stubExplanation}
        >
            <p>{furtherExplanation}</p>
        </AccordionItem>
  </Accordion>

but if i use this hack. it works.

<Accordion className="Accordion">
    {[1].map((item, index) => {
     return (
         <AccordionItem
             key={`accordion-key-${index}`}
             titleClassName="Accordion-title"
             bodyClassName="Accordion-body"
             expandedClassName="is-expanded"
             title={stubExplanation}
            >
                 <p>{furtherExplanation}</p>
             </AccordionItem>
              );
      })}
</Accordion>

Pass to title props a function

Is there any way or idea in how to implement a function inside the ?

Im thinking in some stuff like that:

  <AccordionItem title={this.renderMateriaSqueezed.bind(this)} key={key}>
    <HeaderComponent title={item.title} id={item.id} subtitle={item.subtitle} category={item.categoria} />
    <Content content={item.content[0]} />
    <Footer />
  </AccordionItem>

I need to render a whole content as "title" or some way to load previous content before the accordion is clicked. I'm able to help you guys in this feature if there's no way to do this yet.

AccordionItem closes after button click

I have something like this.

  handleDeleteUser = (e) => {
    if (this.state.confirm) {
      this.setState({
        confirm: false 
      })
    } else {
      this.setState({
        confirm: true 
      })
    }
  }

...

<button type='button' id={id} onClick={this.handleDeleteUser}>
  {this.state.confirm ? 'Really?' : 'Delete'}
</button>

Setting state within the handler closes all open accordions. Any ideas why?

With new version onClose event is triggering by itself

Hi, I upgraded to latest version of react-sanfona(0.1.0) and my onClose and onExpand events are not working as expected, when I try to open an AccordionItem it closes by itself. below is the code snippet.
<AccordionItem id={"test"+c} uuid={"test"+c} onClose={() => this.hideItem(value)} onExpand={() => this.showItem(value)} title={value} slug={c} key={id} allowMultiple={true} expanded={true}>

Thank you

Using PropTypes

Hi,

I see that the package is using PropTypes still and that practice has been deprecated in the newer versions of React. Thought I'd give a heads up on that.

-R

component throwing exception

Render method throws the below error.

Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. Check the render method oft.

To test it out I am running the exact same code from the docs and still see the issue.

Some investigation revels, that
import { Accordion, AccordionItem } from 'react-sanfona' returns undefined.
Both Accordion and AccordionItem are undefined.

Whereas using

import myAccordion from 'react-sanfona'
<myAccordion.Accordion>
  <myAccordion.AccordionItem></myAccordion.AccordionItem>
</myAccordion>

seem to work fine.

webpack error

when webpack tries to run on any files where i have required('react-sanfona') i get the following errors:
ERROR in /home/mpbill/NodeTest//react-sanfona/dist-modules/AccordionItem/index.js
Module not found: Error: Cannot resolve module 'classnames' in /home/mpbill/NodeTest/node_modules/react-sanfona/dist-modules/AccordionItem
@ /home/mpbill/NodeTest/
/react-sanfona/dist-modules/AccordionItem/index.js 31:18-39

ERROR in /home/mpbill/NodeTest//react-sanfona/dist-modules/AccordionItem/index.js
Module not found: Error: Cannot resolve module 'uuid' in /home/mpbill/NodeTest/node_modules/react-sanfona/dist-modules/AccordionItem
@ /home/mpbill/NodeTest/
/react-sanfona/dist-modules/AccordionItem/index.js 39:12-27

any ideas?

Event onClick on Each AccordionItem?

Is there a way to add an onClick event on each AccordionItem? I need to dispatch an action every time user click the AccordionItem. I've tried to add onClick event directly to the AccordionItem, but it doesn't work. This is what I've tried so far

<AccordionItem
  title={`Room Details for ${this.props.nights} nights`}
  titleClassName="panel-heading"
  onClick={() => this.changeActiveForm('room-breakdown')}
>

How to prevent default onClick over AccordionItem

Hello,

Thank very much for your work.
is it possible to prevent onClick over AccordionItem title so users can click on buttons inside it?
This means I will control the expanded state.

Thank you

screen shot 2016-11-23 at 3 13 09 pm

onExpand doesn't handle specific item

onExpand doesn't return a key of accordion item, I want to know the slug key of expended accordion item.

I did it by my self just added to accordionItem/index.js

handleExpand() {
    const {onExpand, # slug} = this.props;

    this.startTransition();
    this.timeout = setTimeout(() => {
      this.setState({maxHeight: 'none', overflow: 'visible'});

      if (onExpand) {
        onExpand(# slug);
      }

    }, this.state.duration);
  }

Now onExpand callback is running with slug value.

Could you add that to repo?
Thanks.

Improve import in JavaScript ES6

When using ES6, it is required to write two lines of code to import the React components:

import ReactSanfona from 'react-sanfona';
const { Accordion, AccordionItem } = ReactSanfona;

It would be nice if this could be done in a more standard way, like this:

import { Accordion, AccordionItem } from 'react-sanfona';

E.g. like in react-grid-layout.

max-height causing problems

the max-height property on react-sanfona-item-body class is causing major problems in case anything needs to be expanded within the sanfona item body, or in case the browser window changes size and the body needs to accommodate for it, causing it to overflow.

When the page with my accordion loads it defaults to open the first one

When my accordion item loads it defaults to expanding the first item on the list. How can I prevent this (so that on load none of the accordion items are open)?

Thank you! I love this library otherwise :)

 <Accordion allowMultiple={false} onChange={this.onClickProject}>
            {projectLoop && projectLoop.map((instance, index) => {
              const titleBar = (
                  <div className="project-title" onClick={this.onClickProject}>
                    <span>{instance.name}</span>

                    <Link>
                      <span className="icon-height"style={{float: 'right'}} onClick={(evt) => {
                        this.props.fetchCollabs(instance);
                        hashHistory.push('/collabs');
                        evt.stopPropagation() // **LEAVE THIS HERE!** it makes sure we don't trigger AccordionItemTitle onClick of the icon
                      }}>
                      <i className="small material-icons">supervisor_account</i>
                      </span>
                    </Link>

                  </div>
                )
                return (
                    <AccordionItem title={titleBar} key={index} slug={index} className="card-panel left-justified-text">
                            {instance.commits && instance.commits.map((commit, index) => {
                              return (
                                <div className="item-commit-border" key={commit.id}
                                  onClick={() => {this.onClickCommit(index)}}>
                                  <div className="commit-message commit-color">{commit.message.slice(0, 20)}</div>
                                  <div className="item-commit-details"><span className="commit-message commit-info-font commit-date">{`On ${Moment(commit.date).format('MMMM Do')}`}</span><span className="commit-info-font">{`by ${commit.committer}`}</span></div>
                                </div>
                                )
                            })}
                    </AccordionItem>
                    );
                })}
        </Accordion>

FAQ - Testando components

@daviferreira 🎉

achei massa você testar o component em si, e não só a integração (Stores/Actions etc),

https://github.com/daviferreira/react-sanfona/blob/master/src/AccordionItemTest.jsx#L16-l51

vi muita gente dizendo que testar o componente em sí, não é muito viável (até relacionaram com teste end-2-end),

cheguei a trocar uma idéia com o Dan Abramov e até vi alguns argumentos do Ryan Florence, dizendo que, realmente, eles preferem testar outras partes ao invés do componente em si,

e, tirando uma conclusão de suíte de testes para app's em React:

  • Jest, ninguém recomenda
  • Karma, ótimo se você não puder evitar testes no DOM
  • Mocha, ótimo se você puder evitar testes no DOM

Estou caçando argumentos e exemplos para isso e tentar achar um mmc,

Atualmente, também uso Mocha, e testo apenas a integração e não o componente,

Queria sua opinião sobre 👍

Null AccordionItem

Same bug as I fixed long time ago. #107
1.0

Element of Accordion children array can be null and should be ignored.

#129

Cannot read property 'slug' of undefined

Hi.
Got a problem with displaying accordion, no matter what I do I always end up with an : Uncaught TypeError: Cannot read property 'slug' of undefined . If I replace accordion with my own component everything goes smoothly. If I click second time on the link to faqs I got : Uncaught TypeError: Cannot read property 'getHostNode' of null - ReactReconciler.js:64
Anyone ?

const faqsList = !isLoaded(faqs)
    ? 'Loading'
      : isEmpty(faqs)
    ? 'Faqs list is empty'
      : Object.keys(faqs).map(
          (key, id) => {
              <AccordionItem title={key} key={key} id={id} slug={key} >
                <div> {faqs[key]} </div>
              </AccordionItem>
          }
      )
return (
  <div>
    <h1>FAQS</h1>
      <Accordion
        allowMultiple={true}
      >
        {faqsList}
      </Accordion>
      <input type="text" ref="newFaq" />
      <button onClick={handleAdd}>
        Add
      </button>
  </div>
)

Add custom class and style support

eg:-

<AccordionItem 
   className={ styles.accordian }
   style={{ fontSize: '12px' }} 
   title={`Item ${ item }`} 
   key={item}
>
  ...
</AccordionItem>

separating AccordianItem from Accordian doesn't work

When I try to put the AccordianItem component separate from the Accordian component, the AccordianItem doesn't expand. For example, my render function of the AccordianItem is defined as:

import { AccordionItem } from 'react-sanfona';

export default class Learnable extends Component {

....

render() {
return (
      <AccordionItem title={this.props.tags[0]} key={this.props.learnableid}  >
          <div>
            {this.props.text}
          </div>
      </AccordionItem>
    );
  }
}

and then my Accordian is defined as:

import Learnable from './Learnable';
import { Accordion } from 'react-sanfona';

export default class LearnableList2 extends Component {

... 

render() {
    const { learnables } = this.props;
    const learnablesList = learnables.map((learnable) => <Learnable key={learnable.id} learnableid={learnable.id} text={learnable.text} tags={learnable.tags} />);
    return (
      <Accordion allowMultiple >
        {learnablesList}
      </Accordion>
    );
  }
}

When I do this, only the title of each AccordianItem shows up, but if I try to expand the item, it doesn't expand.

However, if I put the Accordian and AccordianItem in one file like you do in the demo examples, it works perfectly.

Is there anything I'm doing wrong?

Better docs

  • how to use as a module
  • how to use on browser
  • options

etc.

The collapse stop working according certain function

Everything was great before I try to use a callback function inside the onExpand prop of this module. When I call another function inherited from the parent component, simply, out of blue, the accordion doesn't work anymore. And as test I deleted the snippet to check if the accordion back to work again, and it works! Let's go to the code to clarify it better.

App.js


import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import './App.css';
import Materia from '../components/materia/Materia.js';
import Header from '../components/header/Header.js';
import auth from '../helpers/auth.js';

class App extends Component {
  constructor(props) { 
    super(props);
    this.state = {
      items: [],
      tipoMateria: ['video', 'artigos', 'galeria', 'outros'],
      headerExpanded: false,
    };

    axios.get('/data.json')
    .then(res => {
      this.setState({ items : res.data });
    });

    this.changeHeaderExpanded = this.changeHeaderExpanded.bind(this);
    }

  changeHeaderExpanded(headerExpanded) {
    this.setState({ headerExpanded });
  } 

  render() {
    return (
      <div className="">
        <Header headerExpanded={this.state.header} />
        <div className="container main-wrapper">
          <Materia items={this.state.items} headerExpanded={this.state.headerExpanded} changeHeaderExpanded={this.changeHeaderExpanded} />
        </div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("app"));

Materia.js

import React, { Component } from 'react';
import { Accordion, AccordionItem } from 'react-sanfona';
import style from './style.scss';
import HeaderComponent from './header_component/HeaderComponent.js';
import Content from './content/Content.js';
import Footer from './footer/Footer.js';

class Materia extends Component {
  constructor(props) {
    super(props);
    this.state = {
    };
    this.toggleContent = this.toggleContent.bind(this);
  }
  toggleContent() {
    console.log(this.props);
    this.props.changeHeaderExpanded(!this.props.headerExpanded);
  }

  render() {
    const Materias = this.props.items.map((item, key) => ( 
      <AccordionItem 
        title={
          <div className={style.container}>
            <div className={style.resume}>
              <span className={style.description}>fim de conflito</span><span className={style.descriptionTime}>Há 4 minutos</span>
            </div>
            <h1 className={style.title}>{item.title} </h1>
            <h3 className={style.preview}>{item.subtitle}</h3>
            <p> social network social network social network </p>
          </div>
        } key={key} onExpand={this.toggleContent} 
      >
        <HeaderComponent title={item.title} id={item.id} subtitle={item.subtitle} category={item.categoria} />
        <Content content={item.content[0]} />
        <Footer />
      </AccordionItem>
    )); 
    return (
      <Accordion activeItems={null} >
        {Materias}
      </Accordion>
    );
  }
}
export default Materia;

This work:

  toggleContent() {
    console.log(this.props);
  }

This don't

  toggleContent() {
    console.log(this.props);
    this.props.changeHeaderExpanded(!this.props.headerExpanded);
  }

onActiveItemsChange

It would be really useful to add an event handler that would trigger when a set of active items has changed. I was going to use it to save the state of the accordion to my global state objects so that the clients that are looking at the same page could always be in sync.

Could you please add this feature? There should not be much to write.

Create new release based on #83

The current latest release doesn't work in a module-less environment (i.e. included by a <script> tag) due to ReactDOM missing from webpack externals.
Would be nice to have a new release based on #83 so I could update my dependencies.

Thanks!

Only one accordion item at a time

When you implemented the new feature to allow for all items to be expanded on initial render, I think it broke your first example in your demo (which should constrain the accordion to only show one accordion item at a time, right?). Now, it behaves in the same way as your "Allow Multiple" example.

This is quickly becoming the best react accordion component imo. Keep it up!

Peer dependencies broken

I think this needs to be republished to NPM. The package.json I'm getting back after npm install has react and react-dom set to version 0.14.0, while the source on Github has it at ^0.14.2. This is preventing me from being able to try out your project since I have React 0.14.3, and the peer dependencies aren't being fulfilled.

Render Open Accordion

Is there a way (using props or something else) to set the Accordion so that all Accordion Items are showing open on page load? I see that there is a way to select a certain Item to render open on page load using the prop "selectedIndex", but that's not quite what I'm looking for. I need them to be all "open" when the page loads. Thanks in advance!

snapshot testing

There is an issue using this library with snapshot testing. The uuid created changes on each test run, and which is used as id and other attributes, so snapshot differs in each test run. Is there a way to make them deterministic, or a way to mock part of this library which varies on test run.

               <div
    -            aria-controls="react-sanfona-item-body-b63789ff-4a49-4f8f-9184-85127fc5e3e0"
    +            aria-controls="react-sanfona-item-body-f913643c-4ad1-4707-85dd-25d8364e2667"
                 className="react-sanfona-item-title"
    -            id="react-safona-item-title-b63789ff-4a49-4f8f-9184-85127fc5e3e0"
    +            id="react-safona-item-title-f913643c-4ad1-4707-85dd-25d8364e2667"
                 onClick={[Function]}>
                 <div

overflow always hidden when AccordeonItem has images

Hello

https://github.com/daviferreira/react-sanfona/blob/master/src/AccordionItem/index.js#L89

I have an AccordeonItem with images inside, tooltips, and <react-select> components.
It used to work in version 0.0.15. I've just updated to 0.0.4. Because of the line above, the tooltips and the <react-select> are always truncated because of the overflow.

Is there any reason for forcing this value to hidden instead of using a check like on:
https://github.com/daviferreira/react-sanfona/blob/master/src/AccordionItem/index.js#L76

?

Getting "Uncaught Error: Element type is invalid" on render

I'm getting this error on render
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of ...

I'm importing it like this: import { Accordian, AccordianItem } from 'react-sanfona'; and it seems as though both Accordian and AccordianItem are undefined. I've tried other ways of importing (seen in previous issues) but nothing seems to work.

I'm using version 0.1.0.

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.