Skip to content

Commit

Permalink
Allow re-opening completed and dead-end modals (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
kangasta authored Jun 14, 2024
1 parent f03edbd commit 5ab720b
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 54 deletions.
16 changes: 16 additions & 0 deletions src/components/Menu/Icon.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script lang="ts">
import { icons, type IIconName } from "./icons";
export let icon: IIconName;
</script>

<svg viewBox="0 0 16 16">
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1"
d={icons[icon].path}
/>
</svg>
37 changes: 7 additions & 30 deletions src/components/Menu/IconButton.svelte
Original file line number Diff line number Diff line change
@@ -1,24 +1,8 @@
<script lang="ts">
import { randomString } from "../../utils/components";
type IIconName = "Close" | "Help" | "Menu" | "Shuffle" | "Undo";
const icons: { [key in IIconName]: { path: string } } = {
Close: {
path: "M 3 3 L 13 13 M 3 13 L 13 3",
},
Help: {
path: "M 8 12 L 8 12 M 8 10 L 8 9 C 8 7 10 8 10 6 A 2 2 0 1 0 6 6 M 8 1.5 A 6.5 6.5 0 0 1 8 14.5 A 6.5 6.5 0 0 1 8 1.5",
},
Menu: {
path: "M 2 4 L 14 4 M 2 8 L 14 8 M 2 12 L 14 12",
},
Shuffle: {
path: "M 5 2 L 2 5 L 5 8 M 2 5 L 12 5 M 11 14 L 14 11 L 11 8 M 14 11 L 4 11",
},
Undo: {
path: "M 5 3 L 2 6 L 5 9 M 2 6 L 10 6 A 3 3 0 1 1 10 13 L 8 13",
},
};
import Icon from "./Icon.svelte";
import type { IIconName } from "./icons";
export let icon: IIconName;
export let label: string;
Expand All @@ -37,16 +21,9 @@
class:open
on:click={onClick}
>
<svg viewBox="0 0 16 16">
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1"
d={icons[icon].path}
/>
</svg>
<div class="icon">
<Icon {icon} />
</div>
</button>
<div class="label" id={labelId}>{label}</div>
</div>
Expand All @@ -65,7 +42,7 @@
&:hover .content
transform: scale(1.1) translateY(-0.15rem)
&:active svg
&:active .icon
transform: translateY(0.15rem)
div.content
Expand All @@ -89,7 +66,7 @@
outline: 3px solid black
border-radius: 0.5em
svg
:global(svg)
height: 2rem
div.label
Expand Down
31 changes: 31 additions & 0 deletions src/components/Menu/icons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export type IIconName =
| "Close"
| "Help"
| "Menu"
| "Minimize"
| "OpenModal"
| "Shuffle"
| "Undo";
export const icons: { [key in IIconName]: { path: string } } = {
Close: {
path: "M 3 3 L 13 13 M 3 13 L 13 3",
},
Help: {
path: "M 8 12 L 8 12 M 8 10 L 8 9 C 8 7 10 8 10 6 A 2 2 0 1 0 6 6 M 8 1.5 A 6.5 6.5 0 0 1 8 14.5 A 6.5 6.5 0 0 1 8 1.5",
},
Menu: {
path: "M 2 4 L 14 4 M 2 8 L 14 8 M 2 12 L 14 12",
},
Minimize: {
path: "M 11 13 L 6.75 13 M 11 11 L 6.75 11 M 11 11 L 11 6.75 M 11 11 L 3 3",
},
OpenModal: {
path: "M 3 3 L 7.25 3 M 3 3 L 3 7.25 M 3 3 L 10 10 M 3 11 A 2 2 0 0 0 5 13 L 11 13 A 2 2 0 0 0 13 11 L 13 5 A 2 2 0 0 0 11 3 L 11 3",
},
Shuffle: {
path: "M 5 2 L 2 5 L 5 8 M 2 5 L 12 5 M 11 14 L 14 11 L 11 8 M 14 11 L 4 11",
},
Undo: {
path: "M 5 3 L 2 6 L 5 9 M 2 6 L 10 6 A 3 3 0 1 1 10 13 L 8 13",
},
};
72 changes: 72 additions & 0 deletions src/components/MinimizeableModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<script lang="ts">
import Icon from "./Menu/Icon.svelte";
import Modal from "./Modal.svelte";
export let title: string;
export let position: "left" | "center" = "center";
let open = true;
const onClose = () => {
setTimeout(() => (open = false), 25);
};
const onOpen = () => {
open = true;
};
</script>

{#if open}
<Modal {title} {position} closeIcon="Minimize" on:close={onClose}>
<slot />
</Modal>
{/if}
<button class="minimized-modal {open ? '' : 'open'}" on:click={onOpen}>
<Icon icon="OpenModal" />
<span class="title">{title}</span>
</button>

<style lang="sass">
.minimized-modal
position: fixed
bottom: -1rem
right: 1.5rem
z-index: 2
appearance: none
background: white
border: 0px none
border-radius: 0.25em
cursor: pointer
padding: 0.33em 0.66em 1.33rem 0.5em
display: flex
align-items: center
gap: 0.25em
font-size: 1rem
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.75)
transition: transform 100ms, box-shadow 100ms
transform: translateY(110%)
&.open
transform: translateY(0)
&:hover
transform: translateY(-0.15rem)
&:active
box-shadow: 0 -0.25rem 1rem rgba(0, 0, 0, 0.75)
transform: translateY(0.1rem)
&:focus-visible
outline: 4px solid black
outline-offset: 4px
:global(svg)
height: 1.5em
vertical-align: top
margin-right: 0.25em
</style>
6 changes: 4 additions & 2 deletions src/components/Modal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import { randomString } from "../utils/components";
import IconButton from "./Menu/IconButton.svelte";
import type { IIconName } from "./Menu/icons";
export let title: string;
export let position: "left" | "center" = "center";
export let closeIcon: IIconName = "Close";
const id = `modal-${randomString()}`;
const titleId = `${id}-title`;
Expand Down Expand Up @@ -55,7 +57,7 @@
>
<div class="header">
<h2 id={titleId}>{title}</h2>
<IconButton icon="Close" label="Close" onClick={onClose} />
<IconButton icon={closeIcon} label="Close" onClick={onClose} />
</div>
<div class="content">
<slot />
Expand Down Expand Up @@ -138,7 +140,7 @@
top: calc(env(titlebar-area-height) + 1rem)
background: white
z-index: 4
z-index: 6
font-size: 1rem
overflow: hidden
Expand Down
15 changes: 4 additions & 11 deletions src/views/Pileon/CompletedModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { createEventDispatcher } from "svelte";
import IconButton from "../../components/Menu/IconButton.svelte";
import Modal from "../../components/Modal.svelte";
import MinimizeableModal from "../../components/MinimizeableModal.svelte";
import { isCompleted, type Piles } from "../../utils/pileon";
import { type IEvent } from "../../utils/statistics";
Expand All @@ -11,20 +11,13 @@
export let events: IEvent[];
export let piles: Piles;
let show = true;
$: completed = isCompleted(piles);
$: events, (show = true);
const dispatch = createEventDispatcher();
</script>

{#if completed && show}
<Modal
title="Completed"
on:close={() => {
show = false;
}}
>
{#if completed}
<MinimizeableModal title="Completed">
<StatisticsTable {events} />
<div class="actions">
<IconButton
Expand All @@ -33,7 +26,7 @@
onClick={() => dispatch("shuffle")}
/>
</div>
</Modal>
</MinimizeableModal>
{/if}

<style lang="sass">
Expand Down
15 changes: 4 additions & 11 deletions src/views/Pileon/DeadEndModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,20 @@
import { createEventDispatcher } from "svelte";
import IconButton from "../../components/Menu/IconButton.svelte";
import Modal from "../../components/Modal.svelte";
import MinimizeableModal from "../../components/MinimizeableModal.svelte";
import { isDeadEnd, type Piles } from "../../utils/pileon";
import { cardsToPrettyString } from "../../utils/text";
export let piles: Piles;
let show = true;
$: [deadEnd, loopCards] = isDeadEnd(piles);
$: loopCardsStr = cardsToPrettyString(loopCards);
$: piles, (show = true);
const dispatch = createEventDispatcher();
</script>

{#if deadEnd && show}
<Modal
title="Dead end"
on:close={() => {
show = false;
}}
>
{#if deadEnd}
<MinimizeableModal title="Dead end">
{#if deadEnd === "dead-end"}
<p>No more possible moves. Undo the last move or start a new game.</p>
{/if}
Expand All @@ -40,7 +33,7 @@
/>
<IconButton icon="Undo" label="Undo" onClick={() => dispatch("undo")} />
</div>
</Modal>
</MinimizeableModal>
{/if}

<style lang="sass">
Expand Down
2 changes: 2 additions & 0 deletions src/views/Pileon/Pileon.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
calculateDimensions,
fillerStacks,
calculateTableEmSize,
isCompleted,
} from "../../utils/pileon";
import { getStackDataTransfer, stackWidthEm } from "../../utils/stack";
import { newEvent } from "../../utils/statistics";
Expand Down Expand Up @@ -75,6 +76,7 @@
$: piles = pilesHistory[pilesHistory.length - 1];
$: donePiles = getDonePiles(piles);
$: isCompleted(piles) && events.push(newEvent("stop"));
let selected: [number, Card[]] = [undefined, []];
Expand Down

0 comments on commit 5ab720b

Please sign in to comment.