0
\$\begingroup\$

React Grid-List View

React v16.3
Font Awesome 5

This program uses the React Context API to produce a responsive grid or table list using Zen Design styles and Font Awesome icons.

Notes:

  1. Zen Design is a work in progress, and is added to as more UI/UX programs are created. A compiled program that contains all of the styles will eventually be written .

/**
* Name:        Grid-List View
* Description: A React-based grid-list view using Zen Design styles
* @package     Chimera Apps
* @version     1.2.2
* @author      Chimera.Zen
* @copyright   Copyright (c) 2018, Chimera.Zen
* @link        https://github.com/ChimeraZen
* @license     http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/

const GridListViewContext = React.createContext()

class GridListViewProvider extends React.Component {
	render() {
  	return(
    	<GridListViewContext.Provider value={{state: this.props.state}}>
        {this.props.children}
      </GridListViewContext.Provider>
    )
  }
}

class GridView extends React.Component {
	constructor(props) {
  	super(props)
    this.state = {
    	isLoaded: false
    }
  }
  
	componentDidMount() {
    setTimeout(() => {
      this.setState({
      	isLoaded: true
      })
    },100)
  }
  
	render() {
    return (
      <div className={this.state.isLoaded ? "grid-list-view grid" : "grid-list-view grid loading"}>
        <GridListViewContext.Consumer>
          {(context) => (
            context.state.content.items.map(item => {
              return <div key={item.title} className="grid-item">
                <h3>{item.title}</h3>
                <p>{item.parent}</p>
              </div>
            })
          )}
        </GridListViewContext.Consumer>
      </div>
    )
  }
}

class ListView extends React.Component {
	constructor(props) {
  	super(props)
    this.state = {
    	isLoaded: false
    }
  }
  
	componentDidMount() {
    setTimeout(() => {
      this.setState({
      	isLoaded: true
      })
    },100)
  }
  
	render() {
  	return (
      <GridListViewContext.Consumer>
        {(context) => (
          <React.Fragment>
            <table className={this.state.isLoaded ? "grid-list-view list" : "grid-list-view list loading"}>
              <thead>
                <tr>
                  {Object.keys(context.state.content.items[0]).map(key => {
                  	return (
                    	<td key={key}>
                    	  <p>{key}</p>
                    	</td>
                    )
                  })}
                </tr>
              </thead>
              <tbody>
                {
                  context.state.content.items.map(item => {
                    return (
                      <tr key={item.title}>
                        {Object.keys(item).map(index => {
                          return (
                            <td key={item[index]}>
                              <p>{item[index]}</p>
                            </td>
                          )
                        })}
                      </tr>
                    )
                  })
                }
              </tbody>
            </table>
          </React.Fragment>
        )}
      </GridListViewContext.Consumer>
    )
  }
}

const GridListItems = () => {
  return (
    <GridListViewContext.Consumer>
      {(context) => (
        <React.Fragment>
          {context.state.listOptions.isListView
            ? <ListView />
            :	<GridView />
          }
        </React.Fragment>
      )}
    </GridListViewContext.Consumer>
  )
}

const GridListOptions = () => {
  return (
    <div className="grid-list-options">
      <GridListViewContext.Consumer>
        {(context) => (
          <React.Fragment>
            <i className={!context.state.listOptions.isListView ? "fas fa-th-large active" : "fas fa-th-large"} data-type="grid" onClick={context.state.listOptions.handleViewChange}></i>
            <i className={context.state.listOptions.isListView ? "fas fa-th-list active" : "fas fa-th-list"} data-type="list" onClick={context.state.listOptions.handleViewChange}></i>
          </React.Fragment>
        )}
      </GridListViewContext.Consumer>
    </div>
  )
}

const GridListHeader = (props) => {
  return (
  	<div className="grid-list-header">
      <h2>{props.title}</h2>
      <GridListOptions />
    </div>
  )
}

class GridListView extends React.Component {
	constructor() {
  	super()
    this.state = {
    	listOptions: {
        isListView: true,
        handleViewChange: (e) => {
          const view = e.target.getAttribute('data-type')
          const isListView = view === 'grid' ? false : true
          
          this.setState((prevState) => {
            return {
              listOptions: {
                ...prevState.listOptions, 
                isListView: isListView
              }
            }
          })
        }
      },
      content: {
        header: 'Categories',
        items: [
          {
            title: 'Archery',
            parent: false						// parent is false if list item is top-level
          },
          {
            title: 'Blacksmithing',
            parent: false
          },
          {
            title: 'Arrowheads',
            parent: 'Archery'
          },
          {
            title: 'Shafts',
            parent: 'Archery'
          },
          {
            title: 'Carbon Fiber',
            parent: 'Shafts'
          },
          {
            title: 'Plastic',
            parent: 'Shafts'
          },
          {
            title: 'Tongs',
            parent: 'Blacksmithing'
          },
          {
            title: 'Hammers',
            parent: 'Blacksmithing'
          },
          {
            title: 'Broadhead',
            parent: 'Arrowheads'
          },
          {
            title: 'Baseball',
            parent: false
          }
        ]
      }
    }
  }
  
	render() {
  	return (
      <GridListViewProvider state={this.state}>
        <div className="grid-list-view">
          <GridListHeader title={this.state.content.header}/>
          <GridListItems />
        </div>
      </GridListViewProvider>
    )
  }
}

const App = (props) => {
  return (
    <GridListView />
  )
}

ReactDOM.render(<App />, document.querySelector("#app"))
* {
  padding: 0;
  margin: 0;
}

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
  color: white;
}

.grid-list-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 5px;
  padding: 7px 10px;
  background: #2D333B;
}

.grid-list-options i {
  display: inline-flex;
  margin-right: 7px;
  padding: 1px;
  cursor: pointer;
  font-size: 20px;
  transition: all 0.1s ease-out;
}
.grid-list-options i.active {
  border-bottom: 1px solid deepskyblue;
}
.grid-list-options i:last-child {
  margin-right: 0;
}
.grid-list-options i:hover {
  color: #33abf4;
  transition: all 0.2s ease-in;
}

.grid-list-view {
  opacity: 1;
  transition: all 0.3s ease-in;
}
.grid-list-view.loading {
  opacity: 0;
  transition: all 0.3s ease-in;
}
.grid-list-view.list {
  margin-top: 10px;
  width: -webkit-fill-available;
}
.grid-list-view.list thead td {
  font-size: 18px;
  border-bottom: 1px solid #2D333B;
}
.grid-list-view.list thead td p {
  display: inline-block;
  margin-right: 10px;
  text-transform: capitalize;
}
.grid-list-view.list thead td i {
  cursor: pointer;
  transition: all 0.2s ease-in;
}
.grid-list-view.list thead td i:hover {
  color: #0571D6;
  transition: all 0.2s ease-in;
}
.grid-list-view.list td {
  padding: 0 10px;
}
.grid-list-view.grid {
  display: flex;
  flex-wrap: wrap;
  margin-top: 10px;
}
.grid-list-view.grid .grid-item {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 175px;
  min-height: 175px;
  margin: 0 5px 10px 5px;
  padding: 5px 10px;
  background: #4a586a;
  flex-grow: 1;
  flex-basis: 175px;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<link href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" rel="stylesheet" />
<div id="app"></div>

\$\endgroup\$
  • 1
    \$\begingroup\$ You have an error, line 24 in the jS section. Also, snippets support all Scripts... you use a script tag. <script src="https://unpkg.com/react@15.4.0/dist/react.js"></script> \$\endgroup\$ – FreezePhoenix May 15 '18 at 16:23
  • \$\begingroup\$ I see line 24 as class GridView extends React.Component {. Is that the line you're referring to? \$\endgroup\$ – Chimera.Zen May 15 '18 at 16:41
  • \$\begingroup\$ Yes. React is not defined \$\endgroup\$ – FreezePhoenix May 15 '18 at 16:47
  • \$\begingroup\$ Odd. I'm not getting that error. Everything seems to work fine for me. Do you have an idea why you're getting that error? Would that not also produce an error for the previous line const GridListViewContext = React.createContext() \$\endgroup\$ – Chimera.Zen May 15 '18 at 17:14
  • \$\begingroup\$ It appears you added the script tag - That would be why there is no error anymore. \$\endgroup\$ – FreezePhoenix May 15 '18 at 17:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.