From af796b465c66a61b498facff010b372a52a24508 Mon Sep 17 00:00:00 2001
From: lonkaars <l.leblansch@gmail.com>
Date: Sun, 18 Apr 2021 14:28:53 +0200
Subject: wip dialog box

---
 components/gameSettings.tsx | 363 +++++++++++++++++++++-----------------------
 1 file changed, 173 insertions(+), 190 deletions(-)

(limited to 'components/gameSettings.tsx')

diff --git a/components/gameSettings.tsx b/components/gameSettings.tsx
index f562e5d..3c3a699 100644
--- a/components/gameSettings.tsx
+++ b/components/gameSettings.tsx
@@ -1,5 +1,5 @@
 import axios from 'axios';
-import { Component, CSSProperties, ReactNode } from 'react';
+import { Component, CSSProperties, ReactNode, useEffect, useState } from 'react';
 
 import { ruleset, userPreferences } from '../api/api';
 import { DialogBox } from './dialogBox';
@@ -7,106 +7,93 @@ import { Button, CheckBox, Input, Vierkant } from './ui';
 
 import BuildOutlinedIcon from '@material-ui/icons/BuildOutlined';
 
-type CurrentGameSettingsStateType = {
-	editGameRulesDialogVisible: boolean;
-	ruleset: ruleset;
-};
-
-export class CurrentGameSettings extends Component {
-	state: CurrentGameSettingsStateType = {
-		editGameRulesDialogVisible: false,
-		ruleset: {
-			timelimit: {
-				enabled: false,
-				shared: false,
-			},
-			ranked: false,
+export function CurrentGameSettings() {
+	var [editGameRulesDialogVisible, setEditGameRulesDialogVisible] = useState(false);
+	var [ruleset, setRuleset] = useState<ruleset>({
+		timelimit: {
+			enabled: false,
+			shared: false,
+			minutes: 0,
+			seconds: 0,
+			addmove: 0,
 		},
-	};
-
-	constructor(props: {}) {
-		super(props);
+		ranked: false,
+	});
 
-		if (typeof window === 'undefined') return; // return if run on server
-
-		axios.request<userPreferences>({
+	useEffect(() => {
+		axios.request<{ preferences: userPreferences; }>({
 			method: 'get',
 			url: `/api/user/preferences`,
 			headers: { 'content-type': 'application/json' },
 		})
-			// FIXME: this assumes the request ruleset has all properties of a ruleset
-			.then(request => this.setState({ ruleset: request.data.ruleset || this.state.ruleset }))
+			.then(request => setRuleset(request.data.preferences.ruleset))
 			.catch(() => {});
-	}
+	}, []);
 
-	showEditGameRules = () => this.setState({ editGameRulesDialogVisible: true });
-	hideEditGameRules = () => this.setState({ editGameRulesDialogVisible: false });
-	setGameRules = (newRules: ruleset) => this.setState({ ruleset: newRules });
+	/* showEditGameRules = () => this.setState({ editGameRulesDialogVisible: true }); */
+	/* hideEditGameRules = () => this.setState({ editGameRulesDialogVisible: false }); */
+	/* setGameRules = (newRules: ruleset) => this.setState({ ruleset: newRules }); */
 
-	render() {
-		var timelimit_str = this.state.ruleset.timelimit.enabled
-			? `${this.state.ruleset.timelimit.minutes}m${this.state.ruleset.timelimit.seconds}s plus ${this.state.ruleset.timelimit.addmove}`
-			: 'Geen tijdslimiet';
-		var ranked_str = this.state.ruleset.ranked
-			? 'Gerangschikt'
-			: 'Niet gerangschikt';
-		return <div
+	var timelimit_str = ruleset.timelimit.enabled
+		? `${ruleset.timelimit.minutes}m${ruleset.timelimit.seconds}s plus ${ruleset.timelimit.addmove}`
+		: 'Geen tijdslimiet';
+	var ranked_str = ruleset.ranked
+		? 'Gerangschikt'
+		: 'Niet gerangschikt';
+	return <div
+		style={{
+			position: 'relative',
+			height: 80,
+			overflow: 'visible',
+			zIndex: 1,
+		}}
+	>
+		<p
+			className='subtile nosel posabs'
 			style={{
-				position: 'relative',
-				height: 80,
-				overflow: 'visible',
-				zIndex: 1,
+				top: '50%',
+				left: 0,
+				transform: 'translateY(-50%)',
 			}}
 		>
-			<p
-				style={{
-					opacity: .75,
-					fontStyle: 'italic',
-					userSelect: 'none',
-					position: 'absolute',
-					top: '50%',
-					left: 0,
-					transform: 'translateY(-50%)',
-				}}
-			>
-				{timelimit_str}
-				<br />
-				{ranked_str}
-			</p>
-			<Button
+			{timelimit_str}
+			<br />
+			{ranked_str}
+		</p>
+		<Button
+			style={{
+				width: 150,
+				position: 'absolute',
+				top: '50%',
+				right: 0,
+				transform: 'translateY(-50%)',
+			}}
+			onclick={() => setEditGameRulesDialogVisible(true)}
+		>
+			<BuildOutlinedIcon style={{ fontSize: 48 }} />
+			<span
 				style={{
-					width: 150,
+					fontWeight: 600,
 					position: 'absolute',
+					right: 24,
 					top: '50%',
-					right: 0,
+					width: 85,
+					verticalAlign: 'middle',
+					textAlign: 'center',
 					transform: 'translateY(-50%)',
+					userSelect: 'none',
 				}}
-				onclick={this.showEditGameRules}
 			>
-				<BuildOutlinedIcon 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>
-			<EditGameSettings
-				parentState={this.state}
-				hideEditGameRules={this.hideEditGameRules}
-				setGameRules={this.setGameRules}
-			/>
-		</div>;
-	}
+				Spelregels aanpassen
+			</span>
+		</Button>
+		<EditGameSettings
+			hideEditGameRules={() => setEditGameRulesDialogVisible(false)}
+			setGameRules={setRuleset}
+			ruleset={ruleset}
+			visible={editGameRulesDialogVisible}
+		/>
+	</div>;
 }
 
 function GameSettingsSection(props: {
@@ -168,120 +155,116 @@ function GameRule(props: {
 }
 
 type editGameSettingsProps = {
-	parentState: CurrentGameSettingsStateType;
+	visible: boolean;
+	ruleset: ruleset;
 	hideEditGameRules: () => void;
 	setGameRules: (newRules: ruleset) => void;
 };
 
-export class EditGameSettings extends Component<editGameSettingsProps> {
-	render() {
-		return <DialogBox
-			title='Spelregels aanpassen'
+export function EditGameSettings(props: editGameSettingsProps) {
+	return <DialogBox
+		title='Spelregels aanpassen'
+		hidden={!props.visible}
+		onclick={props.hideEditGameRules}
+	>
+		<div
 			style={{
-				margin: 0,
-				display: this.props.parentState.editGameRulesDialogVisible ? 'block' : 'none',
+				marginTop: 24,
+				maxHeight: 500,
+				overflowY: 'scroll',
+				borderRadius: 8,
 			}}
-			onclick={this.props.hideEditGameRules}
 		>
-			<div
-				style={{
-					marginTop: 24,
-					maxHeight: 500,
-					overflowY: 'scroll',
-					borderRadius: 8,
-				}}
+			<GameSettingsSection
+				title='Tijdslimiet'
+				state={props.ruleset.timelimit.enabled}
+				id='timelimit'
 			>
-				<GameSettingsSection
-					title='Tijdslimiet'
-					state={this.props.parentState.ruleset.timelimit.enabled}
-					id='timelimit'
+				<div
+					style={{
+						display: 'grid',
+						gridTemplateColumns: '1fr 1fr 1fr',
+						gridGap: 16,
+						margin: '16px 0',
+					}}
 				>
-					<div
-						style={{
-							display: 'grid',
-							gridTemplateColumns: '1fr 1fr 1fr',
-							gridGap: 16,
-							margin: '16px 0',
-						}}
-					>
-						<Input
-							id='timelimit_minutes'
-							type='number'
-							label='min'
-							min={0}
-							max={60}
-							value={this.props.parentState.ruleset.timelimit.minutes}
-						/>
-						<Input
-							id='timelimit_seconds'
-							type='number'
-							label='sec'
-							min={0}
-							max={60}
-							value={this.props.parentState.ruleset.timelimit.seconds}
-						/>
-						<Input
-							id='timelimit_addmove'
-							type='number'
-							label='plus'
-							min={0}
-							value={this.props.parentState.ruleset.timelimit.addmove}
-						/>
-					</div>
-					<CheckBox id='timelimit_shared' state={this.props.parentState.ruleset.timelimit.shared} />
-					<span
-						style={{
-							verticalAlign: 'super',
-							marginLeft: 4,
-						}}
-					>
-						Timer gebruiken voor bijde spelers
-					</span>
-				</GameSettingsSection>
-				{false && <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={this.props.parentState.ruleset.ranked}
-					id='ranked'
-					noMarginBottom
-				/>
-			</div>
-			<Button
-				style={{
-					textAlign: 'center',
-					marginTop: 24,
-				}}
-				onclick={() => {
-					var rules: ruleset = {
-						timelimit: {
-							enabled: document.getElementById('timelimit_enabled').classList.contains('on'),
-							minutes: Number((document.getElementById('timelimit_minutes') as HTMLInputElement).value),
-							seconds: Number((document.getElementById('timelimit_seconds') as HTMLInputElement).value),
-							addmove: Number((document.getElementById('timelimit_addmove') as HTMLInputElement).value),
-							shared: document.getElementById('timelimit_shared').classList.contains('on'),
-						},
-						ranked: document.getElementById('ranked_enabled').classList.contains('on'),
-					};
-					this.props.setGameRules(rules);
-					this.props.hideEditGameRules();
-				}}
-			>
-				Instellingen opslaan
-			</Button>
-		</DialogBox>;
-	}
+					<Input
+						id='timelimit_minutes'
+						type='number'
+						label='min'
+						min={0}
+						max={60}
+						value={props.ruleset.timelimit.minutes}
+					/>
+					<Input
+						id='timelimit_seconds'
+						type='number'
+						label='sec'
+						min={0}
+						max={60}
+						value={props.ruleset.timelimit.seconds}
+					/>
+					<Input
+						id='timelimit_addmove'
+						type='number'
+						label='plus'
+						min={0}
+						value={props.ruleset.timelimit.addmove}
+					/>
+				</div>
+				<CheckBox id='timelimit_shared' state={props.ruleset.timelimit.shared} />
+				<span
+					style={{
+						verticalAlign: 'super',
+						marginLeft: 4,
+					}}
+				>
+					Timer gebruiken voor bijde spelers
+				</span>
+			</GameSettingsSection>
+			{false && <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={props.ruleset.ranked}
+				id='ranked'
+				noMarginBottom
+			/>
+		</div>
+		<Button
+			style={{
+				textAlign: 'center',
+				marginTop: 24,
+			}}
+			onclick={() => {
+				var rules: ruleset = {
+					timelimit: {
+						enabled: document.getElementById('timelimit_enabled').classList.contains('on'),
+						minutes: Number((document.getElementById('timelimit_minutes') as HTMLInputElement).value),
+						seconds: Number((document.getElementById('timelimit_seconds') as HTMLInputElement).value),
+						addmove: Number((document.getElementById('timelimit_addmove') as HTMLInputElement).value),
+						shared: document.getElementById('timelimit_shared').classList.contains('on'),
+					},
+					ranked: document.getElementById('ranked_enabled').classList.contains('on'),
+				};
+				props.setGameRules(rules);
+				props.hideEditGameRules();
+			}}
+		>
+			Instellingen opslaan
+		</Button>
+	</DialogBox>;
 }
-- 
cgit v1.2.3


From 763d21dc09ea1ae5bf7bda03763386039de396a9 Mon Sep 17 00:00:00 2001
From: lonkaars <l.leblansch@gmail.com>
Date: Sun, 18 Apr 2021 19:34:00 +0200
Subject: edit game rules working (still some inline css)

---
 components/dialogBox.tsx    | 19 ++++------
 components/gameSettings.tsx | 85 ++++++++-------------------------------------
 pages/_app.tsx              |  1 +
 styles/gameSettings.css     | 59 +++++++++++++++++++++++++++++++
 styles/ui.css               | 10 ++++++
 5 files changed, 92 insertions(+), 82 deletions(-)
 create mode 100644 styles/gameSettings.css

(limited to 'components/gameSettings.tsx')

diff --git a/components/dialogBox.tsx b/components/dialogBox.tsx
index 0a61762..4ead7c5 100644
--- a/components/dialogBox.tsx
+++ b/components/dialogBox.tsx
@@ -9,20 +9,15 @@ export function DialogBox(props: {
 	title: string;
 	onclick?: () => void;
 	hidden?: boolean;
+	className?: string;
 }) {
-	return <Vierkant className={'dialogbox drop-2 pad-l posfix abscenter ' + (props.hidden ? 'dispnone' : '')}>
-		<h2 style={{ marginBottom: 24 }}>{props.title}</h2>
+	return <Vierkant
+		className={'dialogbox drop-2 pad-l posfix abscenter ' + (props.hidden ? 'dispnone' : '') + ' '
+			+ props.className}
+	>
+		<h2 className='title'>{props.title}</h2>
 		<span onClick={props.onclick}>
-			<CancelIcon
-				style={{
-					position: 'absolute',
-					top: 25,
-					right: 25,
-					color: 'var(--text)',
-					opacity: .85,
-					cursor: 'pointer',
-				}}
-			/>
+			<CancelIcon className='posabs close icon subtile' />
 		</span>
 		{props.children}
 	</Vierkant>;
diff --git a/components/gameSettings.tsx b/components/gameSettings.tsx
index 3c3a699..bb01284 100644
--- a/components/gameSettings.tsx
+++ b/components/gameSettings.tsx
@@ -30,60 +30,24 @@ export function CurrentGameSettings() {
 			.catch(() => {});
 	}, []);
 
-	/* showEditGameRules = () => this.setState({ editGameRulesDialogVisible: true }); */
-	/* hideEditGameRules = () => this.setState({ editGameRulesDialogVisible: false }); */
-	/* setGameRules = (newRules: ruleset) => this.setState({ ruleset: newRules }); */
-
 	var timelimit_str = ruleset.timelimit.enabled
 		? `${ruleset.timelimit.minutes}m${ruleset.timelimit.seconds}s plus ${ruleset.timelimit.addmove}`
 		: 'Geen tijdslimiet';
 	var ranked_str = ruleset.ranked
 		? 'Gerangschikt'
 		: 'Niet gerangschikt';
-	return <div
-		style={{
-			position: 'relative',
-			height: 80,
-			overflow: 'visible',
-			zIndex: 1,
-		}}
-	>
-		<p
-			className='subtile nosel posabs'
-			style={{
-				top: '50%',
-				left: 0,
-				transform: 'translateY(-50%)',
-			}}
-		>
+	return <div className='editGameSettings posrel'>
+		<p className='currentRules subtile nosel posabs l0'>
 			{timelimit_str}
 			<br />
 			{ranked_str}
 		</p>
 		<Button
-			style={{
-				width: 150,
-				position: 'absolute',
-				top: '50%',
-				right: 0,
-				transform: 'translateY(-50%)',
-			}}
+			className='posabs r0 pad-m'
 			onclick={() => setEditGameRulesDialogVisible(true)}
 		>
-			<BuildOutlinedIcon style={{ fontSize: 48 }} />
-			<span
-				style={{
-					fontWeight: 600,
-					position: 'absolute',
-					right: 24,
-					top: '50%',
-					width: 85,
-					verticalAlign: 'middle',
-					textAlign: 'center',
-					transform: 'translateY(-50%)',
-					userSelect: 'none',
-				}}
-			>
+			<BuildOutlinedIcon className='icon' />
+			<span className='posabs center nosel text'>
 				Spelregels aanpassen
 			</span>
 		</Button>
@@ -105,13 +69,7 @@ function GameSettingsSection(props: {
 }) {
 	return <Vierkant
 		id={props.id}
-		style={{
-			backgroundColor: 'var(--background-alt)',
-			width: '100%',
-			padding: 16,
-			margin: 0,
-			marginBottom: props.noMarginBottom ? 0 : 24,
-		}}
+		className='pad-m editableRulesSection'
 	>
 		<span
 			style={{
@@ -166,28 +124,15 @@ export function EditGameSettings(props: editGameSettingsProps) {
 		title='Spelregels aanpassen'
 		hidden={!props.visible}
 		onclick={props.hideEditGameRules}
+		className='gameRuleEdit'
 	>
-		<div
-			style={{
-				marginTop: 24,
-				maxHeight: 500,
-				overflowY: 'scroll',
-				borderRadius: 8,
-			}}
-		>
+		<div className='editableRules round-t'>
 			<GameSettingsSection
 				title='Tijdslimiet'
 				state={props.ruleset.timelimit.enabled}
 				id='timelimit'
 			>
-				<div
-					style={{
-						display: 'grid',
-						gridTemplateColumns: '1fr 1fr 1fr',
-						gridGap: 16,
-						margin: '16px 0',
-					}}
-				>
+				<div className='sidebyside timeControls'>
 					<Input
 						id='timelimit_minutes'
 						type='number'
@@ -195,6 +140,7 @@ export function EditGameSettings(props: editGameSettingsProps) {
 						min={0}
 						max={60}
 						value={props.ruleset.timelimit.minutes}
+						className='pad-m round-t'
 					/>
 					<Input
 						id='timelimit_seconds'
@@ -203,6 +149,7 @@ export function EditGameSettings(props: editGameSettingsProps) {
 						min={0}
 						max={60}
 						value={props.ruleset.timelimit.seconds}
+						className='pad-m round-t'
 					/>
 					<Input
 						id='timelimit_addmove'
@@ -210,19 +157,20 @@ export function EditGameSettings(props: editGameSettingsProps) {
 						label='plus'
 						min={0}
 						value={props.ruleset.timelimit.addmove}
+						className='pad-m round-t'
 					/>
 				</div>
 				<CheckBox id='timelimit_shared' state={props.ruleset.timelimit.shared} />
 				<span
+					className='valignsup'
 					style={{
-						verticalAlign: 'super',
 						marginLeft: 4,
 					}}
 				>
 					Timer gebruiken voor bijde spelers
 				</span>
 			</GameSettingsSection>
-			{false && <GameSettingsSection title='Regelset' state={false}>
+			{false && <GameSettingsSection id='gamemodes' title='Regelset' state={false}>
 				<div
 					style={{
 						display: 'grid',
@@ -245,10 +193,7 @@ export function EditGameSettings(props: editGameSettingsProps) {
 			/>
 		</div>
 		<Button
-			style={{
-				textAlign: 'center',
-				marginTop: 24,
-			}}
+			className='save'
 			onclick={() => {
 				var rules: ruleset = {
 					timelimit: {
diff --git a/pages/_app.tsx b/pages/_app.tsx
index bbdbae8..9521d58 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -11,6 +11,7 @@ import '../styles/navbar.css';
 import '../styles/ui.css';
 import '../styles/utility.css';
 
+import '../styles/gameSettings.css';
 import '../styles/index.css';
 import '../styles/search.css';
 import '../styles/settings.css';
diff --git a/styles/gameSettings.css b/styles/gameSettings.css
new file mode 100644
index 0000000..533cea0
--- /dev/null
+++ b/styles/gameSettings.css
@@ -0,0 +1,59 @@
+.editGameSettings {
+	height: 80px;
+	overflow: visible;
+	z-index: 1;
+}
+
+.editGameSettings .currentRules {
+	top: 50%;
+	transform: translateY(-50%);
+}
+
+.editGameSettings > .button {
+	width: 150px;
+	top: 50%;
+	transform: translateY(-50%);
+	text-align: left;
+}
+
+.editGameSettings > .button .icon {
+	font-size: 48px;
+}
+
+.editGameSettings > .button .text {
+	right: var(--spacing-medium);
+	width: 85px;
+	top: 50%;
+	vertical-align: middle;
+	transform: translateY(-50%);
+}
+
+.editGameSettings .editableRules {
+	margin-top: var(--spacing-large);
+	max-height: 500px;
+	overflow-y: scroll;
+}
+
+.editGameSettings .editableRules .editableRulesSection {
+	width: 100%;
+	background-color: var(--gray-700);
+	margin: 0;
+	margin-bottom: var(--spacing-medium);
+}
+
+.editGameSettings .button {
+	line-height: normal;
+}
+
+.editGameSettings .editableRules .editableRulesSection .timeControls {
+	margin: var(--spacing-medium);
+	margin-left: 0;
+	margin-right: 0;
+}
+
+.editGameSettings .editableRules .editableRulesSection .timeControls input {
+	background-color: var(--background);
+
+	width: calc(100% - 2 * var(--spacing-medium));
+}
+
diff --git a/styles/ui.css b/styles/ui.css
index efc96b7..55b24e2 100644
--- a/styles/ui.css
+++ b/styles/ui.css
@@ -70,3 +70,13 @@
 	width: 392px;
 }
 
+.dialogbox > .title {
+	margin-bottom: var(--spacing-large);
+}
+
+.dialogbox .icon.close {
+	top: 25px;
+	right: 25px;
+	cursor: pointer;
+}
+
-- 
cgit v1.2.3


From de2853cc4793b7948b94525a0a4f964e49943131 Mon Sep 17 00:00:00 2001
From: lonkaars <l.leblansch@gmail.com>
Date: Wed, 21 Apr 2021 09:57:40 +0200
Subject: even more components without inline css

---
 components/gameSettings.tsx | 60 ++++++++++++---------------------------------
 components/navbar.tsx       | 42 +++----------------------------
 styles/gameSettings.css     | 25 +++++++++++++++----
 styles/navbar.css           | 25 +++++++++++++++++++
 styles/notifications.css    |  5 ++--
 5 files changed, 67 insertions(+), 90 deletions(-)

(limited to 'components/gameSettings.tsx')

diff --git a/components/gameSettings.tsx b/components/gameSettings.tsx
index bb01284..13462be 100644
--- a/components/gameSettings.tsx
+++ b/components/gameSettings.tsx
@@ -1,5 +1,5 @@
 import axios from 'axios';
-import { Component, CSSProperties, ReactNode, useEffect, useState } from 'react';
+import { ReactNode, useEffect, useState } from 'react';
 
 import { ruleset, userPreferences } from '../api/api';
 import { DialogBox } from './dialogBox';
@@ -71,24 +71,15 @@ function GameSettingsSection(props: {
 		id={props.id}
 		className='pad-m editableRulesSection'
 	>
-		<span
-			style={{
-				verticalAlign: 'top',
-				fontSize: 14,
-				fontWeight: 600,
-			}}
-		>
+		<span className='valigntop nosel'>
 			{props.title}
 		</span>
-		<CheckBox
-			state={props.state}
-			id={`${props.id}_enabled`}
-			style={{
-				verticalAlign: 'top',
-				float: 'right',
-				margin: -3,
-			}}
-		/>
+		<div className='checkboxWrapper valigntop floatr'>
+			<CheckBox
+				state={props.state}
+				id={props.id + '_enabled'}
+			/>
+		</div>
 		<div>{props.children}</div>
 	</Vierkant>;
 }
@@ -96,19 +87,10 @@ function GameSettingsSection(props: {
 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>
+	return <div className='gamerule pad-m round-t center bg-900'>
+		<h1>{props.title}</h1>
+		<p>{props.description}</p>
 	</div>;
 }
 
@@ -161,28 +143,16 @@ export function EditGameSettings(props: editGameSettingsProps) {
 					/>
 				</div>
 				<CheckBox id='timelimit_shared' state={props.ruleset.timelimit.shared} />
-				<span
-					className='valignsup'
-					style={{
-						marginLeft: 4,
-					}}
-				>
+				<span className='valignsup'>
 					Timer gebruiken voor bijde spelers
 				</span>
 			</GameSettingsSection>
-			{false && <GameSettingsSection id='gamemodes' title='Regelset' state={false}>
-				<div
-					style={{
-						display: 'grid',
-						gridTemplateColumns: '1fr 1fr',
-						gridGap: 16,
-						margin: '16px 0',
-					}}
-				>
+			{true && <GameSettingsSection id='gamemodes' title='Regelset' state={false}>
+				<div className='sidebyside'>
 					<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='Gravity' description='De zwaartekracht draait soms' />
 				<GameRule title='Flashlight' description='Het veld wordt opgelicht door de vallende fiches' />
 			</GameSettingsSection>}
 			<GameSettingsSection
diff --git a/components/navbar.tsx b/components/navbar.tsx
index 7f6e694..5ce43bb 100644
--- a/components/navbar.tsx
+++ b/components/navbar.tsx
@@ -54,25 +54,7 @@ export function NavBar() {
 		})();
 	}, []);
 
-	return <div
-		className='navbar bg-800'
-		style={{
-			width: 48,
-			height: '100%',
-
-			lineHeight: 0,
-
-			display: 'inline-block',
-
-			position: 'fixed',
-			top: 0,
-			left: 0,
-
-			overflow: 'visible',
-			whiteSpace: 'nowrap',
-			zIndex: 2,
-		}}
-	>
+	return <div className='navbar bg-800 h100vh dispinbl t0 l0 posfix'>
 		<div className='item'>
 			<Logo />
 		</div>
@@ -90,29 +72,13 @@ export function NavBar() {
 		</a>
 
 		<div className='bg-800 bottomArea'>
-			{loggedIn && <a
-				className='item'
-				style={{
-					overflow: 'visible',
-					position: 'relative',
-				}}
-			>
+			{loggedIn && <a className='notifications item posrel'>
 				<div
-					style={{ cursor: 'pointer' }}
+					className='iconWrapper'
 					onClick={() => setNotificationsAreaVisible(!notificationsAreaVisible)}
 				>
 					<NotificationsIcon />
-					{gotNotifications && <div
-						style={{
-							backgroundColor: 'var(--disk-a)',
-							width: 8,
-							height: 8,
-							borderRadius: 4,
-							position: 'absolute',
-							top: 2,
-							right: 2,
-						}}
-					/>}
+					{gotNotifications && <div className='notificationDot posabs' />}
 				</div>
 				<NotificationsArea
 					visible={notificationsAreaVisible}
diff --git a/styles/gameSettings.css b/styles/gameSettings.css
index d9ba262..3c45fb4 100644
--- a/styles/gameSettings.css
+++ b/styles/gameSettings.css
@@ -29,7 +29,7 @@
 }
 
 .editGameSettings .editableRules {
-	margin-top: var(--spacing-large);
+	margin: var(--spacing-large) 0;
 	max-height: 500px;
 	overflow-y: scroll;
 }
@@ -43,11 +43,14 @@
 html.dark .editGameSettings .editableRules .editableRulesSection {
 	background-color: var(--gray-800);
 }
-
-.editGameSettings .button {
-	line-height: normal;
+.editGameSettings .editableRules .editableRulesSection:last-child {
+	margin-bottom: 0;
 }
 
+.editGameSettings .button { line-height: normal; }
+
+.editGameSettings .checkboxWrapper { margin: -3px; }
+
 .editGameSettings .editableRules .editableRulesSection .timeControls {
 	margin: var(--spacing-medium);
 	margin-left: 0;
@@ -56,7 +59,19 @@ html.dark .editGameSettings .editableRules .editableRulesSection {
 
 .editGameSettings .editableRules .editableRulesSection .timeControls input {
 	background-color: var(--background);
-
 	width: calc(100% - 2 * var(--spacing-medium));
 }
 
+.editGameSettings .editableRules .gamerule {
+	margin-top: var(--spacing-medium);
+}
+
+.editGameSettings .editableRules .gamerule h1 {
+	color: var(--accent);
+	font-size: 2.5rem;
+}
+
+#timelimit .valignsup {
+	margin-left: var(--spacing-small);
+}
+
diff --git a/styles/navbar.css b/styles/navbar.css
index 5866b8f..baf9fd6 100644
--- a/styles/navbar.css
+++ b/styles/navbar.css
@@ -9,3 +9,28 @@
 	bottom: -4px;
 	left: 0;
 }
+
+.navbar {
+	width: 48px;
+	line-height: 0;
+	overflow: visible;
+	white-space: nowrap;
+	z-index: 2;
+}
+
+.navbar .bottomArea .item.notifications {
+	overflow: visible;
+}
+
+.navbar .bottomArea .item.notifications > .iconWrapper {
+	cursor: pointer;
+}
+
+.notifications .notificationDot {
+	background-color: var(--accent);
+	width: 8px;
+	height: 8px;
+	border-radius: 4px;
+	top: 2px;
+	right: 2px;
+}
diff --git a/styles/notifications.css b/styles/notifications.css
index ec47836..db1598d 100644
--- a/styles/notifications.css
+++ b/styles/notifications.css
@@ -1,4 +1,5 @@
-.notificationsArea {
+/* a tags are here because of css specificity */
+a.notificationsArea {
 	left: calc(48px + var(--spacing-medium));
 	top: 92px;
 	transform: translateY(-100%);
@@ -7,7 +8,7 @@
 	height: 450px;
 }
 
-.notificationsArea .tuitje {
+a.notificationsArea .tuitje {
 	left: var(--spacing-medium);
 	bottom: 86px;
 	transform: translate(-100%, 100%) rotate(90deg);
-- 
cgit v1.2.3


From 31396f6b4f1271cb646947111661d9bb59ca951f Mon Sep 17 00:00:00 2001
From: lonkaars <l.leblansch@gmail.com>
Date: Wed, 21 Apr 2021 10:22:50 +0200
Subject: toasts without inline css

---
 components/gameSettings.tsx |  2 +-
 components/toast.tsx        | 75 +++++++--------------------------------------
 pages/_app.tsx              |  1 +
 styles/toast.css            | 66 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 79 insertions(+), 65 deletions(-)
 create mode 100644 styles/toast.css

(limited to 'components/gameSettings.tsx')

diff --git a/components/gameSettings.tsx b/components/gameSettings.tsx
index 13462be..e2c60e6 100644
--- a/components/gameSettings.tsx
+++ b/components/gameSettings.tsx
@@ -147,7 +147,7 @@ export function EditGameSettings(props: editGameSettingsProps) {
 					Timer gebruiken voor bijde spelers
 				</span>
 			</GameSettingsSection>
-			{true && <GameSettingsSection id='gamemodes' title='Regelset' state={false}>
+			{false && <GameSettingsSection id='gamemodes' title='Regelset' state={false}>
 				<div className='sidebyside'>
 					<GameRule title='+2' description='Extra kolommen' />
 					<GameRule title='+4' description='Extra kolommen' />
diff --git a/components/toast.tsx b/components/toast.tsx
index 97e17e6..3a72ae1 100644
--- a/components/toast.tsx
+++ b/components/toast.tsx
@@ -1,26 +1,14 @@
-import { createContext, CSSProperties, ReactNode, useState } from 'react';
+import { createContext, ReactNode, useState } from 'react';
 
 import CloseIcon from '@material-ui/icons/Close';
 
 function ToastArea(props: {
-	style?: CSSProperties;
 	children?: ReactNode;
 	rerender?: boolean;
 }) {
 	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,
-		}}
+		className='posfix abscenterh'
 	>
 		{props.children}
 	</div>;
@@ -32,71 +20,30 @@ function Toast(props: {
 	icon?: ReactNode;
 	children?: ReactNode;
 	type?: 'normal' | 'confirmation' | 'error';
-	style?: CSSProperties;
 }) {
 	var [visible, setVisibility] = useState(true);
 
 	setTimeout(() => setVisibility(false), 10e3);
 
-	return visible && <div
-		style={{
-			padding: 0,
-			marginBottom: 12,
-			borderRadius: 6,
-			boxShadow: '0 8px 12px -4px #00000033',
-			color: props.type === 'confirmation' ? 'var(--background)' : 'var(--text)',
-			backgroundColor: props.type === 'normal'
-				? 'var(--background)'
-				: props.type === 'confirmation'
-				? 'var(--disk-b)'
-				: props.type === 'error'
-				? 'var(--disk-a)'
-				: 'var(--background)',
-			...props.style,
-		}}
-	>
+	return visible && <div className={'round-t drop-1 toast ' + props.type}>
 		{props.children
 			|| <div
-				style={{
-					lineHeight: 0,
-					padding: 12,
-					minHeight: props.description ? 36 : 24,
-					position: 'relative',
-				}}
+				className={'inner pad-m posrel '
+					+ (props.description ? 'hasDescription' : '') + ' '
+					+ (props.icon ? 'hasIcon' : '')}
 			>
-				<div
-					style={{
-						position: 'absolute',
-						left: 12,
-						top: '50%',
-						transform: 'translateY(-50%)',
-					}}
-				>
+				<div className='icon posabs abscenterv'>
 					{props.icon}
 				</div>
-				<div
-					style={{
-						userSelect: 'none',
-						position: 'absolute',
-						left: props.icon ? 48 : 12,
-						top: '50%',
-						transform: 'translateY(-50%)',
-					}}
-				>
-					<h2 style={{ fontSize: 16 }}>{props.text}</h2>
+				<div className='content nosel posabs abscenterv'>
+					<h2>{props.text}</h2>
 					<p>{props.description}</p>
 				</div>
 				<div
-					style={{
-						cursor: 'pointer',
-						position: 'absolute',
-						right: 12,
-						top: '50%',
-						transform: 'translateY(-50%)',
-					}}
+					className='closeIcon posabs abscenterv'
 					onClick={() => setVisibility(false)}
 				>
-					<CloseIcon style={{ fontSize: 24 }} />
+					<CloseIcon />
 				</div>
 			</div>}
 	</div>;
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 317b389..c1347e8 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -10,6 +10,7 @@ import '../styles/global.css';
 import '../styles/navbar.css';
 import '../styles/notifications.css';
 import '../styles/recentGames.css';
+import '../styles/toast.css';
 import '../styles/ui.css';
 import '../styles/utility.css';
 
diff --git a/styles/toast.css b/styles/toast.css
new file mode 100644
index 0000000..2ecbcfb
--- /dev/null
+++ b/styles/toast.css
@@ -0,0 +1,66 @@
+.toast.error {
+	background-color: var(--error);
+}
+.toast.confirmation {
+	background-color: var(--confirm);
+}
+.toast.normal {
+	background-color: var(--gray-700);
+}
+
+.toast.confirmation,
+.toast.error {
+	color: var(--gray-900);
+}
+
+html.dark .toast.confirmation,
+html.dark .toast.error {
+	background-color: var(--gray-700);
+	color: var(--foreground);
+}
+html.dark .toast.error {
+	box-shadow: inset 0 0 0 2px var(--error);
+}
+html.dark .toast.confirmation {
+	box-shadow: inset 0 0 0 2px var(--confirm);
+}
+
+.toast {
+	margin-bottom: var(--spacing-medium);
+}
+
+#ToastArea {
+	white-space: nowrap;
+	bottom: var(--spacing-medium);
+	z-index: 1;
+	max-width: 600px;
+	width: calc(100% - 2 * 48px);
+	margin: 0 var(--spacing-large);
+}
+
+.toast .inner {
+	line-height: 0;
+	min-height: 24px;
+}
+
+.toast .inner.hasDescription {
+	min-height: 36px;
+}
+
+.toast .inner .icon,
+.toast .inner .content {
+	left: var(--spacing-medium);
+}
+
+.toast .inner.hasIcon .content {
+	left: calc(36px + var(--spacing-medium));
+}
+
+.toast .inner .content h2 {
+	font-size: 1rem;
+}
+
+.toast .inner .closeIcon {
+	right: var(--spacing-medium);
+	cursor: pointer;
+}
-- 
cgit v1.2.3

