Fix some styling & layout things and use events instead of imports

- No component should import SharkGame except App.svelte, except *as a type*
  - use props instead
- Add events for Log
- Make tab not use name but the actual tab instead
This commit is contained in:
Tobias Berger 2021-09-28 14:17:51 +02:00
parent 1ff92d152d
commit 416585e0da
13 changed files with 170 additions and 86 deletions

View file

@ -7,6 +7,6 @@
SharkGame.init();
</script>
<Header />
<Wrapper />
<Header title={SharkGame.title} />
<Wrapper game={SharkGame} />
<Footer />

View file

@ -7,13 +7,8 @@
<style lang="scss">
footer {
user-select: none;
pointer-events: none;
font-size: 80%;
color: var(--color-lighter);
filter: brightness(130%);
> a {
pointer-events: initial;
}
}
</style>

View file

@ -1,16 +0,0 @@
<script lang="ts">
import { SharkGame } from "../shark/SharkGame";
import type { Tabs } from "../shark/Tabs";
export let currentTab: typeof Tabs.currentTab;
</script>
<div>
<svelte:component this={SharkGame.Tabs.Tabs[currentTab]} />
</div>
<style lang="scss">
div {
height: calc(100% - 2em);
}
</style>

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { SharkGame } from "../shark/SharkGame";
export let title: string;
const discordLink = "https://discord.gg/eYqApFkFPY";
@ -38,16 +38,16 @@
</script>
<svelte:head>
<title>{SharkGame.title}</title>
<title>{title}</title>
</svelte:head>
<header>
<header id="header">
<ul id="main-header-buttons">
{#each Object.entries(mainHeaderButtons) as [name, onClick]}
<li><a on:click={onClick} href={"javascript:;"}>{name}</a></li>
{/each}
</ul>
<span>{SharkGame.title}</span>
<span>{title}</span>
<ul id="other-header-buttons">
{#each Object.entries(otherHeaderButtons) as [name, onClick]}
<li>
@ -78,11 +78,6 @@
margin: 0;
padding: 0;
position: fixed;
top: 0;
left: 0;
right: 0;
pointer-events: none;
> span {
@ -104,15 +99,6 @@
&:not(:first-child):before {
content: " | ";
}
> a:link,
> a:visited {
color: var(--color-lighter);
filter: none;
}
> a:hover {
filter: brightness(130%);
}
}
&#main-header-buttons {

View file

@ -1,21 +1,34 @@
<svelte:options immutable />
<script lang="ts">
import { createEventDispatcher } from "svelte";
import { expoOut } from "svelte/easing";
import type { Writable } from "svelte/store";
import { slide } from "svelte/transition";
import { Message, MessageType } from "../shark/Message";
import { SharkGame } from "../shark/SharkGame";
import type {
AddMessageEvent,
ResetMessagesEvent,
Message,
} from "../shark/Message";
import { MessageType } from "../shark/Message";
export let messages: Writable<Message[]>;
export let logLength: number;
const dispatch = createEventDispatcher<{
addMessage: AddMessageEvent;
resetLog: ResetMessagesEvent;
}>();
// Shorthand
function addMessage(message: string, messageType?: MessageType) {
SharkGame.Log.addMessage(message, messageType);
dispatch("addMessage", { message, messageType });
}
function resetMessages() {
dispatch("resetLog", { reset: true });
}
$: logLength = SharkGame.Settings.logLength.current;
$: displayMessages = $messages.slice(-logLength).reverse();
</script>
@ -45,11 +58,7 @@
addMessage("error" + $messages.length, MessageType.error);
}}>Add Error</button
>
<button
on:click={() => {
SharkGame.Log.reset();
}}>Clear log</button
>
<button on:click={resetMessages}>Clear log</button>
<ol>
{#each displayMessages as message, i (message)}
{#if i < logLength}
@ -81,6 +90,7 @@
> li {
padding: 1em 0.4em;
overflow-wrap: break-word;
overflow-anchor: none;
&.odd {
background-color: var(--color-med);

View file

@ -1,21 +1,21 @@
<script lang="ts">
import type { Tabs } from "../shark/Tabs";
export let tabs: typeof Tabs.Tabs;
export let tabs: typeof Tabs.AllTabs;
export let selectedTab: typeof Tabs.currentTab;
$: tabNames = Object.keys(tabs) as typeof selectedTab[];
$: tabEntries = Object.entries(tabs);
</script>
<div>
<ul>
{#each tabNames as tab}
{#each tabEntries as [tabName, tab]}
<li>
<a
on:click={() => {
selectedTab = tab;
}}
disabled={tab === selectedTab}
href={"javascript:;"}>{tab}</a
href={"javascript:;"}>{tabName}</a
>
</li>
{/each}
@ -55,16 +55,11 @@
content: " | ";
}
> a {
color: var(--color-lighter);
}
> a:not([disabled="true"]):hover {
filter: brightness(130%);
> a[disabled="false"] {
text-decoration: none;
}
> a[disabled="true"] {
pointer-events: none;
text-decoration: none;
color: var(--color-light);
text-decoration: underline;
}
}
}

View file

@ -1,11 +1,16 @@
<script lang="ts">
import { createEventDispatcher } from "svelte";
import type { HomeAction } from "../../shark/data/HomeActions";
import { HomeActions } from "../../shark/data/HomeActions";
import { SharkGame } from "../../shark/SharkGame";
import { Resources } from "../../shark/data/Resources";
import type { AddMessageEvent } from "../../shark/Message";
const dispatch = createEventDispatcher<{ addMessage: AddMessageEvent }>();
function homeActionClick(homeAction: HomeAction) {
if (homeAction.effect.resource) {
const resources = SharkGame.Resources.getResources(
const resources = Resources.getResources(
Object.keys(homeAction.effect.resource)
);
@ -17,11 +22,12 @@
}
if (homeAction.outcomes) {
SharkGame.Log.addMessage(
dispatch("addMessage", {
message:
homeAction.outcomes[
Math.floor(Math.random() * homeAction.outcomes.length)
]
);
],
});
}
}
</script>
@ -37,5 +43,6 @@
<style lang="scss">
div {
display: flex;
flex-direction: row;
}
</style>

View file

@ -1 +1,56 @@
Haha, Laboratory go <em>BRRRRRRRRRRRRRRR!</em>
A bunch of empty lines:<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
This is because I wanted to test the scrollability of the content wrapper.
<br />
More lines:<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Egg

View file

@ -1,22 +1,43 @@
<script lang="ts">
import { SharkGame } from "../shark/SharkGame";
import Game from "./Game.svelte";
import type { AddMessageEvent } from "../shark/Message";
import type { SharkGame } from "../shark/SharkGame";
import Log from "./Log.svelte";
import ResourceTable from "./ResourceTable/ResourceTable.svelte";
import TabSelector from "./TabSelector.svelte";
export let game: typeof SharkGame;
$: Game = game;
function handleAddMessage(event: CustomEvent<AddMessageEvent>) {
Game.Log.addMessage(event.detail.message, event.detail.messageType);
}
function handleResetLog() {
Game.Log.reset();
}
</script>
<main>
<div id="left-column">
<ResourceTable bind:resources={SharkGame.Resources.Resources} />
<Log bind:messages={SharkGame.Log.messages} />
<ResourceTable bind:resources={Game.Resources.Resources} />
<Log
bind:logLength={Game.Settings.logLength.current}
bind:messages={Game.Log.messages}
on:addMessage={handleAddMessage}
on:resetLog={handleResetLog}
/>
</div>
<div id="right-column">
<TabSelector
bind:tabs={SharkGame.Tabs.Tabs}
bind:selectedTab={SharkGame.Tabs.currentTab}
bind:tabs={Game.Tabs.AllTabs}
bind:selectedTab={Game.Tabs.currentTab}
/>
<Game bind:currentTab={SharkGame.Tabs.currentTab} />
<div id="tab-content">
<svelte:component
this={Game.Tabs.currentTab}
on:addMessage={handleAddMessage}
/>
</div>
</div>
</main>
@ -26,12 +47,12 @@
flex-direction: row;
background-color: var(--color-dark);
margin: 2em 0 0 0;
padding: 0;
height: 100%;
// Subtract footer and header size
height: calc(100% - 2em - 3em);
overflow-y: scroll;
overflow-y: hidden;
> #left-column {
height: 100%;
@ -41,8 +62,18 @@
}
> #right-column {
height: 100%;
max-height: 100%;
width: 80%;
max-width: 80%;
> #tab-content {
width: 100%;
// Subtract the height of the TabSelector
height: calc(100% - 2em);
overflow-y: scroll;
}
}
}
</style>

View file

@ -1,3 +1,6 @@
export type AddMessageEvent = { message: string; messageType?: MessageType };
export type ResetMessagesEvent = { reset: true };
export enum MessageType {
message = "message",
warning = "warning",

View file

@ -3,9 +3,10 @@ import Lab from "../components/Tabs/Lab.svelte";
import { StaticClass } from "./StaticClass";
export class Tabs extends StaticClass {
static readonly Tabs = {
static readonly AllTabs = {
Home,
Lab,
} as const;
static currentTab: keyof typeof Tabs.Tabs = "Home";
static currentTab: typeof Tabs.AllTabs[keyof typeof Tabs.AllTabs] =
Tabs.AllTabs.Home;
}

View file

@ -7,7 +7,6 @@ export type HomeAction = {
};
outcomes: string[];
multiOutcomes?: string[];
helpText: string;
};
export class HomeActions extends StaticClass {
@ -23,8 +22,6 @@ export class HomeActions extends StaticClass {
fish: 1,
},
},
cost: {},
prereq: {},
outcomes: [
"Dropped the bass.",
"Ate a kipper. Wait. Hang on.",
@ -67,7 +64,21 @@ export class HomeActions extends StaticClass {
"Ate a swedish fish.",
"Ate a goldfish.",
],
helpText: "Use your natural shark prowess to find and catch a fish.",
},
catchShark: {
name: "Catch shark",
effect: {
resource: {
shark: 1,
},
},
outcomes: [
"S h a r k",
"s.h.a.r.k.",
"shark",
"sharg",
"that was probably a shark",
],
},
};
}

View file

@ -1,7 +1,8 @@
@use "./themes.scss";
html {
height: calc(100vh - 2em - 3em);
// Subtract height of header and footer
height: calc(100vh);
}
body {
height: 100%;
@ -20,6 +21,9 @@ a {
&:active {
filter: brightness(135%);
}
&[disabled="true"] {
pointer-events: none;
}
}
button {
@ -29,6 +33,8 @@ button {
text-shadow: 0 0 2px black;
color: white;
user-select: none;
&:hover {
box-shadow: 0 0 2px 2px var(--color-lighter);
}