components: rewrite layout with CSS Grid, add line drawing

This commit is contained in:
Artur Tamborski 2020-11-27 19:00:24 +01:00
parent 6468f94c61
commit 9001deaf3a
4 changed files with 131 additions and 46 deletions

View File

@ -1,5 +1,9 @@
.App { .App {
max-width: 80vw;
max-height: 100vh; max-height: 100vh;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 1fr;
grid-column-gap: 0;
grid-row-gap: 0;
} }

View File

@ -8,8 +8,15 @@ import './App.scss';
export default function App(): JSX.Element { export default function App(): JSX.Element {
return ( return (
<div className="App"> <div className="App">
<div />
<div>
<Logo /> <Logo />
<Board /> <Board
numRows={10}
numCols={10}
/>
</div>
<div />
</div> </div>
); );
} }

View File

@ -1,24 +1,56 @@
$LetterBaseColor: ghostwhite;
$LetterHoverColor: #d9d9ff;
.Container {
display: grid;
}
.Content, .Overlay {
grid-area: 1 / 1;
}
.Overlay {
user-select: none;
pointer-events: none;
}
.Canvas {
width: 100%;
height: 100%;
}
.Line {
stroke: red;
stroke-width: 10px;
opacity: 0.3;
}
.Board { .Board {
display: grid; display: grid;
justify-content: center; justify-content: center;
grid-template-columns: repeat(8, 8vw); grid-template-columns: repeat(10, 60px);
column-gap: 15px;
row-gap: 15px;
user-select: none;
text-align: center;
} }
.Letter { .Letter {
width: 60px;
height: 60px;
font-weight: bold; font-weight: bold;
font-size: larger; font-size: x-large;
padding: 20px; font-family: monospace;
background: ghostwhite; padding: 15px;
border-radius: 1rem; background: $LetterBaseColor;
border-color: #e5e5ea; text-align: center;
border: 5px solid #e5e5ea;
border-radius: 100%;
color: brown; color: brown;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: #e4e4ff; border-color: $LetterHoverColor;
}
&:focus {
border-color: #8b8be5;
} }
} }

View File

@ -1,48 +1,90 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import './Board.scss'; import './Board.scss';
export default class Board extends React.Component { interface IBoardProps {
numRows: number;
numCols: number;
}
static propTypes = { type Position = [x: number, y: number];
clickHandler: PropTypes.func,
};
genSquares() { interface IBoardState {
let squares = []; board: string[][];
for (let i = 0; i < 64; i++) { isSelectingWord: boolean;
let x = String.fromCharCode(i % 8 + 65); startPos: Position;
let y = String.fromCharCode(i / 8 + 49); }
let letter = x + y;
squares.push( export default class Board extends React.Component<IBoardProps, IBoardState> {
<div private line: React.RefObject<SVGLineElement>;
id={letter} private line_x1: string;
private line_y1: string;
constructor(props: IBoardProps) {
super(props);
this.state = {
board: Array(props.numCols).fill(Array(props.numRows).fill('·')),
isSelectingWord: false,
startPos: [0, 0],
}
this.line = React.createRef();
this.line_x1 = "0px";
this.line_y1 = "0px";
}
handleMouseDown(startPos: Position) {
this.setState({...this.state, startPos, isSelectingWord: true});
}
handleMouseUp(startPos: Position) {
let [x, y] = startPos;
this.line_x1 = `${y * 100}px`;
this.line_y1 = `${x * 100}px`;
this.setState({...this.state, startPos, isSelectingWord: false});
}
handleMouseOver(currentPos: Position) {
if (!this.state.isSelectingWord)
return;
}
render(): JSX.Element {
let letters =
this.state.board.map((ox, x) =>
ox.map((s, y) =>
<button
key={`${x}${y}`}
className="Letter" className="Letter"
onMouseUp={() => this.handleMouseUp([x, y])}
onMouseDown={() => this.handleMouseDown([x, y])}
onMouseOver={() => this.handleMouseOver([x, y])}
> >
{letter} {s}
</div> </button>
); ));
}
return squares;
}
onMouseMove() {
return 1;
}
onMouseDown() {
return 1;
}
render() {
return ( return (
<div <div className="Container">
className="Board" <div className="Content">
onMouseDown={this.onMouseDown} <div className="Board">
onMouseMove={this.onMouseMove} {letters}
> </div>
{this.genSquares()} </div>
<div className="Overlay">
<svg className="Canvas">
<line
className="Line"
ref={this.line}
x1={this.line_x1}
y1={this.line_y1}
x2="0"
y2="0"
/>
</svg>
</div>
</div> </div>
); );
} }