components: rewrite layout with CSS Grid, add line drawing
This commit is contained in:
parent
6468f94c61
commit
9001deaf3a
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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">
|
||||||
<Logo />
|
<div />
|
||||||
<Board />
|
<div>
|
||||||
|
<Logo />
|
||||||
|
<Board
|
||||||
|
numRows={10}
|
||||||
|
numCols={10}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
className="Letter"
|
private line_y1: string;
|
||||||
>
|
|
||||||
{letter}
|
constructor(props: IBoardProps) {
|
||||||
</div>
|
super(props);
|
||||||
);
|
|
||||||
|
this.state = {
|
||||||
|
board: Array(props.numCols).fill(Array(props.numRows).fill('·')),
|
||||||
|
isSelectingWord: false,
|
||||||
|
startPos: [0, 0],
|
||||||
}
|
}
|
||||||
return squares;
|
|
||||||
|
this.line = React.createRef();
|
||||||
|
this.line_x1 = "0px";
|
||||||
|
this.line_y1 = "0px";
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseMove() {
|
handleMouseDown(startPos: Position) {
|
||||||
return 1;
|
this.setState({...this.state, startPos, isSelectingWord: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseDown() {
|
handleMouseUp(startPos: Position) {
|
||||||
return 1;
|
let [x, y] = startPos;
|
||||||
|
this.line_x1 = `${y * 100}px`;
|
||||||
|
this.line_y1 = `${x * 100}px`;
|
||||||
|
|
||||||
|
this.setState({...this.state, startPos, isSelectingWord: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
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"
|
||||||
|
onMouseUp={() => this.handleMouseUp([x, y])}
|
||||||
|
onMouseDown={() => this.handleMouseDown([x, y])}
|
||||||
|
onMouseOver={() => this.handleMouseOver([x, y])}
|
||||||
|
>
|
||||||
|
{s}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
|
|
||||||
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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user