Add basic button control (no functionality)

This commit is contained in:
sschwei1 2022-10-24 15:52:23 +02:00
parent 2fe61bff89
commit 4d3113dc99
10 changed files with 126 additions and 8 deletions

17
package-lock.json generated
View File

@ -10,7 +10,8 @@
"dependencies": { "dependencies": {
"classnames": "^2.3.2", "classnames": "^2.3.2",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0",
"react-icons": "^4.6.0"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.0.17", "@types/react": "^18.0.17",
@ -1455,6 +1456,14 @@
"react": "^18.2.0" "react": "^18.2.0"
} }
}, },
"node_modules/react-icons": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.6.0.tgz",
"integrity": "sha512-rR/L9m9340yO8yv1QT1QurxWQvWpbNHqVX0fzMln2HEb9TEIrQRGsqiNFQfiv9/JEUbyHmHPlNTB2LWm2Ttz0g==",
"peerDependencies": {
"react": "*"
}
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.14.0", "version": "0.14.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
@ -2620,6 +2629,12 @@
"scheduler": "^0.23.0" "scheduler": "^0.23.0"
} }
}, },
"react-icons": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.6.0.tgz",
"integrity": "sha512-rR/L9m9340yO8yv1QT1QurxWQvWpbNHqVX0fzMln2HEb9TEIrQRGsqiNFQfiv9/JEUbyHmHPlNTB2LWm2Ttz0g==",
"requires": {}
},
"react-refresh": { "react-refresh": {
"version": "0.14.0", "version": "0.14.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",

View File

@ -11,7 +11,8 @@
"dependencies": { "dependencies": {
"classnames": "^2.3.2", "classnames": "^2.3.2",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0",
"react-icons": "^4.6.0"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.0.17", "@types/react": "^18.0.17",

View File

@ -0,0 +1,35 @@
import React, {CSSProperties} from 'react';
interface ButtonGroupProps {
buttons: ButtonDefinition[];
buttonStyleProps: CSSProperties;
}
export interface ButtonDefinition {
text: string|JSX.Element;
onClick: React.MouseEventHandler<HTMLButtonElement>;
cssProps: CSSProperties;
}
const ButtonGroup = ({buttons, buttonStyleProps}: ButtonGroupProps) => {
return (
<div className='button-group'>
{
buttons.map(((btn, index) => (
<button
key={index}
onClick={btn.onClick}
style={{
...buttonStyleProps,
...btn.cssProps
}}
>
<>{btn.text}</>
</button>
)))
}
</div>
);
}
export default ButtonGroup;

View File

@ -0,0 +1,2 @@
export {default as ButtonGroup} from './ButtonGroup';
export type { ButtonDefinition } from './ButtonGroup';

View File

@ -33,9 +33,9 @@ const Cell = ({value, position, updateCell}: CellProps) => {
return ( return (
<div <div
className={cellClasses} className={cellClasses}
draggable={false}
onMouseDown={handleCellMouseDown} onMouseDown={handleCellMouseDown}
// onMouseEnter={handleCellMouseEnter} onMouseEnter={handleCellMouseOver}
onMouseOver={handleCellMouseOver}
/> />
) )
} }

View File

@ -0,0 +1,38 @@
import {ButtonDefinition, ButtonGroup} from '../button';
import {AiOutlineClear, BsFillPlayFill, BsFillStopFill, CiSettings, TbArrowsRandom} from 'react-icons/all';
import React, {useMemo} from 'react';
interface ControlPanelProps {
handleStart: React.MouseEventHandler<HTMLButtonElement>;
handleStop: React.MouseEventHandler<HTMLButtonElement>;
handleRandomFill: React.MouseEventHandler<HTMLButtonElement>;
handleClear: React.MouseEventHandler<HTMLButtonElement>;
}
const ControlPanel = ({
handleStart,
handleStop,
handleRandomFill,
handleClear
}: ControlPanelProps) => {
const controlButtons: ButtonDefinition[] = useMemo(() => [
{text: <BsFillPlayFill />, onClick: handleStart, cssProps: {}},
{text: <BsFillStopFill />, onClick: handleStop, cssProps: {}},
{text: <TbArrowsRandom />, onClick: handleRandomFill, cssProps: {}},
{text: <AiOutlineClear />, onClick: handleClear, cssProps: {}}
], [handleStart, handleStop, handleRandomFill, handleClear]);
return (
<div className='control-panel'>
<ButtonGroup
buttons={controlButtons}
buttonStyleProps={{
width: '50px'
}}
/>
<button><CiSettings/></button>
</div>
);
}
export default ControlPanel;

View File

@ -2,6 +2,7 @@ import CellContainer from './CellContainer';
import {useCallback, useEffect, useState} from 'react'; import {useCallback, useEffect, useState} from 'react';
import '../../styles/game.less'; import '../../styles/game.less';
import ControlPanel from './ControlPanel';
interface GameProps { interface GameProps {
@ -41,6 +42,12 @@ const Game = ({}: GameProps) => {
return ( return (
<div className='game-container'> <div className='game-container'>
<ControlPanel
handleStart={() => {}}
handleStop={() => {}}
handleRandomFill={() => {}}
handleClear={() => {}}
/>
<CellContainer <CellContainer
cells={cells} cells={cells}
width={gameOptions.width} width={gameOptions.width}

View File

@ -1,4 +1,4 @@
@col-dark: #171717; @col-dark: #171717;
@col-dark-light: #444444; @col-dark-light: #444444;
@col-primary: #DA0037; @col-primary: #da005e;
@col-light: #EDEDED; @col-light: #EDEDED;

View File

@ -1,20 +1,30 @@
@import 'colors'; @import 'colors';
.game-container { .game-container {
min-width: 1000px;
min-height: 1000px;
display: flex; display: flex;
flex-direction: column;
.control-panel {
display: flex;
justify-content: space-between;
margin-bottom: 1rem;
}
.cell-container { .cell-container {
flex-grow: 1; flex-grow: 1;
display: grid; display: grid;
min-width: 500px;
min-height: 500px;
.cell { .cell {
background: @col-dark; background: @col-dark;
border: 1px solid @col-dark-light; border: 1px solid @col-dark-light;
width: 100%; width: 100%;
height: 100%; height: 100%;
//pointer-events: none;
user-select: none;
&.active { &.active {
background: @col-primary; background: @col-primary;

View File

@ -19,3 +19,13 @@ body {
align-items: center; align-items: center;
} }
} }
button {
display: inline-flex;
padding: 7px 10px;
margin: 0;
font-size: 20px;
align-content: center;
justify-content: center;
}