forked from external-repos/LifeTrinket
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
354c0dbbb2 | ||
|
|
3770d13beb | ||
|
|
13733242a2 | ||
|
|
81f3891b20 | ||
|
|
e153de9093 | ||
|
|
07775f85d2 |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "life-trinket",
|
"name": "life-trinket",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.5.5",
|
"version": "0.6.0",
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18",
|
"node": ">=18",
|
||||||
@@ -43,8 +43,9 @@
|
|||||||
"install": "^0.13.0",
|
"install": "^0.13.0",
|
||||||
"postcss": "^8.4.32",
|
"postcss": "^8.4.32",
|
||||||
"prettier": "2.8.8",
|
"prettier": "2.8.8",
|
||||||
"tailwindcss": "^3.4.0",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5.0.2",
|
"typescript": "^5.3.3",
|
||||||
"vite": "^4.4.5"
|
"vite": "^5.0.12",
|
||||||
|
"vite-plugin-pwa": "^0.17.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { twc } from 'react-twc';
|
|||||||
import { Separator } from './Separator';
|
import { Separator } from './Separator';
|
||||||
import { Paragraph } from './TextComponents';
|
import { Paragraph } from './TextComponents';
|
||||||
|
|
||||||
export const ModalWrapper = twc.div`absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[80vw] h-[85vh] bg-background-default p-4 overflow-scroll rounded-2xl border-none text-text-primary`;
|
export const ModalWrapper = twc.div`absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 h-[85vh] bg-background-default p-4 overflow-scroll rounded-2xl border-none text-text-primary w-[95vw] max-w-[548px]`;
|
||||||
|
|
||||||
type InfoModalProps = {
|
type InfoModalProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -12,7 +12,20 @@ type InfoModalProps = {
|
|||||||
|
|
||||||
export const InfoModal = ({ isOpen, closeModal }: InfoModalProps) => {
|
export const InfoModal = ({ isOpen, closeModal }: InfoModalProps) => {
|
||||||
return (
|
return (
|
||||||
<Modal open={isOpen} onClose={closeModal}>
|
<Modal
|
||||||
|
open={isOpen}
|
||||||
|
onClose={closeModal}
|
||||||
|
style={{ display: 'flex', justifyContent: 'center' }}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<div className="flex relative w-full max-w-[548px]">
|
||||||
|
<button
|
||||||
|
onClick={closeModal}
|
||||||
|
className="flex absolute top-10 right-0 z-10 w-10 h-10 text-common-white bg-primary-main items-center justify-center rounded-full border-solid border-primary-dark border-2"
|
||||||
|
>
|
||||||
|
X
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<ModalWrapper>
|
<ModalWrapper>
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl text-center mb-4">📋 Usage Guide</h2>
|
<h2 className="text-2xl text-center mb-4">📋 Usage Guide</h2>
|
||||||
@@ -28,8 +41,8 @@ export const InfoModal = ({ isOpen, closeModal }: InfoModalProps) => {
|
|||||||
subtract <strong>1 life</strong>.
|
subtract <strong>1 life</strong>.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Long press</strong> on a player's + or - button to add or
|
<strong>Long press</strong> on a player's + or - button to add
|
||||||
subtract <strong>10 life</strong>.
|
or subtract <strong>10 life</strong>.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -52,8 +65,8 @@ export const InfoModal = ({ isOpen, closeModal }: InfoModalProps) => {
|
|||||||
When a player is <strong>at or below 0 life</strong>, has taken{' '}
|
When a player is <strong>at or below 0 life</strong>, has taken{' '}
|
||||||
<strong>21 or more Commander Damage</strong> or has{' '}
|
<strong>21 or more Commander Damage</strong> or has{' '}
|
||||||
<strong>10 or more poison counters</strong>, a button with a skull
|
<strong>10 or more poison counters</strong>, a button with a skull
|
||||||
will appear on that player's card. Tapping it will dim the player's
|
will appear on that player's card. Tapping it will dim the
|
||||||
card.
|
player's card.
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center mt-4">
|
<div className="text-center mt-4">
|
||||||
@@ -69,6 +82,7 @@ export const InfoModal = ({ isOpen, closeModal }: InfoModalProps) => {
|
|||||||
for more info about this web app.
|
for more info about this web app.
|
||||||
</div>
|
</div>
|
||||||
</ModalWrapper>
|
</ModalWrapper>
|
||||||
|
</>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -67,6 +67,15 @@ export const SettingsModal = ({ isOpen, closeModal }: SettingsModalProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={isOpen} onClose={closeModal}>
|
<Modal open={isOpen} onClose={closeModal}>
|
||||||
|
<>
|
||||||
|
<div className="flex relative w-full max-w-[548px]">
|
||||||
|
<button
|
||||||
|
onClick={closeModal}
|
||||||
|
className="flex absolute top-10 right-0 z-10 w-10 h-10 text-common-white bg-primary-main items-center justify-center rounded-full border-solid border-primary-dark border-2"
|
||||||
|
>
|
||||||
|
X
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<ModalWrapper>
|
<ModalWrapper>
|
||||||
<Container>
|
<Container>
|
||||||
<h2 className="text-center text-2xl mb-2">⚙️ Settings ⚙️</h2>
|
<h2 className="text-center text-2xl mb-2">⚙️ Settings ⚙️</h2>
|
||||||
@@ -95,13 +104,16 @@ export const SettingsModal = ({ isOpen, closeModal }: SettingsModalProps) => {
|
|||||||
<Switch
|
<Switch
|
||||||
checked={settings.keepAwake}
|
checked={settings.keepAwake}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
setSettings({ ...settings, keepAwake: !settings.keepAwake });
|
setSettings({
|
||||||
|
...settings,
|
||||||
|
keepAwake: !settings.keepAwake,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ToggleContainer>
|
</ToggleContainer>
|
||||||
<Description>
|
<Description>
|
||||||
Will prevent device from going to sleep while this app is open if
|
Will prevent device from going to sleep while this app is open
|
||||||
this is enabled.
|
if this is enabled.
|
||||||
</Description>
|
</Description>
|
||||||
</SettingContainer>
|
</SettingContainer>
|
||||||
<SettingContainer>
|
<SettingContainer>
|
||||||
@@ -135,8 +147,8 @@ export const SettingsModal = ({ isOpen, closeModal }: SettingsModalProps) => {
|
|||||||
</Paragraph>
|
</Paragraph>
|
||||||
</ToggleContainer>
|
</ToggleContainer>
|
||||||
<Description className="mt-1">
|
<Description className="mt-1">
|
||||||
If you do, this app will work offline and the toolbar will be
|
If you do, this app will work offline and the toolbar will
|
||||||
automatically hidden.
|
be automatically hidden.
|
||||||
</Description>
|
</Description>
|
||||||
</SettingContainer>
|
</SettingContainer>
|
||||||
</>
|
</>
|
||||||
@@ -177,6 +189,7 @@ export const SettingsModal = ({ isOpen, closeModal }: SettingsModalProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Container>
|
</Container>
|
||||||
</ModalWrapper>
|
</ModalWrapper>
|
||||||
|
</>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { twc } from 'react-twc';
|
|||||||
import OnePlayerLandscape from '../../../Icons/generated/Layouts/OnePlayerLandscape';
|
import OnePlayerLandscape from '../../../Icons/generated/Layouts/OnePlayerLandscape';
|
||||||
import { Orientation } from '../../../Types/Settings';
|
import { Orientation } from '../../../Types/Settings';
|
||||||
|
|
||||||
const LayoutWrapper = twc.div`flex flex-row justify-between self-center`;
|
const LayoutWrapper = twc.div`flex flex-row justify-center items-center self-center w-full`;
|
||||||
|
|
||||||
type LayoutOptionsProps = {
|
type LayoutOptionsProps = {
|
||||||
numberOfPlayers: number;
|
numberOfPlayers: number;
|
||||||
@@ -31,14 +31,16 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
selectedOrientation,
|
selectedOrientation,
|
||||||
onChange,
|
onChange,
|
||||||
}) => {
|
}) => {
|
||||||
const iconHeight = '30vmin';
|
const iconWidth = '21vmin';
|
||||||
const iconWidth = '20vmin';
|
const iconHeight = '40vmin';
|
||||||
|
const iconMaxWidth = '124px';
|
||||||
|
const iconMaxHeight = '196px';
|
||||||
|
|
||||||
const renderLayoutOptions = () => {
|
const renderLayoutOptions = () => {
|
||||||
switch (numberOfPlayers) {
|
switch (numberOfPlayers) {
|
||||||
case 1:
|
case 1:
|
||||||
return (
|
return (
|
||||||
<>
|
<div>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
value={Orientation.Landscape}
|
value={Orientation.Landscape}
|
||||||
control={
|
control={
|
||||||
@@ -58,6 +60,7 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
TouchRippleProps={{ style: { display: 'none' } }}
|
TouchRippleProps={{ style: { display: 'none' } }}
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label=""
|
label=""
|
||||||
@@ -81,11 +84,12 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
TouchRippleProps={{ style: { display: 'none' } }}
|
TouchRippleProps={{ style: { display: 'none' } }}
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label=""
|
label=""
|
||||||
/>
|
/>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
case 2:
|
case 2:
|
||||||
return (
|
return (
|
||||||
@@ -94,6 +98,7 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
value={Orientation.Landscape}
|
value={Orientation.Landscape}
|
||||||
control={
|
control={
|
||||||
<Radio
|
<Radio
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
icon={
|
icon={
|
||||||
<TwoPlayersSameSide
|
<TwoPlayersSameSide
|
||||||
height={iconHeight}
|
height={iconHeight}
|
||||||
@@ -117,6 +122,7 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
value={Orientation.Portrait}
|
value={Orientation.Portrait}
|
||||||
control={
|
control={
|
||||||
<Radio
|
<Radio
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
icon={
|
icon={
|
||||||
<TwoPlayersOppositePortrait
|
<TwoPlayersOppositePortrait
|
||||||
height={iconHeight}
|
height={iconHeight}
|
||||||
@@ -140,6 +146,7 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
value={Orientation.OppositeLandscape}
|
value={Orientation.OppositeLandscape}
|
||||||
control={
|
control={
|
||||||
<Radio
|
<Radio
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
icon={
|
icon={
|
||||||
<TwoPlayersOppositeLandscape
|
<TwoPlayersOppositeLandscape
|
||||||
height={iconHeight}
|
height={iconHeight}
|
||||||
@@ -168,6 +175,7 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
value={Orientation.Landscape}
|
value={Orientation.Landscape}
|
||||||
control={
|
control={
|
||||||
<Radio
|
<Radio
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
icon={
|
icon={
|
||||||
<ThreePlayers
|
<ThreePlayers
|
||||||
height={iconHeight}
|
height={iconHeight}
|
||||||
@@ -191,6 +199,7 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
value={Orientation.Portrait}
|
value={Orientation.Portrait}
|
||||||
control={
|
control={
|
||||||
<Radio
|
<Radio
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
icon={
|
icon={
|
||||||
<ThreePlayersSide
|
<ThreePlayersSide
|
||||||
height={iconHeight}
|
height={iconHeight}
|
||||||
@@ -220,6 +229,7 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
value={Orientation.Landscape}
|
value={Orientation.Landscape}
|
||||||
control={
|
control={
|
||||||
<Radio
|
<Radio
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
icon={
|
icon={
|
||||||
<FourPlayers
|
<FourPlayers
|
||||||
height={iconHeight}
|
height={iconHeight}
|
||||||
@@ -243,6 +253,7 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
value={Orientation.Portrait}
|
value={Orientation.Portrait}
|
||||||
control={
|
control={
|
||||||
<Radio
|
<Radio
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
icon={
|
icon={
|
||||||
<FourPlayersSide
|
<FourPlayersSide
|
||||||
height={iconHeight}
|
height={iconHeight}
|
||||||
@@ -272,6 +283,7 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
value={Orientation.Landscape}
|
value={Orientation.Landscape}
|
||||||
control={
|
control={
|
||||||
<Radio
|
<Radio
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
icon={
|
icon={
|
||||||
<FivePlayers
|
<FivePlayers
|
||||||
height={iconHeight}
|
height={iconHeight}
|
||||||
@@ -324,6 +336,7 @@ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
|
|||||||
value={Orientation.Landscape}
|
value={Orientation.Landscape}
|
||||||
control={
|
control={
|
||||||
<Radio
|
<Radio
|
||||||
|
style={{ maxWidth: iconMaxWidth, maxHeight: iconMaxHeight }}
|
||||||
icon={
|
icon={
|
||||||
<SixPlayers
|
<SixPlayers
|
||||||
height={iconHeight}
|
height={iconHeight}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ const MainWrapper = twc.div`w-[100dvw] h-fit pb-14 overflow-hidden items-center
|
|||||||
|
|
||||||
const StartButtonFooter = twc.div`w-full max-w-[548px] fixed bottom-4 z-1 items-center flex flex-col px-4`;
|
const StartButtonFooter = twc.div`w-full max-w-[548px] fixed bottom-4 z-1 items-center flex flex-col px-4`;
|
||||||
|
|
||||||
|
const SliderWrapper = twc.div`mx-8`;
|
||||||
|
|
||||||
const ToggleButtonsWrapper = twc.div`flex flex-row justify-between items-center`;
|
const ToggleButtonsWrapper = twc.div`flex flex-row justify-between items-center`;
|
||||||
|
|
||||||
const ToggleContainer = twc.div`flex flex-col items-center`;
|
const ToggleContainer = twc.div`flex flex-col items-center`;
|
||||||
@@ -174,9 +176,10 @@ const Start = () => {
|
|||||||
Life Trinket
|
Life Trinket
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div className="overflow-hidden items-center flex flex-col max-w-[548px] mb-8 px-4">
|
<div className="overflow-hidden items-center flex flex-col max-w-[548px] w-full mb-8 px-4">
|
||||||
<FormControl focused={false}>
|
<FormControl focused={false} style={{ width: '100%' }}>
|
||||||
<FormLabel>Number of Players</FormLabel>
|
<FormLabel>Number of Players</FormLabel>
|
||||||
|
<SliderWrapper>
|
||||||
<Slider
|
<Slider
|
||||||
title="Number of Players"
|
title="Number of Players"
|
||||||
max={6}
|
max={6}
|
||||||
@@ -194,7 +197,10 @@ const Start = () => {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</SliderWrapper>
|
||||||
|
|
||||||
<FormLabel className="mt-[0.7rem]">Starting Health</FormLabel>
|
<FormLabel className="mt-[0.7rem]">Starting Health</FormLabel>
|
||||||
|
<SliderWrapper>
|
||||||
<Slider
|
<Slider
|
||||||
title="Starting Health"
|
title="Starting Health"
|
||||||
max={60}
|
max={60}
|
||||||
@@ -212,6 +218,7 @@ const Start = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</SliderWrapper>
|
||||||
|
|
||||||
<ToggleButtonsWrapper className="mt-4">
|
<ToggleButtonsWrapper className="mt-4">
|
||||||
<ToggleContainer>
|
<ToggleContainer>
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import type { Config } from 'tailwindcss';
|
|||||||
export default {
|
export default {
|
||||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
|
screens: {
|
||||||
|
modalSm: '548px',
|
||||||
|
},
|
||||||
extend: {
|
extend: {
|
||||||
gridTemplateAreas: {
|
gridTemplateAreas: {
|
||||||
onePlayerLandscape: ['player0 player0'],
|
onePlayerLandscape: ['player0 player0'],
|
||||||
@@ -53,10 +56,10 @@ export default {
|
|||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
primary: '#F5F5F5',
|
primary: '#F5F5F5',
|
||||||
secondary: '#b3b39b',
|
secondary: '#76A6A5',
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
disabled: '#5E714C',
|
disabled: '#234A47',
|
||||||
},
|
},
|
||||||
common: {
|
common: {
|
||||||
white: '#F9FFE3',
|
white: '#F9FFE3',
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react-swc';
|
import react from '@vitejs/plugin-react-swc';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import { VitePWA } from 'vite-plugin-pwa';
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [
|
||||||
|
react(),
|
||||||
|
VitePWA({
|
||||||
|
registerType: 'autoUpdate',
|
||||||
|
workbox: {
|
||||||
|
clientsClaim: true,
|
||||||
|
skipWaiting: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
build: {
|
build: {
|
||||||
minify: 'esbuild',
|
minify: 'esbuild',
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
|
|||||||
Reference in New Issue
Block a user