add tabbar
This commit is contained in:
parent
022e8b89f7
commit
a0f0486590
@ -3,6 +3,7 @@ import "./style.css";
|
|||||||
import Canvas from "./Canvas";
|
import Canvas from "./Canvas";
|
||||||
import { Editor } from "./editor/Editor";
|
import { Editor } from "./editor/Editor";
|
||||||
import Toolbar from "./Toolbar";
|
import Toolbar from "./Toolbar";
|
||||||
|
import Tabbar from "./Tabbar";
|
||||||
|
|
||||||
function App(): ReactElement {
|
function App(): ReactElement {
|
||||||
const [editor] = useState(() => new Editor());
|
const [editor] = useState(() => new Editor());
|
||||||
@ -12,8 +13,13 @@ function App(): ReactElement {
|
|||||||
<>
|
<>
|
||||||
<h1>nandsim</h1>
|
<h1>nandsim</h1>
|
||||||
<div className="Editor">
|
<div className="Editor">
|
||||||
|
<div>
|
||||||
<Toolbar editor={editor} canvasRef={canvasRef} />
|
<Toolbar editor={editor} canvasRef={canvasRef} />
|
||||||
<Canvas editor={editor} canvasRef={canvasRef} width={800} height={800} />
|
</div>
|
||||||
|
<main>
|
||||||
|
<Tabbar editor={editor} />
|
||||||
|
<Canvas editor={editor} canvasRef={canvasRef} />
|
||||||
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -5,11 +5,9 @@ import { v2 } from "./editor/V2";
|
|||||||
type Props = {
|
type Props = {
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
canvasRef: RefObject<HTMLCanvasElement | null>;
|
canvasRef: RefObject<HTMLCanvasElement | null>;
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function Canvas({ editor, canvasRef, width, height }: Props): ReactElement {
|
function Canvas({ editor, canvasRef }: Props): ReactElement {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canvasRef.current) return;
|
if (!canvasRef.current) return;
|
||||||
|
|
||||||
@ -21,9 +19,7 @@ function Canvas({ editor, canvasRef, width, height }: Props): ReactElement {
|
|||||||
<div className="Canvas">
|
<div className="Canvas">
|
||||||
<canvas
|
<canvas
|
||||||
ref={canvasRef}
|
ref={canvasRef}
|
||||||
width={width}
|
style={{ backgroundColor: "black" }}
|
||||||
height={height}
|
|
||||||
style={{ width, height, backgroundColor: "black" }}
|
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onMouseDown={(ev) => {
|
onMouseDown={(ev) => {
|
||||||
const pos = v2(ev.nativeEvent.offsetX, ev.nativeEvent.offsetY);
|
const pos = v2(ev.nativeEvent.offsetX, ev.nativeEvent.offsetY);
|
||||||
|
|||||||
20
editor/src/Tabbar.tsx
Normal file
20
editor/src/Tabbar.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { useEffect, useState, type ReactElement } from "react";
|
||||||
|
import type { Editor } from "./editor/Editor";
|
||||||
|
|
||||||
|
type Props = { editor: Editor };
|
||||||
|
|
||||||
|
function Tabbar({ editor }: Props): ReactElement {
|
||||||
|
const [selectedTool, setSelectedTool] = useState("select");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="Tabbar">
|
||||||
|
<button className="active"><unnamed></button>
|
||||||
|
<button>Component one</button>
|
||||||
|
<button>Another components</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Tabbar;
|
||||||
@ -15,6 +15,8 @@ function Toolbar({ editor, canvasRef }: Props): ReactElement {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="Toolbar">
|
<div className="Toolbar">
|
||||||
|
<h2>Toolbar</h2>
|
||||||
|
<div>
|
||||||
{editor.tools().map((tool, key) => (
|
{editor.tools().map((tool, key) => (
|
||||||
<button
|
<button
|
||||||
key={`${key}`}
|
key={`${key}`}
|
||||||
@ -28,6 +30,10 @@ function Toolbar({ editor, canvasRef }: Props): ReactElement {
|
|||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<button className="add">+</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { Cx, type Tool } from "./Cx";
|
import { Cx, type Tool } from "./Cx";
|
||||||
import { EventBus } from "./events";
|
import { EventBus } from "./events";
|
||||||
import { V2 } from "./V2";
|
|
||||||
|
|
||||||
export class Editor {
|
export class Editor {
|
||||||
public events = new EventBus();
|
public events = new EventBus();
|
||||||
|
|||||||
@ -14,6 +14,13 @@ export class Renderer {
|
|||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
const { canvas, c } = this;
|
const { canvas, c } = this;
|
||||||
|
|
||||||
|
const width = canvas.offsetWidth;
|
||||||
|
const height = canvas.offsetHeight;
|
||||||
|
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
|
||||||
c.fillStyle = "#666";
|
c.fillStyle = "#666";
|
||||||
c.fillRect(0, 0, canvas.width, canvas.height);
|
c.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
}
|
}
|
||||||
@ -25,8 +32,8 @@ export class Renderer {
|
|||||||
const gridSize = v2(20, 20);
|
const gridSize = v2(20, 20);
|
||||||
|
|
||||||
c.fillStyle = "#111";
|
c.fillStyle = "#111";
|
||||||
for (let y = 0; y < canvas.width / gridSize.x + 1; ++y) {
|
for (let y = 0; y < canvas.height / gridSize.y + 1; ++y) {
|
||||||
for (let x = 0; x < canvas.height / gridSize.y + 1; ++x) {
|
for (let x = 0; x < canvas.width / gridSize.x + 1; ++x) {
|
||||||
c.fillRect(
|
c.fillRect(
|
||||||
(this.offset.x % gridSize.x) + x * gridSize.x - dotSize.x / 2,
|
(this.offset.x % gridSize.x) + x * gridSize.x - dotSize.x / 2,
|
||||||
(this.offset.y % gridSize.y) + y * gridSize.y - dotSize.y / 2,
|
(this.offset.y % gridSize.y) + y * gridSize.y - dotSize.y / 2,
|
||||||
|
|||||||
@ -2,14 +2,21 @@
|
|||||||
color-scheme: light dark;
|
color-scheme: light dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
font-family: sans;
|
||||||
|
}
|
||||||
|
|
||||||
#root {
|
#root {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
min-height: 100svh;
|
height: 100svh;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
|||||||
@ -1,14 +1,51 @@
|
|||||||
|
|
||||||
.Editor {
|
.Editor {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
.Toolbar {
|
.Toolbar {
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
|
max-width: 300px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #2b2a33;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
|
||||||
|
font-size: 1rem;
|
||||||
|
text-transform: capitalize;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
min-width: 200px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 2px solid #2b2a33;
|
||||||
|
}
|
||||||
|
button.active {
|
||||||
|
background-color: #373541;
|
||||||
|
border-bottom: 2px solid #ff8800;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.add {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.Tabbar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 2px;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
@ -19,19 +56,38 @@
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
|
|
||||||
width: 200px;
|
max-width: 200px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border: 2px solid gray;
|
border-radius: 10px 10px 0 0;
|
||||||
border-radius: 5px;
|
|
||||||
|
border: none;
|
||||||
|
border-bottom: 2px solid #2b2a33;
|
||||||
}
|
}
|
||||||
button.active {
|
button.active {
|
||||||
border: 2px solid #ff8800;
|
border-bottom: 2px solid #ff8800;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Canvas {
|
.Canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> div,
|
||||||
|
> main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user