Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>Basic Blackjack</title>
</head>

<body>
Expand Down
21 changes: 12 additions & 9 deletions src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,23 @@
display: flex;
align-items: center;
justify-content: center;
height: 100dvh;
aspect-ratio: 1/2;
@media only screen and (max-width: 600px) {
height: 100dvh;
width: 100dvw;
aspect-ratio: auto;
}
}
.Content {
@include AppDimensions;
height: 100%;
width: 100%;
position: relative;
overflow: hidden;
background-color: red;
}

.ToggleSettings {
position: absolute;
top: 0;
right: 0;
z-index: 1;
margin: 7px;
height: 30px !important;
width: 30px !important;
height: 50px !important;
width: 50px !important;
font-size: 20px !important;
}
15 changes: 7 additions & 8 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ import "./App.scss";
import Table from "./components/Table";
import { useGameSettingsStore } from "./stores/gameSettingsStore";
import GameSettings from "./components/GameSettings";
import CheckBox from "./components/CheckBox";

const App: React.FC = () => {
const { settingsModalOpen, setSettingsModelOpen } = useGameSettingsStore();
const { settingsModalOpen } = useGameSettingsStore();

return (
<div className="App">
<div className="Content">
<CheckBox
className="ToggleSettings"
checked={settingsModalOpen}
onChanged={(open) => setSettingsModelOpen(open)}
symbol="☰"
/>
{settingsModalOpen && <GameSettings />}
{/*
Rather than conditionally rendering the table,
pass through a boolean to toggle whether it's displayed or not.
This preserves the state of the game, if settings accessed mid-hand.
Could consider moving the entire game state into a store
*/}
<Table hide={settingsModalOpen} />
</div>
</div>
Expand Down
5 changes: 0 additions & 5 deletions src/StyleConstants.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,3 @@ $TableClothShadow: #164624;
border-right: $TableClothShadow 2px solid;
border-bottom: $TableClothShadow 2px solid;
}

@mixin AppDimensions {
height: 563px;
width: 460px;
}
33 changes: 26 additions & 7 deletions src/components/Card/Card.module.scss
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
@import "../../StyleConstants.scss";

.CardWrapper {
display: flex;
align-items: center;
height: 100%;
// 20% of the table width.
// The subtraction of 12px comes from the cards having a 10px gap, and there being 5 of them.
// subtract (10px + 10px / 5 cards)
width: calc(20% - 12px);
}
.Card {
width: 80px;
height: 100px;
margin-top: 10px;
margin-bottom: 10px;
text-align: center;
line-height: 75px;
font-size: 30px;
width: 100%;
height: 80%;
border-radius: 5%;
box-shadow: $TableClothShadow 2px 2px 8px 3px;
animation: slide-from-right 0.3s;
display: flex;
align-items: center;
justify-content: center;
container-type: inline-size;
}
.CardContent {
text-align: center;
overflow-wrap: break-word;
width: 100%;
font-size: 40cqw;
width: 80%;

@media only screen and (max-width: 500px) {
container-type: normal;
font-size: 24px;
}
}
@keyframes slide-from-right {
0% {
transform: translateX(calc(100vw / 2));
Expand Down
6 changes: 4 additions & 2 deletions src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ function Card({ rank, suit, facing }: CardProps) {
}

return (
<div className={styles.Card} style={{ backgroundColor: color }}>
{content}
<div className={styles.CardWrapper}>
<div className={styles.Card} style={{ backgroundColor: color }}>
<div className={styles.CardContent}>{content}</div>
</div>
</div>
);
}
Expand Down
11 changes: 7 additions & 4 deletions src/components/CardRow/CardRow.module.scss
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
@import "../../StyleConstants.scss";

.CardRow {
height: 100%;
display: grid;
grid-template-rows: 1fr 2fr;
.CardOwner {
padding: 10px;
text-align: left;
width: auto;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
background-color: $TableClothDark;
@include TableDarkRaisedSection;
}
.Cards {
display: flex;
flex-wrap: wrap;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 10px;
height: 120px;
}
}
11 changes: 10 additions & 1 deletion src/components/CardRow/CardRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,25 @@ import { Participant } from "../Table";
import { CardObject } from "../Card";

import styles from "./CardRow.module.scss";
import React from "react";

export interface CardRowProps {
cardOwner: Participant;
cards: CardObject[];
children?: React.ReactNode;
}

const CardRow = (props: CardRowProps) => {
return (
<div className={styles.CardRow}>
<div className={styles.CardOwner}>{props.cardOwner} Cards</div>
<div className={styles.CardOwner}>
<span>{props.cardOwner} Cards</span>
{/*
Pretty hacky, but the settings icon is passed
into this row as a child element
*/}
{props.children}
</div>
<div className={styles.Cards}>
{props.cards.map(({ facing, rank, suit }, i) => (
<Card facing={facing} rank={rank} suit={suit} key={i}></Card>
Expand Down
23 changes: 18 additions & 5 deletions src/components/CheckBox/CheckBox.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
import React from "react";
import styles from "./CheckBox.module.scss";

export interface CheckBoxProps {
checked: boolean;
onChanged: (checked: boolean) => void;
className?: string;
symbol?: string;
checkedSymbol?: string;
uncheckedSymbol?: string;
}

const tick = "✔";
const cross = "✕";
export const tick = "✔";
export const cross = "✕";

function CheckBox({ checked, onChanged, className, symbol }: CheckBoxProps) {
function CheckBox({
checked,
onChanged,
className,
symbol,
checkedSymbol,
uncheckedSymbol,
}: CheckBoxProps) {
function getSymbol() {
if (symbol !== undefined) return symbol;
if (checked) return checkedSymbol ?? tick;
return uncheckedSymbol ?? cross;
}
return (
<div
className={[
Expand All @@ -21,7 +34,7 @@ function CheckBox({ checked, onChanged, className, symbol }: CheckBoxProps) {
].join(" ")}
onClick={() => onChanged(!checked)}
>
<div>{symbol ?? (checked ? tick : cross)}</div>
<div>{getSymbol()}</div>
</div>
);
}
Expand Down
2 changes: 2 additions & 0 deletions src/components/CheckBox/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import CheckBox from "./CheckBox";

export * from "./CheckBox";

export default CheckBox;
37 changes: 25 additions & 12 deletions src/components/GameSettings/GameSettings.module.scss
Original file line number Diff line number Diff line change
@@ -1,32 +1,45 @@
@import "../../StyleConstants.scss";

.GameSettings {
display: flex;
flex-direction: column;
gap: 40px;
display: grid;
// This template matches the table template,
// in order to make sure the top bar (which in this case
// says "Game Settings", but on the table shows "Dealer Cards")
// has a consistent hight when switching to/from settings screen.
grid-template-rows: 1fr 8fr;

background-color: $TableClothLight;
color: $White;
padding: 0 12px 12px 12px;
height: 100%;

.Title {
padding: 10px;
text-align: left;
width: auto;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
background-color: $TableClothDark;
@include TableDarkRaisedSection;
align-self: center;
width: 100%;
}
.Content {
display: flex;
flex-direction: column;
padding: 10px;
gap: 40px;
}

.GameSetting {
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 10px;

display: grid;
grid-template-columns: auto 50px;

width: 100%;

.Info {
display: flex;
flex-direction: column;
width: 400px;
.Header {
padding-bottom: 10px;
}
Expand All @@ -43,8 +56,8 @@
width: 50px;

.Control {
width: 100%;
height: auto;
width: 100%;
aspect-ratio: 1 / 1;
}
button {
Expand Down
Loading