UNPKG

ndla-ui

Version:

UI component library for NDLA.

172 lines (160 loc) 5.29 kB
import React, { Component, Fragment } from 'react'; import BEMHelper from 'react-bem-helper'; import PropTypes from 'prop-types'; import { injectT } from 'ndla-i18n'; import { ChevronDown, ChevronUp } from 'ndla-icons/common'; import Modal, { ModalBody, ModalHeader, ModalCloseButton } from 'ndla-modal'; import Button from 'ndla-button'; import { OneColumn } from '../Layout'; import SafeLink from '../common/SafeLink'; const wrapperClasses = BEMHelper('c-frontpage-subjects-wrapper'); const sectionClasses = BEMHelper('c-frontpage-subjects-section'); export const FrontpageSubjectsSection = injectT( ({ name, subjects, linkToAbout, expanded, onExpand, id, t }) => { const getItems = (disable = false) => subjects.map(subject => ( <li key={subject.url} {...sectionClasses('item')}> <SafeLink tabIndex={disable ? '-1' : null} to={subject.url} {...sectionClasses('link')} aria-label={`${subject.text} ${subject.yearInfo}`}> <span {...sectionClasses('text')}>{subject.text}</span> {subject.yearInfo && ( <span {...sectionClasses('year-info')}>{subject.yearInfo}</span> )} </SafeLink> {subject.beta && ( <Modal narrow containerClass={sectionClasses('beta-label-container').className} activateButton={ <Button lighter {...sectionClasses('beta-label')} aria-label={t('subjectPage.subjectIsBeta.dialogHeader', { title: subject.text, })}> {t('subjectPage.subjectIsBeta.iconLabel')} </Button> }> {onClose => ( <Fragment> <ModalHeader> <ModalCloseButton onClick={onClose} title={t('modal.closeModal')} /> </ModalHeader> <ModalBody> <h1> {t('subjectPage.subjectIsBeta.dialogHeader', { title: subject.text, })} </h1> <hr /> <p> {t('subjectPage.subjectIsBeta.dialogText')} {linkToAbout} </p> </ModalBody> </Fragment> )} </Modal> )} </li> )); return ( <nav {...sectionClasses('', { expanded })}> <h1 {...sectionClasses('heading')}> <button type="button" onClick={() => { onExpand(!expanded); }} {...sectionClasses('expand-button')} aria-expanded={expanded} aria-controls={id}> <span {...sectionClasses('expand-button-text')}>{name}</span> {expanded ? <ChevronUp /> : <ChevronDown />} </button> <span {...sectionClasses('heading-text')}>{name}</span> </h1> <ul {...sectionClasses('subjects', 'wide')}>{getItems()}</ul> <ul {...sectionClasses('subjects', 'narrow')} id={id} aria-hidden={!expanded}> {getItems(!expanded)} </ul> </nav> ); }, ); FrontpageSubjectsSection.propTypes = { id: PropTypes.string.isRequired, expanded: PropTypes.bool.isRequired, onExpand: PropTypes.func.isRequired, name: PropTypes.string.isRequired, linkToAbout: PropTypes.node.isRequired, subjects: PropTypes.arrayOf( PropTypes.shape({ url: PropTypes.string.isRequired, text: PropTypes.string.isRequired, yearInfo: PropTypes.string, }), ), }; export class FrontpageSubjects extends Component { constructor(props) { super(props); this.state = { expanded: props.expanded, }; } render() { const { categories, linkToAbout, t } = this.props; return ( <OneColumn wide noPadding> <div {...wrapperClasses()}> {categories.map(category => ( <FrontpageSubjectsSection key={category.name} expanded={this.state.expanded === category.name} onExpand={expanded => { this.setState({ expanded: expanded ? category.name : undefined, }); }} id={category.name} name={t(`welcomePage.category.${category.name}`)} subjects={category.subjects} linkToAbout={linkToAbout} /> ))} </div> </OneColumn> ); } } FrontpageSubjects.propTypes = { t: PropTypes.func.isRequired, expanded: PropTypes.string, categories: PropTypes.arrayOf( PropTypes.shape({ name: PropTypes.isRequired, subjects: PropTypes.arrayOf( PropTypes.shape({ url: PropTypes.string.isRequired, text: PropTypes.string.isRequired, yearInfo: PropTypes.string, beta: PropTypes.bool, }), ), }), ), linkToAbout: PropTypes.node.isRequired, }; FrontpageSubjects.defaultProps = { expanded: undefined, }; export default injectT(FrontpageSubjects);