Merge pull request #20 from jhalitaksoy/fix/refactor-headerbar
Fix/refactor headerbar
This commit is contained in:
commit
9ac8552641
22
.vscode/.snippet.code-snippets
vendored
22
.vscode/.snippet.code-snippets
vendored
@ -15,5 +15,27 @@
|
|||||||
"`}</style>"
|
"`}</style>"
|
||||||
],
|
],
|
||||||
"description": "Log output to console"
|
"description": "Log output to console"
|
||||||
|
},
|
||||||
|
"React Functional Component": {
|
||||||
|
"scope": "typescriptreact",
|
||||||
|
"prefix": "rfc",
|
||||||
|
"body": [
|
||||||
|
"import * as React from 'react';",
|
||||||
|
"import { FunctionComponent } from 'react';",
|
||||||
|
"",
|
||||||
|
"const $TM_FILENAME_BASE: FunctionComponent = () => {",
|
||||||
|
"\treturn (",
|
||||||
|
"\t\t<div>",
|
||||||
|
"\t\t\t$0",
|
||||||
|
"\t\t\t<style jsx>{`",
|
||||||
|
"\t\t\t\t",
|
||||||
|
"\t\t\t`}</style>",
|
||||||
|
"\t\t</div>",
|
||||||
|
"\t);",
|
||||||
|
"}",
|
||||||
|
"",
|
||||||
|
"export default $TM_FILENAME_BASE;"
|
||||||
|
],
|
||||||
|
"description": "Log output to console"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,81 +1,10 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { FunctionComponent } from "react";
|
import { FunctionComponent } from "react";;
|
||||||
import { Menu, MenuItem } from "@szhsin/react-menu";
|
|
||||||
import { MancalaGame } from "mancala.js";
|
|
||||||
import { Context } from "../context/context";
|
|
||||||
import { getColorByBrightness } from "../util/ColorUtil";
|
|
||||||
import Button from "./Button";
|
|
||||||
import "@szhsin/react-menu/dist/index.css";
|
|
||||||
import "@szhsin/react-menu/dist/transitions/slide.css";
|
|
||||||
//@ts-ignore
|
|
||||||
import MancalaIcon from "jsx:../mancala.svg";
|
|
||||||
|
|
||||||
function renderNewGameButton(
|
const HeaderBar: FunctionComponent<{ color?: string }> = ({children, color }) => {
|
||||||
context: Context,
|
|
||||||
game: MancalaGame | undefined,
|
|
||||||
onNewGameClick: () => void,
|
|
||||||
userKeyWhoLeave: string | undefined,
|
|
||||||
crashMessage: string | undefined): JSX.Element {
|
|
||||||
const newGame = (
|
|
||||||
<Button
|
|
||||||
context={context}
|
|
||||||
text={context.texts.NewGame}
|
|
||||||
color={context.themeManager.theme.pitColor}
|
|
||||||
onClick={onNewGameClick}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
if (userKeyWhoLeave) {
|
|
||||||
return newGame;
|
|
||||||
}
|
|
||||||
if (crashMessage) {
|
|
||||||
return newGame;
|
|
||||||
}
|
|
||||||
if (!game) {
|
|
||||||
return newGame;
|
|
||||||
} else if (game.state == "ended") {
|
|
||||||
return newGame;
|
|
||||||
}
|
|
||||||
return <></>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const HeaderBar: FunctionComponent<{
|
|
||||||
context: Context,
|
|
||||||
game?: MancalaGame,
|
|
||||||
userKeyWhoLeave?: string,
|
|
||||||
crashMessage?: string,
|
|
||||||
onNewGameClick: () => void,
|
|
||||||
onLeaveGameClick: () => void
|
|
||||||
}> = (props) => {
|
|
||||||
const { context, game, userKeyWhoLeave, crashMessage, onNewGameClick, onLeaveGameClick } = props;
|
|
||||||
const textColor = getColorByBrightness(
|
|
||||||
context.themeManager.theme.appBarBgColor,
|
|
||||||
context.themeManager.theme.textColor,
|
|
||||||
context.themeManager.theme.textLightColor
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<div style={{ background: context.themeManager.theme.appBarBgColor }} className="header-bar">
|
<div style={{ background: color }} className="header-bar">
|
||||||
<div className="header-bar-left-panel">
|
{children}
|
||||||
<div className="header-bar-icon-wrapper">
|
|
||||||
<MancalaIcon className="header-bar-icon" style={{ height: "30px", width: "30px" }} />
|
|
||||||
</div>
|
|
||||||
<h1 style={{ color: textColor }} className="header-bar-title">
|
|
||||||
{context.texts.Mancala}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div className="header-bar-right-panel">
|
|
||||||
<ThemeSwitchMenu context={context} textColor={textColor} />
|
|
||||||
{renderNewGameButton(context, game, onNewGameClick, userKeyWhoLeave, crashMessage)}
|
|
||||||
{game &&
|
|
||||||
!userKeyWhoLeave &&
|
|
||||||
!crashMessage &&
|
|
||||||
(game?.state === "playing" || game?.state === "initial") && (
|
|
||||||
<Button
|
|
||||||
context={context}
|
|
||||||
color={context.themeManager.theme.pitColor}
|
|
||||||
text={context.texts.Leave}
|
|
||||||
onClick={onLeaveGameClick} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<style jsx>{`
|
<style jsx>{`
|
||||||
.header-bar {
|
.header-bar {
|
||||||
padding: 0px 4vw;
|
padding: 0px 4vw;
|
||||||
@ -85,80 +14,7 @@ const HeaderBar: FunctionComponent<{
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
.header-bar-title {
|
`}</style>
|
||||||
margin: 10px 0px;
|
|
||||||
}
|
|
||||||
.header-bar-right-panel {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.header-bar-left-panel {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
.header-bar-icon-wrapper {
|
|
||||||
margin-right: 10px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
`}</style>
|
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
export default HeaderBar;
|
export default HeaderBar;
|
||||||
|
|
||||||
const ThemeSwitchMenu: FunctionComponent<{ context: Context, textColor: string }> = (props) => {
|
|
||||||
const { context, textColor } = props;
|
|
||||||
const menuButton = <span
|
|
||||||
style={{ color: textColor }}
|
|
||||||
className="material-symbols-outlined">
|
|
||||||
light_mode
|
|
||||||
</span>;
|
|
||||||
const menuItems = context.themeManager.themes.map((theme, index) => {
|
|
||||||
const themeBackground = context.themeManager.theme.background;
|
|
||||||
return (
|
|
||||||
<MenuItem
|
|
||||||
key={index}
|
|
||||||
style={{ color: textColor }}
|
|
||||||
//@ts-ignore
|
|
||||||
onMouseOver={(event) => (event.target.style.background = themeBackground)}
|
|
||||||
//@ts-ignore
|
|
||||||
onMouseOut={(event) => (event.target.style.background = "transparent")}
|
|
||||||
onClick={() => (context.themeManager.theme = theme)}>
|
|
||||||
<div style={{ background: theme.boardColor }} className="theme-color-circle" />
|
|
||||||
{theme.name}
|
|
||||||
<style jsx>{`
|
|
||||||
.theme-color-circle {
|
|
||||||
border-radius: 5vw;
|
|
||||||
width: 1vw;
|
|
||||||
height: 1vw;
|
|
||||||
margin-right: 1vw;
|
|
||||||
}
|
|
||||||
`}</style>
|
|
||||||
</MenuItem>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
return (
|
|
||||||
<div className="menu-container">
|
|
||||||
<Menu
|
|
||||||
menuStyle={{ background: context.themeManager.theme.appBarBgColor }}
|
|
||||||
menuButton={menuButton}
|
|
||||||
transition
|
|
||||||
align="end">
|
|
||||||
{menuItems}
|
|
||||||
</Menu>
|
|
||||||
<style jsx>{`
|
|
||||||
.menu-container {
|
|
||||||
margin: 0 1vh;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
`}</style>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
20
src/components/Row.tsx
Normal file
20
src/components/Row.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { FunctionComponent } from 'react';
|
||||||
|
|
||||||
|
const Row: FunctionComponent = ({children}) => {
|
||||||
|
return (
|
||||||
|
<div className="row">
|
||||||
|
{children}
|
||||||
|
<style jsx>{`
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Row;
|
||||||
22
src/components/headerbar/HeaderbarIcon.tsx
Normal file
22
src/components/headerbar/HeaderbarIcon.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import { FunctionComponent } from "react";
|
||||||
|
//@ts-ignore
|
||||||
|
import MancalaIcon from "jsx:../../mancala.svg";
|
||||||
|
|
||||||
|
const HeaderbarIcon: FunctionComponent = () => {
|
||||||
|
return (
|
||||||
|
<div className="header-bar-icon-wrapper">
|
||||||
|
<MancalaIcon style={{ height: "30px", width: "30px" }} />
|
||||||
|
<style jsx>{`
|
||||||
|
.header-bar-icon-wrapper {
|
||||||
|
margin-right: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HeaderbarIcon;
|
||||||
18
src/components/headerbar/HeaderbarTitle.tsx
Normal file
18
src/components/headerbar/HeaderbarTitle.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { FunctionComponent } from 'react';
|
||||||
|
import { Context } from '../../context/context';
|
||||||
|
|
||||||
|
const HeaderbarTitle: FunctionComponent<{ title: string, color: string }> = ({ title, color }) => {
|
||||||
|
return (
|
||||||
|
<h1 style={{ color: color }} className="header-bar-title">
|
||||||
|
{title}
|
||||||
|
<style jsx>{`
|
||||||
|
.header-bar-title {
|
||||||
|
margin: 10px 0px;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</h1>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HeaderbarTitle;
|
||||||
59
src/components/headerbar/ThemeSwitchMenu.tsx
Normal file
59
src/components/headerbar/ThemeSwitchMenu.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||||
|
import * as React from "react";
|
||||||
|
import { FunctionComponent } from "react";
|
||||||
|
import { Context } from "../../context/context";
|
||||||
|
import "@szhsin/react-menu/dist/index.css";
|
||||||
|
import "@szhsin/react-menu/dist/transitions/slide.css"
|
||||||
|
|
||||||
|
const ThemeSwitchMenu: FunctionComponent<{ context: Context, textColor: string }> = (props) => {
|
||||||
|
const { context, textColor } = props;
|
||||||
|
const menuButton = <span
|
||||||
|
style={{ color: textColor }}
|
||||||
|
className="material-symbols-outlined">
|
||||||
|
light_mode
|
||||||
|
</span>;
|
||||||
|
const menuItems = context.themeManager.themes.map((theme, index) => {
|
||||||
|
const themeBackground = context.themeManager.theme.background;
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
key={index}
|
||||||
|
style={{ color: textColor }}
|
||||||
|
//@ts-ignore
|
||||||
|
onMouseOver={(event) => (event.target.style.background = themeBackground)}
|
||||||
|
//@ts-ignore
|
||||||
|
onMouseOut={(event) => (event.target.style.background = "transparent")}
|
||||||
|
onClick={() => (context.themeManager.theme = theme)}>
|
||||||
|
<div style={{ background: theme.boardColor }} className="theme-color-circle" />
|
||||||
|
{theme.name}
|
||||||
|
<style jsx>{`
|
||||||
|
.theme-color-circle {
|
||||||
|
border-radius: 5vw;
|
||||||
|
width: 1vw;
|
||||||
|
height: 1vw;
|
||||||
|
margin-right: 1vw;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<div className="menu-container">
|
||||||
|
<Menu
|
||||||
|
menuStyle={{ background: context.themeManager.theme.appBarBgColor }}
|
||||||
|
menuButton={menuButton}
|
||||||
|
transition
|
||||||
|
align="end">
|
||||||
|
{menuItems}
|
||||||
|
</Menu>
|
||||||
|
<style jsx>{`
|
||||||
|
.menu-container {
|
||||||
|
margin: 0 1vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThemeSwitchMenu;
|
||||||
@ -22,6 +22,11 @@ import { Theme } from "../theme/Theme";
|
|||||||
import HeaderBar from "../components/HeaderBar";
|
import HeaderBar from "../components/HeaderBar";
|
||||||
import FloatingPanel from "../components/FloatingPanel";
|
import FloatingPanel from "../components/FloatingPanel";
|
||||||
import PageContainer from "../components/PageContainer";
|
import PageContainer from "../components/PageContainer";
|
||||||
|
import Row from "../components/Row";
|
||||||
|
import HeaderbarIcon from "../components/headerbar/HeaderbarIcon";
|
||||||
|
import HeaderbarTitle from "../components/headerbar/HeaderbarTitle";
|
||||||
|
import ThemeSwitchMenu from "../components/headerbar/ThemeSwitchMenu";
|
||||||
|
import Button from "../components/Button";
|
||||||
|
|
||||||
type ConnectionState = "connecting" | "error" | "connected" | "reconnecting";
|
type ConnectionState = "connecting" | "error" | "connected" | "reconnecting";
|
||||||
|
|
||||||
@ -184,19 +189,31 @@ const Home: FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
|
|||||||
context.themeManager.theme.textColor,
|
context.themeManager.theme.textColor,
|
||||||
context.themeManager.theme.textLightColor
|
context.themeManager.theme.textLightColor
|
||||||
);
|
);
|
||||||
|
const textColorOnAppBar = getColorByBrightness(
|
||||||
|
context.themeManager.theme.appBarBgColor,
|
||||||
|
context.themeManager.theme.textColor,
|
||||||
|
context.themeManager.theme.textLightColor
|
||||||
|
);
|
||||||
|
const renderNewGameBtn = userKeyWhoLeave || !game || (game && game.state == "ended");
|
||||||
return (
|
return (
|
||||||
<PageContainer theme={theme!}>
|
<PageContainer theme={theme!}>
|
||||||
<FloatingPanel context={context} color={context.themeManager.theme.boardColor} visible={showConnectionState}>
|
<FloatingPanel context={context} color={context.themeManager.theme.boardColor} visible={showConnectionState}>
|
||||||
<span style={{ color: textColorOnBoard }}>{connectionStateText()}</span>
|
<span style={{ color: textColorOnBoard }}>{connectionStateText()}</span>
|
||||||
</FloatingPanel>
|
</FloatingPanel>
|
||||||
<HeaderBar
|
<HeaderBar color={theme?.appBarBgColor}>
|
||||||
context={context}
|
<Row>
|
||||||
game={game}
|
<HeaderbarIcon />
|
||||||
userKeyWhoLeave={userKeyWhoLeave}
|
<HeaderbarTitle title={context.texts.Mancala} color={textColorOnAppBar} />
|
||||||
crashMessage={crashMessage}
|
</Row>
|
||||||
onNewGameClick={onNewGameClick}
|
<Row>
|
||||||
onLeaveGameClick={onLeaveGameClick} />
|
<ThemeSwitchMenu context={context} textColor={textColorOnAppBar} />
|
||||||
|
<Button
|
||||||
|
context={context}
|
||||||
|
color={context.themeManager.theme.pitColor}
|
||||||
|
text={renderNewGameBtn ? context.texts.NewGame : context.texts.Leave}
|
||||||
|
onClick={renderNewGameBtn ? onNewGameClick : onLeaveGameClick} />
|
||||||
|
</Row>
|
||||||
|
</HeaderBar>
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
context={context}
|
context={context}
|
||||||
game={game}
|
game={game}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user