diff options
author | lonkaars <l.leblansch@gmail.com> | 2021-01-16 11:40:36 +0100 |
---|---|---|
committer | lonkaars <l.leblansch@gmail.com> | 2021-01-16 11:40:36 +0100 |
commit | d2c2cc62a4c2e1ac10f8434bea7bb834da820869 (patch) | |
tree | d8d0ed49957d1103a0fd79d4bb2928d7e1b5846e /components | |
parent | be52cd3265f93b09fc400ecaa58cde0a93ed41e6 (diff) |
semi working next project
Diffstat (limited to 'components')
-rw-r--r-- | components/account.tsx | 16 | ||||
-rw-r--r-- | components/dialogBox.tsx | 30 | ||||
-rw-r--r-- | components/gameBar.tsx | 88 | ||||
-rw-r--r-- | components/gameSettings.tsx | 134 | ||||
-rw-r--r-- | components/logo.tsx | 28 | ||||
-rw-r--r-- | components/navbar.tsx | 63 | ||||
-rw-r--r-- | components/page.tsx | 32 | ||||
-rw-r--r-- | components/toast.tsx | 78 | ||||
-rw-r--r-- | components/ui.tsx | 132 | ||||
-rw-r--r-- | components/voerBord.tsx | 39 |
10 files changed, 640 insertions, 0 deletions
diff --git a/components/account.tsx b/components/account.tsx new file mode 100644 index 0000000..e6ec58f --- /dev/null +++ b/components/account.tsx @@ -0,0 +1,16 @@ +interface AccountAvatarProps { + size: number; + image: string; +} + +export function AccountAvatar(props: AccountAvatarProps) { + return <div style={{ + width: props.size, + height: props.size, + backgroundImage: props.image, + backgroundSize: "cover", + display: "inline-block" + }}/>; +} + + diff --git a/components/dialogBox.tsx b/components/dialogBox.tsx new file mode 100644 index 0000000..74fe99b --- /dev/null +++ b/components/dialogBox.tsx @@ -0,0 +1,30 @@ +import { ReactNode } from 'react'; + +import { Vierkant } from './ui'; + +import CancelIcon from '@material-ui/icons/Cancel'; + +interface DialogBoxProps { + children: ReactNode; + title: string; +} + +export function DialogBox(props: DialogBoxProps) { + return <Vierkant style={{ + position: "fixed", + top: "50%", left: "50%", + transform: "translate(-50%, -50%)", + boxShadow: "0 8px 32px -5px #0007", + width: 392 + }}> + <h2 style={{ marginBottom: 24 }}>{props.title}</h2> + <CancelIcon style={{ + position: "absolute", + top: 25, right: 25, + color: "var(--text)", + opacity: .85, + cursor: "pointer" + }}/> + {props.children} + </Vierkant> +} diff --git a/components/gameBar.tsx b/components/gameBar.tsx new file mode 100644 index 0000000..53eda88 --- /dev/null +++ b/components/gameBar.tsx @@ -0,0 +1,88 @@ +import { CSSProperties, ReactNode } from 'react'; +import { Vierkant } from './ui'; + +import SettingsRoundedIcon from '@material-ui/icons/SettingsRounded'; +import ExitToAppRoundedIcon from '@material-ui/icons/ExitToAppRounded'; +import NavigateNextRoundedIcon from '@material-ui/icons/NavigateNextRounded'; +import NavigateBeforeRoundedIcon from '@material-ui/icons/NavigateBeforeRounded'; + +interface GameBarModuleProps { + children?: ReactNode; +} + +function GameBarModule(props: GameBarModuleProps) { + return <Vierkant style={{ + backgroundColor: "var(--background-alt)", + padding: 12, + borderRadius: 6, + margin: 0, + verticalAlign: "top" + }}>{props.children}</Vierkant> +} + +var GameBarSpacer = () => <div style={{ width: 8, display: "inline-block" }}></div>; + +var GameBarAlignStyle: CSSProperties = { + display: "inline-block" +} + +export function GameBar() { + return <Vierkant className="gameBar" style={{ + padding: 8, + width: "calc(100% - 12px)" + }}> + <div style={{ gridAutoColumns: "auto" }}> + <div style={{ ...GameBarAlignStyle, float: "left" }}> + <div style={{ + width: 32, height: 32, + margin: 8, + backgroundColor: "var(--disk-b)", + borderRadius: 16, + display: "inline-block" + }}/> + <h2 style={{ + fontSize: 20, + margin: 12, + verticalAlign: "top", + display: "inline-block" + }}>Tegenstander</h2> + </div> + <div style={{ + ...GameBarAlignStyle, + position: "absolute", + top: "50%", left: "50%", + transform: "translate(-50%, -50%)" + }}> + <span style={{ + color: "var(--text)", + fontSize: 20, + opacity: .75 + }}>0-0</span> + </div> + <div style={{ ...GameBarAlignStyle, float: "right" }}> + <GameBarModule> + <SettingsRoundedIcon/> + </GameBarModule> + <GameBarSpacer/> + <GameBarModule> + <span style={{ + margin: "0 4px", + fontSize: 20 + }}>00:00</span> + </GameBarModule> + <GameBarSpacer/> + <GameBarModule> + <ExitToAppRoundedIcon/> + </GameBarModule> + <GameBarSpacer/> + <GameBarModule> + <NavigateBeforeRoundedIcon/> + </GameBarModule> + <GameBarSpacer/> + <GameBarModule> + <NavigateNextRoundedIcon/> + </GameBarModule> + </div> + </div> + </Vierkant>; +} diff --git a/components/gameSettings.tsx b/components/gameSettings.tsx new file mode 100644 index 0000000..fb5188e --- /dev/null +++ b/components/gameSettings.tsx @@ -0,0 +1,134 @@ +import { ReactNode, CSSProperties } from 'react'; + +import { Button, Vierkant, CheckBox, Input } from './ui'; +import { DialogBox } from './dialogBox'; + +import BuildRoundedIcon from '@material-ui/icons/BuildRounded'; + +export function CurrentGameSettings(/*props: CurrentGameSettingsProps*/) { + return <div style={{ + position: "relative", + height: 80 + }}> + <p style={{ + opacity: .75, + fontStyle: "italic", + userSelect: "none", + position: "absolute", + top: "50%", + left: 0, + transform: "translateY(-50%)" + }}> + Geen tijdslimiet<br/> + Standaardregels<br/> + Gerangschikt + </p> + <Button style={{ + width: 150, + position: "absolute", + top: "50%", + right: 0, + transform: "translateY(-50%)" + }}> + <BuildRoundedIcon style={{ fontSize: 48 }}/> + <span style={{ + fontWeight: 600, + position: "absolute", + right: 24, + top: "50%", + width: 85, + verticalAlign: "middle", + textAlign: "center", + transform: "translateY(-50%)", + userSelect: "none" + }}>Spelregels aanpassen</span> + </Button> + </div>; +} + +function GameSettingsSection(props: { + children?: ReactNode; + title: string; + state: boolean; + noMarginBottom?: boolean; +}) { + return <Vierkant style={{ + backgroundColor: "var(--background-alt)", + width: "100%", + padding: 16, + margin: 0, + marginBottom: props.noMarginBottom ? 0 : 24 + }}> + <span style={{ + verticalAlign: "top", + fontSize: 14, + fontWeight: 600 + }}>{props.title}</span> + <CheckBox state={props.state} style={{ + verticalAlign: "top", + float: "right", + margin: -3 + }}/> + <div>{props.children}</div> + </Vierkant> +} + +function GameRule(props: { + title: string; + description: string; + style?: CSSProperties; +}) { + return <div style={{ + backgroundColor: "var(--page-background)", + borderRadius: 8, + padding: "16px 0", + textAlign: "center", + ...props.style + }}> + <h1 style={{ color: "var(--disk-a)", fontSize: 42 }}>{props.title}</h1> + <p style={{ color: "var(--text-alt)", maxWidth: 250, margin: "0 auto" }}>{props.description}</p> + </div>; +} + +export function EditGameSettings() { + return <DialogBox title="Spelregels aanpassen"> + <div style={{ + marginTop: 24, + maxHeight: 500, + overflowY: "scroll", + borderRadius: 8 + }}> + <GameSettingsSection title="Tijdslimiet" state={false}> + <div style={{ + display: "grid", + gridTemplateColumns: "1fr 1fr 1fr", + gridGap: 16, + margin: "16px 0" + }}> + <Input type="number" label="min"/> + <Input type="number" label="sec"/> + <Input type="number" label="plus"/> + </div> + <CheckBox state={false}/> + <span style={{ + verticalAlign: "super", + marginLeft: 4 + }}>Timer gebruiken voor bijde spelers</span> + </GameSettingsSection> + <GameSettingsSection title="Regelset" state={false}> + <div style={{ + display: "grid", + gridTemplateColumns: "1fr 1fr", + gridGap: 16, + margin: "16px 0" + }}> + <GameRule title="+2" description="Extra kolommen"/> + <GameRule title="+4" description="Extra kolommen"/> + </div> + <GameRule style={{ marginBottom: 16 }} title="Gravity" description="De zwaartekracht draait soms"/> + <GameRule title="Flashlight" description="Het veld wordt opgelicht door de vallende fiches"/> + </GameSettingsSection> + <GameSettingsSection title="Gerangschikt spel" state={true} noMarginBottom/> + </div> + </DialogBox>; +} diff --git a/components/logo.tsx b/components/logo.tsx new file mode 100644 index 0000000..b0f358f --- /dev/null +++ b/components/logo.tsx @@ -0,0 +1,28 @@ +export function LogoDark() { + return ( + <div className="noclick"> + <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <rect width="24" height="24" fill="var(--background)"/> + <circle cx="6.5" cy="6.5" r="4.5" fill="var(--disk-b)"/> + <circle cx="6.5" cy="17.5" r="4.5" fill="var(--disk-a)"/> + <circle cx="17.5" cy="17.5" r="4.5" fill="var(--disk-b)"/> + <circle cx="17.5" cy="6.5" r="3.5" stroke="var(--text)" strokeWidth="2"/> + </svg> + </div> + ); +} + +export function LogoLight() { + return ( + <div className="noclick"> + <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <rect width="24" height="24" fill="var(--page-background)"/> + <circle cx="6.5" cy="6.5" r="4.5" fill="var(--disk-b)"/> + <circle cx="6.5" cy="17.5" r="4.5" fill="var(--disk-a)"/> + <circle cx="17.5" cy="17.5" r="4.5" fill="var(--disk-b)"/> + <circle cx="17.5" cy="6.5" r="3.5" stroke="var(--background)" strokeWidth="2"/> + </svg> + </div> + ); +} + diff --git a/components/navbar.tsx b/components/navbar.tsx new file mode 100644 index 0000000..7725ca8 --- /dev/null +++ b/components/navbar.tsx @@ -0,0 +1,63 @@ +import { CSSProperties } from "react"; + +import { LogoDark } from "../components/logo"; + +import Home from '@material-ui/icons/Home'; +import VideogameAssetIcon from '@material-ui/icons/VideogameAsset'; +import ExtensionIcon from '@material-ui/icons/Extension'; +import SearchIcon from '@material-ui/icons/Search'; +import SettingsIcon from '@material-ui/icons/Settings'; +import PersonIcon from '@material-ui/icons/Person'; + +var NavBarItemStyle: CSSProperties = { + margin: 12, + marginBottom: 16, + display: "block" +} + +export function NavBar() { + return ( + <div className="navbar" style={{ + width: 48, + height: "100%", + + lineHeight: 0, + + backgroundColor: "var(--background)", + display: "inline-block", + + position: "fixed", + top: 0, + left: 0, + + overflow: "hidden", + whiteSpace: "nowrap" + }}> + <div style={NavBarItemStyle}><LogoDark/></div> + <a href="/" style={NavBarItemStyle}><Home/></a> + <a href="/game" style={NavBarItemStyle}><VideogameAssetIcon/></a> + <a href="/" style={NavBarItemStyle}><ExtensionIcon/></a> + <a href="/" style={NavBarItemStyle}><SearchIcon/></a> + + <div style={{ + position: "absolute", + bottom: -4, + left: 0, + backgroundColor: "var(--background)" + }}> + <a href="/login" style={NavBarItemStyle}> + <div style={{ + width: 24, + height: 24, + /* background: "#888888", */ + borderRadius: 12 + }}> + <PersonIcon/> + </div> + </a> + <a href="/settings" style={NavBarItemStyle}><SettingsIcon/></a> + </div> + </div> + ); +} + diff --git a/components/page.tsx b/components/page.tsx new file mode 100644 index 0000000..d8a4a2b --- /dev/null +++ b/components/page.tsx @@ -0,0 +1,32 @@ +import { Component, CSSProperties, ReactNode } from 'react'; + +interface CenteredPageProps { + width?: number; + children?: ReactNode; + style?: CSSProperties; +} + +export function CenteredPage (props: CenteredPageProps) { + return <div className="CenteredPageOuter" style={{ + maxWidth: props.width, + margin: "0 auto" + }}> + <div className="CenteredPageInner" style={{ + margin: "0 6px", + lineHeight: 0, + ...props.style + }}>{props.children}</div> + </div>; +} + +export class PageTitle extends Component { + render () { + return <h1 style={{ + color: "var(--text-alt)", + marginLeft: 6, + marginTop: 32, + marginBottom: 64, + fontSize: 25, + }}>{this.props.children}</h1>; + } +} diff --git a/components/toast.tsx b/components/toast.tsx new file mode 100644 index 0000000..1d467bd --- /dev/null +++ b/components/toast.tsx @@ -0,0 +1,78 @@ +import { CSSProperties, ReactNode, Component } from "react"; + +import CloseIcon from '@material-ui/icons/Close'; + +export function ToastArea(props: { + style?: CSSProperties + children?: ReactNode +}) { + return <div id="ToastArea" style={{ + position: "fixed", + whiteSpace: "nowrap", + bottom: 12, + left: "50%", + transform: "translateX(-50%)", + zIndex: 1, + maxWidth: 600, + width: "calc(100% - 48px - 48px)", + margin: "0 24px", + ...props.style + }}>{props.children}</div> +} + +export class Toast extends Component<{ + text?: string + icon?: ReactNode + children?: ReactNode + type?: "normal"|"confirmation"|"error" + style?: CSSProperties +}> { + state = { render: true } + + close = () => this.setState({ render: false }) + + render () { + if (!this.state.render) return null; + return <div style={{ + padding: 0, + marginBottom: 12, + borderRadius: 8, + color: "var(--text)", + boxShadow: "0 8px 12px -4px #00000033", + backgroundColor: + this.props.type === "normal" ? "var(--background)" : + this.props.type === "confirmation" ? "var(--disk-a)" : + this.props.type === "error" ? "var(--disk-b)" : "var(--background)", + ...this.props.style + }}> + { + this.props.children ? + this.props.children : + <div style={{ lineHeight: 0 }}> + <div style={{ + fontSize: 0, + margin: 16, + display: "inline-block", + verticalAlign: "top", + width: 32, height: 32 + }}>{this.props.icon}</div> + <h2 style={{ + margin: "20px 0", + display: "inline-block", + width: "calc(100% - 128px)", + verticalAlign: "top", + fontSize: 20 + }}>{this.props.text}</h2> + <div style={{ + padding: 20, + display: "inline-block", + cursor: "pointer" + }} onClick={this.close}> + <CloseIcon style={{ fontSize: 24 }}/> + </div> + </div> + } + </div> + } +} + diff --git a/components/ui.tsx b/components/ui.tsx new file mode 100644 index 0000000..3afd97a --- /dev/null +++ b/components/ui.tsx @@ -0,0 +1,132 @@ +import { Component, CSSProperties, ReactNode } from "react"; + +import SearchIcon from '@material-ui/icons/Search'; +import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'; +import CheckBoxIcon from '@material-ui/icons/CheckBox'; + +export function Vierkant(props: { + href?: string; + width?: string; + height?: string; + style?: CSSProperties; + children?: ReactNode; + className?: string; }) +{ + return <a style={{ + padding: 24, + backgroundColor: "var(--background)", + borderRadius: 8, + color: "var(--text)", + margin: 6, // geen margin collapse = 12px marge + display: "inline-block", + position: "relative", + boxSizing: "border-box", + width: props.width ? props.width : undefined, + height: props.height ? props.height : undefined, + ...props.style + }} href={props.href} className={props.className}>{props.children}</a> +} + +export function Button(props: { + text?: string; + children?: ReactNode; + style?: CSSProperties; + href?: string; + onclick?: (() => void); }) +{ + return <a onClick={props.onclick} href={props.href} style={{ + padding: props.text ? 8 : 16, + textAlign: props.text ? "center" : "left", + borderRadius: 8, + backgroundColor: "var(--disk-a)", + cursor: "pointer", + position: "relative", + textDecoration: "none", + display: "block", + ...props.style + }}> + { + props.text ? + <span style={{ + fontWeight: 600, + userSelect: "none" + }}>{props.text}</span> + : undefined + } + { props.children } + </a>; +} + +export function Input(props: { + label?: string, + style?: CSSProperties, + type?: string, + id?: string +}) { + return <input id={props.id} type={props.type || "text"} placeholder={props.label} spellCheck={false} style={{ + padding: 12, + border: 0, + width: "calc(100% - 24px)", + fontSize: 14, + backgroundColor: "var(--page-background)", + color: "var(--text-alt)", + borderRadius: 8, + fontFamily: "Inter", + ...props.style + }}/> +} + +export function SearchBar(props: { label?: string }) { + return <div style={{ + marginTop: 24, + borderRadius: 8, + overflow: "hidden", + width: "100%" + }}> + <Input label={props.label} style={{ + width: "calc(100% - 24px - 41px)", + borderTopRightRadius: 0, + borderBottomRightRadius: 0 + }}/> + <div style={{ + width: 41, + height: 41, + backgroundColor: "var(--disk-a)", + display: "inline-block", + verticalAlign: "top", + position: "relative" + }}> + <SearchIcon style={{ + fontSize: 24, + position: "absolute", + top: "50%", left: "50%", + transform: "translate(-50%, -50%)" + }}/> + </div> + </div> +} + +export class CheckBox extends Component<{ + state?: boolean, + style?: CSSProperties +}> { + state = { on: this.props.state || false } + public toggle = () => this.setState({ on: !this.state.on }) + + render() { + return <div onClick={this.toggle} style={{ + ...this.props.style, + display: "inline-block", + cursor: "pointer" + }}> + { + this.state.on ? + <CheckBoxIcon style={{ fontSize: 24 }}/> : + <CheckBoxOutlineBlankIcon style={{ fontSize: 24 }}/> + } + </div>; + } +} + + + diff --git a/components/voerBord.tsx b/components/voerBord.tsx new file mode 100644 index 0000000..3e319a1 --- /dev/null +++ b/components/voerBord.tsx @@ -0,0 +1,39 @@ +interface VoerBordProps { + width: number; + height: number; +} + +export function VoerBord(props: VoerBordProps) { + return <table style={{ + borderSpacing: 8, + width: "100%" + }}> + <tbody> + { + [...Array(props.height)].map(() => ( + <tr> + {[...Array(props.width)].map(() => ( + <td style={{ + position: "relative", + width: "100%", + padding: 0 + }}> + <div style={{ + display: "block", + marginTop: "100%" + }}/> + <div style={{ + position: "absolute", + top: 0, left: 0, right: 0, bottom: 0, + borderRadius: 6, + border: "2px solid var(--background-alt)", + opacity: .5 + }}/> + </td> + ))} + </tr> + )) + } + </tbody> + </table> +} |