Skip to content

Instantly share code, notes, and snippets.

@waynevanson
Created August 17, 2019 04:29
Show Gist options
  • Save waynevanson/a127c64e168076e5bf4a254deee57fc2 to your computer and use it in GitHub Desktop.
Save waynevanson/a127c64e168076e5bf4a254deee57fc2 to your computer and use it in GitHub Desktop.
Paper theme for tsx
// content.tsx
import React, { FC } from 'react'
import { createStyles } from '@material-ui/styles'
import { Paper, AppBar, Toolbar, Grid, TextField, Button, Tooltip, IconButton, Typography, Theme, withStyles } from '@material-ui/core'
import { Search, Refresh } from '@material-ui/icons'
const styles = (theme: Theme) =>
createStyles({
paper: {
maxWidth: 936,
margin: 'auto',
overflow: 'hidden'
},
searchBar: {
borderBottom: '1px solid rgba(0, 0, 0, 0.12)'
},
searchInput: {
fontSize: theme.typography.fontSize
},
block: {
display: 'block'
},
addUser: {
marginRight: theme.spacing(1)
},
contentWrapper: {
margin: '40px 16px'
}
})
const Content: FC<{ classes: any }> = props => {
const { classes } = props
return (
<Paper className={classes.paper}>
<AppBar className={classes.searchBar} position="static" color="default" elevation={0}>
<Toolbar>
<Grid container spacing={2} alignItems="center">
<Grid item>
<Search className={classes.block} color="inherit" />
</Grid>
<Grid item xs>
<TextField
fullWidth
placeholder="Search by email address, phone number, or user UID"
InputProps={{
disableUnderline: true,
className: classes.searchInput
}}
/>
</Grid>
<Grid item>
<Button variant="contained" color="primary" className={classes.addUser}>
Add user
</Button>
<Tooltip title="Reload">
<IconButton>
<Refresh className={classes.block} color="inherit" />
</IconButton>
</Tooltip>
</Grid>
</Grid>
</Toolbar>
</AppBar>
<div className={classes.contentWrapper}>
<Typography color="textSecondary" align="center">
No users for this project yet
</Typography>
</div>
</Paper>
)
}
export default withStyles(styles)(Content)
// header.tsx
import React, { FC } from 'react'
import { Theme, createStyles, AppBar, Toolbar, Grid, Hidden, IconButton, Typography, Tooltip, Avatar, Button, Tabs, Tab } from '@material-ui/core'
import { withStyles } from '@material-ui/styles'
import { Notifications, Menu, Help } from '@material-ui/icons'
const lightColor = 'rgba(255, 255, 255, 0.7)'
const styles = (theme: Theme) =>
createStyles({
secondaryBar: {
zIndex: 0
},
menuButton: {
marginLeft: -theme.spacing(1)
},
iconButtonAvatar: {
padding: 4
},
link: {
textDecoration: 'none',
color: lightColor,
'&:hover': {
color: theme.palette.common.white
}
},
button: {
borderColor: lightColor
}
})
const Header: FC<{ classes: any; onDrawerToggle: any }> = props => {
const { classes, onDrawerToggle } = props
return (
<React.Fragment>
<AppBar color="primary" position="sticky" elevation={0}>
<Toolbar>
<Grid container spacing={1} alignItems="center">
<Hidden smUp>
<Grid item>
<IconButton color="inherit" aria-label="open drawer" onClick={onDrawerToggle} className={classes.menuButton}>
<Menu />
</IconButton>
</Grid>
</Hidden>
<Grid item xs />
<Grid item>
<Typography className={classes.link} component="a">
Go to docs
</Typography>
</Grid>
<Grid item>
<Tooltip title="Alerts • No alters">
<IconButton color="inherit">
<Notifications />
</IconButton>
</Tooltip>
</Grid>
<Grid item>
<IconButton color="inherit" className={classes.iconButtonAvatar}>
<Avatar className={classes.avatar} src="/static/images/avatar/1.jpg" alt="My Avatar" />
</IconButton>
</Grid>
</Grid>
</Toolbar>
</AppBar>
<AppBar component="div" className={classes.secondaryBar} color="primary" position="static" elevation={0}>
<Toolbar>
<Grid container alignItems="center" spacing={1}>
<Grid item xs>
<Typography color="inherit" variant="h5" component="h1">
Authentication
</Typography>
</Grid>
<Grid item>
<Button className={classes.button} variant="outlined" color="inherit" size="small">
Web setup
</Button>
</Grid>
<Grid item>
<Tooltip title="Help">
<IconButton color="inherit">
<Help />
</IconButton>
</Tooltip>
</Grid>
</Grid>
</Toolbar>
</AppBar>
<AppBar component="div" className={classes.secondaryBar} color="primary" position="static" elevation={0}>
<Tabs value={0} textColor="inherit">
<Tab textColor="inherit" label="Users" />
<Tab textColor="inherit" label="Sign-in method" />
<Tab textColor="inherit" label="Templates" />
<Tab textColor="inherit" label="Usage" />
</Tabs>
</AppBar>
</React.Fragment>
)
}
export default withStyles(styles)(Header)
// navigator.tsx
import React, { FC } from 'react'
import { Theme, createStyles, Drawer, List, ListItem, ListItemIcon, ListItemText, Divider } from '@material-ui/core'
import { withStyles } from '@material-ui/styles'
import {
People,
DnsRounded,
PermMediaOutlined,
Public,
SettingsEthernet,
SettingsInputComponent,
Settings,
Timer,
PhonelinkSetup,
Home
} from '@material-ui/icons'
import clsx from 'clsx'
import { DrawerProps } from '@material-ui/core/Drawer'
const categories = [
{
id: 'Develop',
children: [
{ id: 'Authentication', icon: <People />, active: true },
{ id: 'Database', icon: <DnsRounded /> },
{ id: 'Storage', icon: <PermMediaOutlined /> },
{ id: 'Hosting', icon: <Public /> },
{ id: 'Functions', icon: <SettingsEthernet /> },
{ id: 'ML Kit', icon: <SettingsInputComponent /> }
]
},
{
id: 'Quality',
children: [{ id: 'Analytics', icon: <Settings /> }, { id: 'Performance', icon: <Timer /> }, { id: 'Test Lab', icon: <PhonelinkSetup /> }]
}
]
const styles = (theme: Theme) =>
createStyles({
categoryHeader: {
paddingTop: theme.spacing(2),
paddingBottom: theme.spacing(2)
},
categoryHeaderPrimary: {
color: theme.palette.common.white
},
item: {
paddingTop: 1,
paddingBottom: 1,
color: 'rgba(255, 255, 255, 0.7)',
'&:hover,&:focus': {
backgroundColor: 'rgba(255, 255, 255, 0.08)'
}
},
itemCategory: {
backgroundColor: '#232f3e',
boxShadow: '0 -1px 0 #404854 inset',
paddingTop: theme.spacing(2),
paddingBottom: theme.spacing(2)
},
firebase: {
fontSize: 24,
color: theme.palette.common.white
},
itemActiveItem: {
color: '#4fc3f7'
},
itemPrimary: {
fontSize: 'inherit'
},
itemIcon: {
minWidth: 'auto',
marginRight: theme.spacing(2)
},
divider: {
marginTop: theme.spacing(2)
}
})
interface NavigatorProps {
classes: any
drawerProps: DrawerProps
}
const Navigator: FC<NavigatorProps> = props => {
const { classes, drawerProps } = props
return (
<Drawer variant="permanent" {...drawerProps}>
<List disablePadding>
<ListItem className={clsx(classes.firebase, classes.item, classes.itemCategory)}>Paperbase</ListItem>
<ListItem className={clsx(classes.item, classes.itemCategory)}>
<ListItemIcon className={classes.itemIcon}>
<Home />
</ListItemIcon>
<ListItemText
classes={{
primary: classes.itemPrimary
}}
>
Project Overview
</ListItemText>
</ListItem>
{categories.map(({ id, children }) => (
<React.Fragment key={id}>
<ListItem className={classes.categoryHeader}>
<ListItemText
classes={{
primary: classes.categoryHeaderPrimary
}}
>
{id}
</ListItemText>
</ListItem>
{children.map(({ id: childId, icon, active }) => (
<ListItem key={childId} button className={clsx(classes.item, active && classes.itemActiveItem)}>
<ListItemIcon className={classes.itemIcon}>{icon}</ListItemIcon>
<ListItemText
classes={{
primary: classes.itemPrimary
}}
>
{childId}
</ListItemText>
</ListItem>
))}
<Divider className={classes.divider} />
</React.Fragment>
))}
</List>
</Drawer>
)
}
export default withStyles(styles)(Navigator)
// paperbase.tsx
import React from 'react'
import { createMuiTheme, withStyles } from '@material-ui/core/styles'
import { ThemeProvider, createStyles } from '@material-ui/styles'
import CssBaseline from '@material-ui/core/CssBaseline'
import Hidden from '@material-ui/core/Hidden'
import Navigator from './navigator'
import Content from './content'
import Header from './header'
let theme = createMuiTheme({
typography: {
h5: {
fontWeight: 500,
fontSize: 26,
letterSpacing: 0.5
}
},
palette: {
primary: {
light: '#63ccff',
main: '#009be5',
dark: '#006db3'
}
},
shape: {
borderRadius: 8
}
})
theme = {
...theme,
overrides: {
MuiDrawer: {
paper: {
backgroundColor: '#18202c'
}
},
MuiButton: {
label: {
textTransform: 'none'
},
contained: {
boxShadow: 'none',
'&:active': {
boxShadow: 'none'
}
}
},
MuiTabs: {
root: {
marginLeft: theme.spacing(1)
},
indicator: {
height: 3,
borderTopLeftRadius: 3,
borderTopRightRadius: 3,
backgroundColor: theme.palette.common.white
}
},
MuiTab: {
root: {
textTransform: 'none',
margin: '0 16px',
minWidth: 0,
padding: 0,
[theme.breakpoints.up('md')]: {
padding: 0,
minWidth: 0
}
}
},
MuiIconButton: {
root: {
padding: theme.spacing(1)
}
},
MuiTooltip: {
tooltip: {
borderRadius: 4
}
},
MuiDivider: {
root: {
backgroundColor: '#404854'
}
},
MuiListItemText: {
primary: {
fontWeight: theme.typography.fontWeightMedium
}
},
MuiListItemIcon: {
root: {
color: 'inherit',
marginRight: 0,
'& svg': {
fontSize: 20
}
}
},
MuiAvatar: {
root: {
width: 32,
height: 32
}
}
},
props: {
MuiTab: {
disableRipple: true
}
},
mixins: {
...theme.mixins,
toolbar: {
minHeight: 48
}
}
}
const drawerWidth = 256
const styles = createStyles({
root: {
display: 'flex',
minHeight: '100vh'
},
drawer: {
[theme.breakpoints.up('sm')]: {
width: drawerWidth,
flexShrink: 0
}
},
appContent: {
flex: 1,
display: 'flex',
flexDirection: 'column'
},
mainContent: {
flex: 1,
padding: '48px 36px 0',
background: '#eaeff1'
}
})
class Paperbase extends React.Component<{ classes: any }, { mobileOpen: boolean }> {
state = {
mobileOpen: true
}
handleDrawerToggle = () => {
this.setState(state => ({ mobileOpen: !state.mobileOpen }))
}
render() {
const { classes } = this.props
return (
<ThemeProvider theme={theme}>
<div className={classes.root}>
<CssBaseline />
<nav className={classes.drawer}>
<Hidden smUp implementation="js">
<Navigator drawerProps={{ style: { width: drawerWidth }, variant: 'temporary', open: this.state.mobileOpen, onClose: this.handleDrawerToggle }} />
</Hidden>
<Hidden xsDown implementation="css">
<Navigator drawerProps={{ style: { width: drawerWidth } }} />
</Hidden>
</nav>
<div className={classes.appContent}>
<Header onDrawerToggle={this.handleDrawerToggle} />
<main className={classes.mainContent}>
<Content />
</main>
</div>
</div>
</ThemeProvider>
)
}
}
export default withStyles(styles)(Paperbase)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment