Compare commits

..

1 Commits

Author SHA1 Message Date
Vikeo
6d3bf32e4b Add the blobs 2024-06-03 15:18:52 +02:00
23 changed files with 337 additions and 328 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "life-trinket",
"private": true,
"version": "0.9.99",
"version": "0.9.96",
"type": "commonjs",
"engines": {
"node": ">=20",

147
pnpm-lock.yaml generated
View File

@@ -41,7 +41,7 @@ importers:
version: 11.11.4(@types/react@18.3.1)(react@18.2.0)
'@emotion/styled':
specifier: ^11.11.5
version: 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.1)(react@18.2.0)
version: 11.11.5(@emotion/react@11.11.4(@types/react@18.3.1)(react@18.2.0))(@types/react@18.3.1)(react@18.2.0)
'@savvywombat/tailwindcss-grid-areas':
specifier: ^4.0.0
version: 4.0.0(tailwindcss@3.4.3)
@@ -59,13 +59,13 @@ importers:
version: 7.5.8
'@typescript-eslint/eslint-plugin':
specifier: ^7.8.0
version: 7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.4.5)
version: 7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
'@typescript-eslint/parser':
specifier: ^7.8.0
version: 7.8.0(eslint@8.57.0)(typescript@5.4.5)
'@vitejs/plugin-react-swc':
specifier: ^3.6.0
version: 3.6.0(vite@5.2.10)
version: 3.6.0(vite@5.2.10(@types/node@20.12.2)(terser@5.30.0))
autoprefixer:
specifier: ^10.4.19
version: 10.4.19(postcss@8.4.38)
@@ -80,7 +80,7 @@ importers:
version: 0.4.6(eslint@8.57.0)
firebase-tools:
specifier: ^13.7.5
version: 13.7.5
version: 13.7.5(encoding@0.1.13)
install:
specifier: ^0.13.0
version: 0.13.0
@@ -101,10 +101,10 @@ importers:
version: 5.4.5
vite:
specifier: ^5.2.10
version: 5.2.10
version: 5.2.10(@types/node@20.12.2)(terser@5.30.0)
vite-plugin-pwa:
specifier: ^0.20.0
version: 0.20.0(vite@5.2.10)(workbox-build@7.1.0)(workbox-window@7.1.0)
version: 0.20.0(vite@5.2.10(@types/node@20.12.2)(terser@5.30.0))(workbox-build@7.1.0)(workbox-window@7.1.0)
packages:
@@ -5740,9 +5740,10 @@ snapshots:
'@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0)
'@emotion/utils': 1.2.1
'@emotion/weak-memoize': 0.3.1
'@types/react': 18.3.1
hoist-non-react-statics: 3.3.2
react: 18.2.0
optionalDependencies:
'@types/react': 18.3.1
'@emotion/serialize@1.1.4':
dependencies:
@@ -5754,7 +5755,7 @@ snapshots:
'@emotion/sheet@1.2.2': {}
'@emotion/styled@11.11.5(@emotion/react@11.11.4)(@types/react@18.3.1)(react@18.2.0)':
'@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.1)(react@18.2.0))(@types/react@18.3.1)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.1
'@emotion/babel-plugin': 11.11.0
@@ -5763,8 +5764,9 @@ snapshots:
'@emotion/serialize': 1.1.4
'@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0)
'@emotion/utils': 1.2.1
'@types/react': 18.3.1
react: 18.2.0
optionalDependencies:
'@types/react': 18.3.1
'@emotion/unitless@0.8.1': {}
@@ -6184,7 +6186,7 @@ snapshots:
'@google-cloud/promisify@2.0.4': {}
'@google-cloud/pubsub@3.7.5':
'@google-cloud/pubsub@3.7.5(encoding@0.1.13)':
dependencies:
'@google-cloud/paginator': 4.0.1
'@google-cloud/precise-date': 3.0.1
@@ -6196,8 +6198,8 @@ snapshots:
'@types/long': 4.0.2
arrify: 2.0.1
extend: 3.0.2
google-auth-library: 8.9.0
google-gax: 3.6.1
google-auth-library: 8.9.0(encoding@0.1.13)
google-gax: 3.6.1(encoding@0.1.13)
heap-js: 2.5.0
is-stream-ended: 0.1.4
lodash.snakecase: 4.1.1
@@ -6345,15 +6347,17 @@ snapshots:
'@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.1)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.1
'@types/react': 18.3.1
react: 18.2.0
optionalDependencies:
'@types/react': 18.3.1
'@radix-ui/react-slot@1.0.2(@types/react@18.3.1)(react@18.2.0)':
dependencies:
'@babel/runtime': 7.24.1
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.1)(react@18.2.0)
'@types/react': 18.3.1
react: 18.2.0
optionalDependencies:
'@types/react': 18.3.1
'@rollup/plugin-babel@5.3.1(@babel/core@7.24.5)(rollup@2.79.1)':
dependencies:
@@ -6370,6 +6374,7 @@ snapshots:
is-builtin-module: 3.2.1
is-module: 1.0.0
resolve: 1.22.8
optionalDependencies:
rollup: 2.79.1
'@rollup/plugin-replace@2.4.2(rollup@2.79.1)':
@@ -6380,10 +6385,11 @@ snapshots:
'@rollup/plugin-terser@0.4.4(rollup@2.79.1)':
dependencies:
rollup: 2.79.1
serialize-javascript: 6.0.2
smob: 1.5.0
terser: 5.30.0
optionalDependencies:
rollup: 2.79.1
'@rollup/pluginutils@3.1.0(rollup@2.79.1)':
dependencies:
@@ -6397,6 +6403,7 @@ snapshots:
'@types/estree': 1.0.5
estree-walker: 2.0.2
picomatch: 2.3.1
optionalDependencies:
rollup: 2.79.1
'@rollup/rollup-android-arm-eabi@4.13.2':
@@ -6502,9 +6509,9 @@ snapshots:
'@svgr/cli@8.1.0(typescript@5.4.5)':
dependencies:
'@svgr/core': 8.1.0(typescript@5.4.5)
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0)
'@svgr/plugin-prettier': 8.1.0(@svgr/core@8.1.0)
'@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0)(typescript@5.4.5)
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.4.5))
'@svgr/plugin-prettier': 8.1.0(@svgr/core@8.1.0(typescript@5.4.5))
'@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.4.5))(typescript@5.4.5)
camelcase: 6.3.0
chalk: 4.1.2
commander: 9.5.0
@@ -6531,7 +6538,7 @@ snapshots:
'@babel/types': 7.24.0
entities: 4.5.0
'@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0)':
'@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.4.5))':
dependencies:
'@babel/core': 7.24.3
'@svgr/babel-preset': 8.1.0(@babel/core@7.24.3)
@@ -6541,13 +6548,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@svgr/plugin-prettier@8.1.0(@svgr/core@8.1.0)':
'@svgr/plugin-prettier@8.1.0(@svgr/core@8.1.0(typescript@5.4.5))':
dependencies:
'@svgr/core': 8.1.0(typescript@5.4.5)
deepmerge: 4.3.1
prettier: 2.8.8
'@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0)(typescript@5.4.5)':
'@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.4.5))(typescript@5.4.5)':
dependencies:
'@svgr/core': 8.1.0(typescript@5.4.5)
cosmiconfig: 8.3.6(typescript@5.4.5)
@@ -6670,7 +6677,7 @@ snapshots:
'@types/trusted-types@2.0.7': {}
'@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.4.5)':
'@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)':
dependencies:
'@eslint-community/regexpp': 4.10.0
'@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5)
@@ -6685,6 +6692,7 @@ snapshots:
natural-compare: 1.4.0
semver: 7.6.2
ts-api-utils: 1.3.0(typescript@5.4.5)
optionalDependencies:
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
@@ -6697,6 +6705,7 @@ snapshots:
'@typescript-eslint/visitor-keys': 7.8.0
debug: 4.3.4
eslint: 8.57.0
optionalDependencies:
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
@@ -6713,6 +6722,7 @@ snapshots:
debug: 4.3.4
eslint: 8.57.0
ts-api-utils: 1.3.0(typescript@5.4.5)
optionalDependencies:
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
@@ -6729,6 +6739,7 @@ snapshots:
minimatch: 9.0.4
semver: 7.6.2
ts-api-utils: 1.3.0(typescript@5.4.5)
optionalDependencies:
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
@@ -6754,10 +6765,10 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
'@vitejs/plugin-react-swc@3.6.0(vite@5.2.10)':
'@vitejs/plugin-react-swc@3.6.0(vite@5.2.10(@types/node@20.12.2)(terser@5.30.0))':
dependencies:
'@swc/core': 1.4.11
vite: 5.2.10
vite: 5.2.10(@types/node@20.12.2)(terser@5.30.0)
transitivePeerDependencies:
- '@swc/helpers'
@@ -6798,7 +6809,7 @@ snapshots:
optional: true
ajv-formats@2.1.1(ajv@8.12.0):
dependencies:
optionalDependencies:
ajv: 8.12.0
ajv@6.12.6:
@@ -7310,6 +7321,7 @@ snapshots:
js-yaml: 4.1.0
parse-json: 5.2.0
path-type: 4.0.0
optionalDependencies:
typescript: 5.4.5
crc-32@1.2.2: {}
@@ -7909,9 +7921,9 @@ snapshots:
locate-path: 6.0.0
path-exists: 4.0.0
firebase-tools@13.7.5:
firebase-tools@13.7.5(encoding@0.1.13):
dependencies:
'@google-cloud/pubsub': 3.7.5
'@google-cloud/pubsub': 3.7.5(encoding@0.1.13)
abort-controller: 3.0.0
ajv: 6.12.6
archiver: 5.3.2
@@ -7936,7 +7948,7 @@ snapshots:
fs-extra: 10.1.0
fuzzy: 0.1.3
glob: 7.2.3
google-auth-library: 7.14.1
google-auth-library: 7.14.1(encoding@0.1.13)
inquirer: 8.2.6
inquirer-autocomplete-prompt: 2.0.1(inquirer@8.2.6)
jsonwebtoken: 9.0.2
@@ -7948,7 +7960,7 @@ snapshots:
mime: 2.6.0
minimatch: 3.1.2
morgan: 1.10.0
node-fetch: 2.7.0
node-fetch: 2.7.0(encoding@0.1.13)
open: 6.4.0
ora: 5.4.1
p-limit: 3.1.0
@@ -7961,13 +7973,13 @@ snapshots:
stream-chain: 2.2.5
stream-json: 1.8.0
strip-ansi: 6.0.1
superstatic: 9.0.3
superstatic: 9.0.3(encoding@0.1.13)
tar: 6.2.1
tcp-port-used: 1.0.2
tmp: 0.2.3
triple-beam: 1.4.1
universal-analytics: 0.5.3
update-notifier-cjs: 5.1.6
update-notifier-cjs: 5.1.6(encoding@0.1.13)
uuid: 8.3.2
winston: 3.13.0
winston-transport: 4.7.0
@@ -8091,38 +8103,38 @@ snapshots:
ga-4-react@0.1.281: {}
gaxios@4.3.3:
gaxios@4.3.3(encoding@0.1.13):
dependencies:
abort-controller: 3.0.0
extend: 3.0.2
https-proxy-agent: 5.0.1
is-stream: 2.0.1
node-fetch: 2.7.0
node-fetch: 2.7.0(encoding@0.1.13)
transitivePeerDependencies:
- encoding
- supports-color
gaxios@5.1.3:
gaxios@5.1.3(encoding@0.1.13):
dependencies:
extend: 3.0.2
https-proxy-agent: 5.0.1
is-stream: 2.0.1
node-fetch: 2.7.0
node-fetch: 2.7.0(encoding@0.1.13)
transitivePeerDependencies:
- encoding
- supports-color
gcp-metadata@4.3.1:
gcp-metadata@4.3.1(encoding@0.1.13):
dependencies:
gaxios: 4.3.3
gaxios: 4.3.3(encoding@0.1.13)
json-bigint: 1.0.0
transitivePeerDependencies:
- encoding
- supports-color
gcp-metadata@5.3.0:
gcp-metadata@5.3.0(encoding@0.1.13):
dependencies:
gaxios: 5.1.3
gaxios: 5.1.3(encoding@0.1.13)
json-bigint: 1.0.0
transitivePeerDependencies:
- encoding
@@ -8221,37 +8233,37 @@ snapshots:
merge2: 1.4.1
slash: 3.0.0
google-auth-library@7.14.1:
google-auth-library@7.14.1(encoding@0.1.13):
dependencies:
arrify: 2.0.1
base64-js: 1.5.1
ecdsa-sig-formatter: 1.0.11
fast-text-encoding: 1.0.6
gaxios: 4.3.3
gcp-metadata: 4.3.1
gtoken: 5.3.2
gaxios: 4.3.3(encoding@0.1.13)
gcp-metadata: 4.3.1(encoding@0.1.13)
gtoken: 5.3.2(encoding@0.1.13)
jws: 4.0.0
lru-cache: 6.0.0
transitivePeerDependencies:
- encoding
- supports-color
google-auth-library@8.9.0:
google-auth-library@8.9.0(encoding@0.1.13):
dependencies:
arrify: 2.0.1
base64-js: 1.5.1
ecdsa-sig-formatter: 1.0.11
fast-text-encoding: 1.0.6
gaxios: 5.1.3
gcp-metadata: 5.3.0
gtoken: 6.1.2
gaxios: 5.1.3(encoding@0.1.13)
gcp-metadata: 5.3.0(encoding@0.1.13)
gtoken: 6.1.2(encoding@0.1.13)
jws: 4.0.0
lru-cache: 6.0.0
transitivePeerDependencies:
- encoding
- supports-color
google-gax@3.6.1:
google-gax@3.6.1(encoding@0.1.13):
dependencies:
'@grpc/grpc-js': 1.8.21
'@grpc/proto-loader': 0.7.12
@@ -8260,9 +8272,9 @@ snapshots:
abort-controller: 3.0.0
duplexify: 4.1.3
fast-text-encoding: 1.0.6
google-auth-library: 8.9.0
google-auth-library: 8.9.0(encoding@0.1.13)
is-stream-ended: 0.1.4
node-fetch: 2.7.0
node-fetch: 2.7.0(encoding@0.1.13)
object-hash: 3.0.0
proto3-json-serializer: 1.1.1
protobufjs: 7.2.4
@@ -8290,18 +8302,18 @@ snapshots:
graphemer@1.4.0: {}
gtoken@5.3.2:
gtoken@5.3.2(encoding@0.1.13):
dependencies:
gaxios: 4.3.3
gaxios: 4.3.3(encoding@0.1.13)
google-p12-pem: 3.1.4
jws: 4.0.0
transitivePeerDependencies:
- encoding
- supports-color
gtoken@6.1.2:
gtoken@6.1.2(encoding@0.1.13):
dependencies:
gaxios: 5.1.3
gaxios: 5.1.3(encoding@0.1.13)
google-p12-pem: 4.0.1
jws: 4.0.0
transitivePeerDependencies:
@@ -8595,9 +8607,9 @@ snapshots:
isexe@3.1.1:
optional: true
isomorphic-fetch@3.0.0:
isomorphic-fetch@3.0.0(encoding@0.1.13):
dependencies:
node-fetch: 2.7.0
node-fetch: 2.7.0(encoding@0.1.13)
whatwg-fetch: 3.6.20
transitivePeerDependencies:
- encoding
@@ -9043,9 +9055,11 @@ snapshots:
dependencies:
lodash: 4.17.21
node-fetch@2.7.0:
node-fetch@2.7.0(encoding@0.1.13):
dependencies:
whatwg-url: 5.0.0
optionalDependencies:
encoding: 0.1.13
node-forge@1.3.1: {}
@@ -9259,8 +9273,9 @@ snapshots:
postcss-load-config@4.0.2(postcss@8.4.38):
dependencies:
lilconfig: 3.1.1
postcss: 8.4.38
yaml: 2.4.1
optionalDependencies:
postcss: 8.4.38
postcss-nested@6.0.1(postcss@8.4.38):
dependencies:
@@ -9882,7 +9897,7 @@ snapshots:
pirates: 4.0.6
ts-interface-checker: 0.1.13
superstatic@9.0.3:
superstatic@9.0.3(encoding@0.1.13):
dependencies:
basic-auth-connect: 1.0.0
commander: 10.0.1
@@ -9901,7 +9916,7 @@ snapshots:
on-headers: 1.0.2
path-to-regexp: 1.8.0
router: 1.3.8
update-notifier-cjs: 5.1.6
update-notifier-cjs: 5.1.6(encoding@0.1.13)
optionalDependencies:
re2: 1.20.10
transitivePeerDependencies:
@@ -10170,7 +10185,7 @@ snapshots:
escalade: 3.1.2
picocolors: 1.0.0
update-notifier-cjs@5.1.6:
update-notifier-cjs@5.1.6(encoding@0.1.13):
dependencies:
boxen: 5.1.2
chalk: 4.1.2
@@ -10181,7 +10196,7 @@ snapshots:
is-installed-globally: 0.4.0
is-npm: 5.0.0
is-yarn-global: 0.3.0
isomorphic-fetch: 3.0.0
isomorphic-fetch: 3.0.0(encoding@0.1.13)
pupa: 2.1.1
registry-auth-token: 5.0.2
registry-url: 5.1.0
@@ -10207,24 +10222,26 @@ snapshots:
vary@1.1.2: {}
vite-plugin-pwa@0.20.0(vite@5.2.10)(workbox-build@7.1.0)(workbox-window@7.1.0):
vite-plugin-pwa@0.20.0(vite@5.2.10(@types/node@20.12.2)(terser@5.30.0))(workbox-build@7.1.0)(workbox-window@7.1.0):
dependencies:
debug: 4.3.4
fast-glob: 3.3.2
pretty-bytes: 6.1.1
vite: 5.2.10
vite: 5.2.10(@types/node@20.12.2)(terser@5.30.0)
workbox-build: 7.1.0
workbox-window: 7.1.0
transitivePeerDependencies:
- supports-color
vite@5.2.10:
vite@5.2.10(@types/node@20.12.2)(terser@5.30.0):
dependencies:
esbuild: 0.20.2
postcss: 8.4.38
rollup: 4.13.2
optionalDependencies:
'@types/node': 20.12.2
fsevents: 2.3.3
terser: 5.30.0
wcwidth@1.0.1:
dependencies:

View File

@@ -9,6 +9,10 @@ export type RotationDivProps = TwcComponentProps<'div'> & {
$rotation?: number;
};
export type RotationSpanProps = TwcComponentProps<'span'> & {
$rotation?: number;
};
export type RotationButtonProps = TwcComponentProps<'button'> & {
$rotation?: number;
};

View File

@@ -3,7 +3,7 @@ import { twc } from 'react-twc';
import { decrementTimeoutMs } from '../../Data/constants';
import { CounterType, Rotation } from '../../Types/Player';
import { OutlinedText } from '../Misc/OutlinedText';
import { MAX_TAP_MOVE_DISTANCE } from './CommanderDamage';
import { MAX_TAP_MOVE_DISTANCE, RotationDivProps } from './CommanderDamage';
const ExtraCounterContainer = twc.div`
flex
@@ -28,14 +28,17 @@ const ExtraCounterButton = twc.button`
webkit-user-select-none
`;
const IconContainer = twc.div`
w-auto opacity-50 data-[rotation-is-side=true]:-rotate-90`;
const IconContainer = twc.div<RotationDivProps>((props) => [
'w-auto opacity-50',
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
? 'rotate-[-90deg]'
: '',
]);
const TextContainer = twc.div`
absolute
top-1/2
left-1/2
data-[rotation-is-side=true]:-rotate-90
`;
type ExtraCounterProps = {
@@ -112,9 +115,6 @@ const ExtraCounter = ({
const fontWeight = 'bold';
const strokeWidth = isSide ? '0.4vmax' : '0.7vmin';
const rotationIsSide =
rotation === Rotation.SideFlipped || rotation === Rotation.Side;
return (
<ExtraCounterContainer>
<ExtraCounterButton
@@ -126,10 +126,8 @@ const ExtraCounter = ({
}}
aria-label={`Player ${playerIndex} extra counter: ${type}`}
>
<IconContainer data-rotation-is-side={rotationIsSide}>
{Icon}
</IconContainer>
<TextContainer data-rotation-is-side={rotationIsSide}>
<IconContainer $rotation={rotation}>{Icon}</IconContainer>
<TextContainer>
<OutlinedText
fontSize={fontSize}
fontWeight={fontWeight}

View File

@@ -1,8 +1,9 @@
import { useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { TwcComponentProps, twc } from 'react-twc';
import { lifeLongPressMultiplier } from '../../Data/constants';
import { Player, Rotation } from '../../Types/Player';
import { MAX_TAP_MOVE_DISTANCE } from './CommanderDamage';
import { checkContrast } from '../../Utils/checkContrast';
type RotationButtonProps = TwcComponentProps<'div'> & {
$align?: string;
@@ -57,6 +58,18 @@ const LifeCounterButton = ({
const [hasPressedDown, setHasPressedDown] = useState(false);
const downPositionRef = useRef({ x: 0, y: 0 });
const [iconColor, setIconColor] = useState<'dark' | 'light'>('dark');
useEffect(() => {
const contrast = checkContrast(player.color, '#00000080');
if (contrast === 'Fail') {
setIconColor('light');
} else {
setIconColor('dark');
}
}, [player.color]);
const handleLifeChange = (increment: number) => {
setLifeTotal(player.lifeTotal + increment);
};
@@ -119,7 +132,7 @@ const LifeCounterButton = ({
<TextContainer
$rotation={player.settings.rotation}
$align={operation === 'add' ? 'right' : 'left'}
data-contrast={player.iconTheme}
data-contrast={iconColor}
className="data-[contrast=dark]:text-icons-dark
data-[contrast=light]:text-icons-light"
>

View File

@@ -10,6 +10,8 @@ import {
import { CounterType, Player, Rotation } from '../../Types/Player';
import { RotationDivProps } from '../Buttons/CommanderDamage';
import ExtraCounter from '../Buttons/ExtraCounter';
import { useEffect, useState } from 'react';
import { checkContrast } from '../../Utils/checkContrast';
const Container = twc.div<RotationDivProps>((props) => [
'flex',
@@ -31,6 +33,17 @@ type ExtraCountersBarProps = {
const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
const { updatePlayer } = usePlayers();
const [iconColor, setIconColor] = useState<'dark' | 'light'>('dark');
useEffect(() => {
const contrast = checkContrast(player.color, '#00000080');
if (contrast === 'Fail') {
setIconColor('light');
} else {
setIconColor('dark');
}
}, [player.color]);
const handleCounterChange = (
updatedCounterTotal: number,
@@ -96,7 +109,7 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
Icon={
<CommanderTax
size={iconSize}
data-contrast={player.iconTheme}
data-contrast={iconColor}
strokeWidth={0}
stroke="transparent"
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
@@ -119,7 +132,7 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
Icon={
<PartnerTax
size={iconSize}
data-contrast={player.iconTheme}
data-contrast={iconColor}
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
/>
}
@@ -140,7 +153,7 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
Icon={
<Poison
size={iconSize}
data-contrast={player.iconTheme}
data-contrast={iconColor}
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
/>
}
@@ -160,7 +173,7 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
Icon={
<Energy
size={iconSize}
data-contrast={player.iconTheme}
data-contrast={iconColor}
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
/>
}
@@ -180,7 +193,7 @@ const ExtraCountersBar = ({ player }: ExtraCountersBarProps) => {
Icon={
<Experience
size={iconSize}
data-contrast={player.iconTheme}
data-contrast={iconColor}
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
/>
}

View File

@@ -1,7 +1,10 @@
import { useEffect, useRef, useState } from 'react';
import { twc } from 'react-twc';
import { Player, Rotation } from '../../Types/Player';
import { RotationDivProps } from '../Buttons/CommanderDamage';
import {
RotationDivProps,
RotationSpanProps,
} from '../Buttons/CommanderDamage';
import LifeCounterButton from '../Buttons/LifeCounterButton';
import { OutlinedText } from '../Misc/OutlinedText';
@@ -29,12 +32,12 @@ const TextWrapper = twc.div`
z-[-1]
`;
const RecentDifference = twc.div`
absolute min-w-[20vmin] drop-shadow-none text-center bg-interface-recentDifference-background tabular-nums rounded-full p-[6px 12px] text-[8vmin] text-interface-recentDifference-text animate-fadeOut
top-1/4 left-[50%] -translate-x-1/2
data-[isSide=true]:top-1/3 data-[isSide=true]:translate-x-1/4 data-[isSide=true]:translate-y-1/2 data-[isSide=true]:rotate-[270deg] data-[isSide=true]:left-auto
`;
const RecentDifference = twc.div<RotationSpanProps>((props) => [
'absolute min-w-[20vmin] drop-shadow-none text-center bg-interface-recentDifference-background tabular-nums rounded-full p-[6px 12px] text-[8vmin] text-interface-recentDifference-text animate-fadeOut',
props.$rotation === Rotation.SideFlipped || props.$rotation === Rotation.Side
? 'top-1/3 translate-x-1/4 translate-y-1/2 rotate-[270deg]'
: 'top-1/4 left-[50%] -translate-x-1/2',
]);
type HealthProps = {
player: Player;
@@ -98,10 +101,6 @@ const Health = ({
return minRatio * scaleFactor * 1;
};
const isSide =
player.settings.rotation === Rotation.SideFlipped ||
player.settings.rotation === Rotation.Side;
return (
<LifeContainer $rotation={player.settings.rotation}>
<LifeCounterButton
@@ -110,31 +109,6 @@ const Health = ({
operation="subtract"
increment={-1}
/>
{player.name && isSide ? (
<div className="size-full relative flex items-center justify-start">
<div className="fixed flex justify-center -rotate-90 left-[5.4vmax] ">
<div
data-contrast={player.iconTheme}
className="absolute text-[4vmin] opacity-50 font-bold
data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
>
{player.name}
</div>
</div>
</div>
) : (
<div className="w-full h-full relative flex items-start justify-center">
<div
data-contrast={player.iconTheme}
className="absolute text-[4vmin] -top-[1.1vmin] opacity-50 font-bold
data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
>
{player.name}
</div>
</div>
)}
<TextWrapper>
<LifeCounterTextContainer
$rotation={player.settings.rotation}
@@ -148,7 +122,10 @@ const Health = ({
{player.lifeTotal}
</OutlinedText>
{recentDifference !== 0 && (
<RecentDifference data-isSide={isSide} key={differenceKey}>
<RecentDifference
key={differenceKey}
$rotation={player.settings.rotation}
>
{recentDifference > 0 ? '+' : ''}
{recentDifference}
</RecentDifference>

View File

@@ -6,6 +6,7 @@ import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
import { usePlayers } from '../../Hooks/usePlayers';
import { Cog } from '../../Icons/generated';
import { Player, Rotation } from '../../Types/Player';
import { checkContrast } from '../../Utils/checkContrast';
import {
RotationButtonProps,
RotationDivProps,
@@ -27,14 +28,22 @@ const SettingsButtonTwc = twc.button<RotationButtonProps>((props) => [
type SettingsButtonProps = {
onClick: () => void;
rotation: Rotation;
iconTheme: 'light' | 'dark';
color: string;
};
const SettingsButton = ({
onClick,
rotation,
iconTheme,
}: SettingsButtonProps) => {
const SettingsButton = ({ onClick, rotation, color }: SettingsButtonProps) => {
const [iconColor, setIconColor] = useState<'dark' | 'light'>('dark');
useEffect(() => {
const contrast = checkContrast(color, '#00000080');
if (contrast === 'Fail') {
setIconColor('light');
} else {
setIconColor('dark');
}
}, [color]);
return (
<SettingsButtonTwc
onClick={onClick}
@@ -43,7 +52,7 @@ const SettingsButton = ({
>
<Cog
size="5vmin"
data-contrast={iconTheme}
data-contrast={iconColor}
className="data-[contrast=dark]:text-icons-dark data-[contrast=light]:text-icons-light"
/>
</SettingsButtonTwc>
@@ -206,9 +215,11 @@ const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
!playing &&
settings.showStartingPlayer &&
player.isStartingPlayer && <StartingPlayerCard player={player} />}
{player.hasLost && (
<PlayerLostWrapper $rotation={player.settings.rotation} />
)}
<CommanderDamageBar
opponents={opponents}
player={player}
@@ -222,7 +233,7 @@ const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
setShowPlayerMenu(!showPlayerMenu);
}}
rotation={player.settings.rotation}
iconTheme={player.iconTheme}
color={player.color}
/>
)}
{playerCanLose(player) && (
@@ -239,6 +250,7 @@ const LifeCounter = ({ player, opponents }: LifeCounterProps) => {
handleLifeChange={handleLifeChange}
/>
<ExtraCountersBar player={player} />
<PlayerMenu
isShown={showPlayerMenu}
player={player}

View File

@@ -11,7 +11,6 @@ import {
Experience,
FullscreenOff,
FullscreenOn,
NameTag,
PartnerTax,
Poison,
ResetGame,
@@ -20,7 +19,6 @@ import { Player, Rotation } from '../../Types/Player';
import { PreStartMode } from '../../Types/Settings';
import { RotationDivProps } from '../Buttons/CommanderDamage';
import { IconCheckbox } from '../Misc/IconCheckbox';
import { checkContrast } from '../../Utils/checkContrast';
const PlayerMenuWrapper = twc.div`
flex
@@ -122,16 +120,8 @@ const PlayerMenu = ({
const { updatePlayer, resetCurrentGame, players } = usePlayers();
const handleColorChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const iconTheme =
checkContrast(event.target.value, '#00000080') === 'Fail'
? 'light'
: 'dark';
updatePlayer({
...player,
color: event.target.value,
iconTheme,
});
const updatedPlayer = { ...player, color: event.target.value };
updatePlayer(updatedPlayer);
};
const handleSettingsChange = (event: React.ChangeEvent<HTMLInputElement>) => {
@@ -162,18 +152,6 @@ const PlayerMenu = ({
setRandomizingPlayer(true);
};
const handleUpdatePlayerName = () => {
const newName = prompt('Enter your name', player.name);
const updatedPlayer: Player = { ...player, name: '' };
if (!newName) {
updatePlayer(updatedPlayer);
return;
}
updatedPlayer.name = newName;
updatePlayer(updatedPlayer);
};
const toggleFullscreen = () => {
if (fullscreen.isFullscreen) {
fullscreen.disableFullscreen();
@@ -418,21 +396,6 @@ const PlayerMenu = ({
Keep Awake
</button>
<button
style={{
cursor: 'pointer',
userSelect: 'none',
fontSize: buttonFontSize,
padding: '2px',
}}
className="text-primary-main"
onClick={handleUpdatePlayerName}
role="name_tag"
aria-label="Name Tag"
>
<NameTag size={iconSize} />
</button>
<button
style={{
cursor: 'pointer',

View File

@@ -1,10 +1,7 @@
import { twc } from 'react-twc';
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
import { usePlayers } from '../../Hooks/usePlayers';
import { Player as PlayerType } from '../../Types/Player';
import { PreStartMode } from '../../Types/Settings';
import LifeCounter from '../LifeCounter/LifeCounter';
import { RoulettePlayerCard } from '../PreStartGame/Games/RandomKing/RoulettePlayerCard';
import { GridLayout } from '../Views/Play';
const getGridArea = (player: PlayerType) => {
@@ -31,8 +28,6 @@ const PlayersWrapper = twc.div`w-full h-full bg-black`;
export const Players = ({ gridLayout }: { gridLayout: GridLayout }) => {
const { players } = usePlayers();
const { playing, settings, preStartCompleted } = useGlobalSettings();
return (
<PlayersWrapper>
<div className={`grid w-full h-full gap-1 box-border ${gridLayout} `}>
@@ -41,7 +36,7 @@ export const Players = ({ gridLayout }: { gridLayout: GridLayout }) => {
return (
<div
key={player.index}
className={`relative flex justify-center items-center align-middle ${gridArea}`}
className={`flex justify-center items-center align-middle ${gridArea}`}
>
<LifeCounter
player={player}
@@ -49,15 +44,6 @@ export const Players = ({ gridLayout }: { gridLayout: GridLayout }) => {
(opponent) => opponent.index !== player.index
)}
/>
{settings.preStartMode === PreStartMode.RandomKing &&
!preStartCompleted &&
!playing &&
settings.showStartingPlayer && (
<div className="absolute size-full z-20">
<RoulettePlayerCard player={player} />
</div>
)}
</div>
);
})}

View File

@@ -0,0 +1,49 @@
import { usePlayers } from '../../../../Hooks/usePlayers';
import { Player } from '../../../../Types/Player';
import { GridLayout } from '../../../Views/Play';
import { RoulettePlayerCard } from './RoulettePlayerCard';
const getGridArea = (player: Player) => {
switch (player.index) {
case 0:
return 'grid-in-player0';
case 1:
return 'grid-in-player1';
case 2:
return 'grid-in-player2';
case 3:
return 'grid-in-player3';
case 4:
return 'grid-in-player4';
case 5:
return 'grid-in-player5';
default:
throw new Error('Invalid player index');
}
};
export const RandomKingPlayers = ({
gridLayout,
}: {
gridLayout: GridLayout;
}) => {
const { players } = usePlayers();
return (
<div className="w-full h-full bg-black">
<div className={`grid w-full h-full gap-1 box-border ${gridLayout} `}>
{players.map((player) => {
const gridArea = getGridArea(player);
return (
<div
key={player.index}
className={`flex justify-center items-center align-middle ${gridArea}`}
>
<RoulettePlayerCard player={player} />
</div>
);
})}
</div>
</div>
);
};

View File

@@ -2,7 +2,7 @@ import { useEffect, useRef } from 'react';
import { useGlobalSettings } from '../../../../Hooks/useGlobalSettings';
import { usePlayers } from '../../../../Hooks/usePlayers';
export const RandomKingRandomizer = () => {
export const RandomKingSelectWrapper = () => {
const { setRandomizingPlayer } = useGlobalSettings();
const randomIntervalRef = useRef<NodeJS.Timeout | null>(null);
@@ -87,7 +87,7 @@ export const RandomKingRandomizer = () => {
backgroundImage: `linear-gradient(60deg, ${gradientColors})`,
}}
/>
<p className="relative z-10 text-[5vmax]">PRESS TO START</p>
<p className="relative z-10 text-[5vmax]">PRESS TO SELECT PLAYER</p>
</div>
</div>
);

View File

@@ -36,7 +36,7 @@ export const RoulettePlayerCard = ({ player }: { player: Player }) => {
: player.settings.rotation;
return (
<div className="relative flex flex-grow flex-col items-center w-full h-full overflow-hidden bg-black">
<div className="relative flex flex-grow flex-col items-center w-full h-full overflow-hidden">
<div
className="flex absolute w-full h-full justify-center items-center pointer-events-none select-none webkit-user-select-none z-10"
style={{ backgroundColor: player.color }}

View File

@@ -1,11 +1,12 @@
import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
import { PreStartMode } from '../../Types/Settings';
import { GridLayout } from '../Views/Play';
import { FingerGame } from './Games/FingerGame';
import { RandomKingRandomizer } from './Games/RandomKing/RandomKingSelectWrapper';
import { RandomKingPlayers } from './Games/RandomKing/RandomKingPlayers';
import { RandomKingSelectWrapper } from './Games/RandomKing/RandomKingSelectWrapper';
import { Trivia } from './Games/Trivia';
export const PreStart = () => {
export const PreStart = ({ gridLayout }: { gridLayout: GridLayout }) => {
const { settings, randomizingPlayer, goToStart } = useGlobalSettings();
if (settings.preStartMode === PreStartMode.RandomKing) {
@@ -13,7 +14,12 @@ export const PreStart = () => {
return null;
}
return <RandomKingRandomizer />;
return (
<>
<RandomKingSelectWrapper />
<RandomKingPlayers gridLayout={gridLayout} />
</>
);
}
if (settings.preStartMode === PreStartMode.FingerGame) {

View File

@@ -94,14 +94,22 @@ export const Play = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
if (
players.length > 1 &&
!preStartCompleted &&
settings.preStartMode !== PreStartMode.None &&
!playing &&
settings.showStartingPlayer
) {
return (
<MainWrapper>
<PreStart gridLayout={gridLayout} />
</MainWrapper>
);
}
return (
<MainWrapper>
{players.length > 1 &&
!preStartCompleted &&
settings.preStartMode !== PreStartMode.None &&
!playing &&
settings.showStartingPlayer && <PreStart />}
<Players gridLayout={gridLayout} />
</MainWrapper>
);

View File

@@ -36,9 +36,9 @@ const standardSettings: Pick<
orientation: Orientation.Landscape,
};
const MainWrapper = twc.div`h-fit w-full pb-24 overflow-hidden items-center flex flex-col min-[349px]:pb-10`;
const MainWrapper = twc.div`h-fit w-full pb-24 overflow-hidden items-center flex flex-col min-[349px]:pb-10 z-10`;
const StartButtonFooter = twc.div`w-full max-w-[548px] fixed bottom-4 z-1 items-center flex flex-row flex-wrap px-4 z-10 gap-4`;
const StartButtonFooter = twc.div`w-full max-w-[548px] fixed bottom-4 z-10 items-center flex flex-row flex-wrap px-4 gap-4`;
const SliderWrapper = twc.div`mx-8 relative`;
@@ -237,14 +237,14 @@ const Start = () => {
<>
<InfoDialog dialogRef={infoDialogRef} />
{settings.showAnimations && (
<>
<div className="blob-container">
<div className="spotlight1" />
<div className="spotlight2" />
</>
</div>
)}
<SettingsDialog dialogRef={settingsDialogRef} />
<div className="flex justify-center items-center w-screen">
<div className="flex justify-center items-center w-screen z-10">
<MainWrapper>
<Info
className="size-8 absolute top-7 left-4 text-primary-main"

View File

@@ -1,6 +1,5 @@
import { Player, Rotation } from '../Types/Player';
import { InitialGameSettings, Orientation } from '../Types/Settings';
import { checkContrast } from '../Utils/checkContrast';
export const presetColors = [
'#D08182', // Muted Pink
@@ -215,8 +214,6 @@ export const createInitialPlayers = ({
lifeTotal: startingLifeTotal,
index: i,
color,
iconTheme:
checkContrast(color, '#00000080') === 'Fail' ? 'light' : 'dark',
settings: {
useCommanderDamage,
usePartner: false,
@@ -230,7 +227,6 @@ export const createInitialPlayers = ({
hasLost: false,
isStartingPlayer: false,
isSide: rotation === Rotation.Side || rotation === Rotation.SideFlipped,
name: '',
};
players.push(player);

View File

@@ -1,36 +0,0 @@
import PropTypes from 'prop-types';
import { SVGProps } from 'react';
interface SVGRProps {
title?: string;
titleId?: string;
size?: string;
}
const NameTag = ({
title,
titleId,
...props
}: SVGProps<SVGSVGElement> & SVGRProps) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={props.size || 16}
height={props.size || 16}
fill="none"
viewBox="0 0 52 52"
aria-labelledby={titleId}
{...props}
>
{title ? <title id={titleId}>{title}</title> : null}
<path
fill="currentColor"
fillRule="evenodd"
d="M33.228 2H48a2 2 0 0 1 2 2v14.772a2 2 0 0 1-.586 1.414L21.721 47.879a3 3 0 0 1-4.242 0L4.12 34.52a3 3 0 0 1 0-4.242L31.814 2.586A2 2 0 0 1 33.228 2m14.105 6a3.333 3.333 0 1 1-6.666 0 3.333 3.333 0 0 1 6.666 0m-16.6 6.644 6.171 6.17 3.773-3.772-.663-.663-3.025 3.026-2.097-2.098 2.784-2.784-.663-.663-2.784 2.785-2.085-2.086 2.977-2.977-.663-.663zm-7.549 7.549.892-.892 7.22 3.025.072-.072-3.025-7.22.892-.892 6.171 6.171-.699.7-4.689-4.69-.06.06 2.76 6.618-.675.675-6.617-2.76-.06.06 4.689 4.689-.7.699zm.69 11.652-.783.783-3.905-8.437.771-.771 8.437 3.905-.783.783-2.368-1.127-2.496 2.496zm.47-5.291-2.024 2.024-1.796-3.772.048-.048zm-2.218 7.04-6.171-6.172-.735.735 4.857 4.858-.06.06-8.232-1.483-.724.724 6.172 6.17.747-.746-4.845-4.846.06-.06 8.208 1.482z"
clipRule="evenodd"
/>
</svg>
);
};
NameTag.propTypes = {
title: PropTypes.string,
};
export default NameTag;

View File

@@ -10,7 +10,6 @@ export { default as FullscreenOn } from './FullscreenOn';
export { default as Info } from './Info';
export { default as LittleGuy } from './LittleGuy';
export { default as Logo } from './Logo';
export { default as NameTag } from './NameTag';
export { default as PartnerTax } from './PartnerTax';
export { default as Poison } from './Poison';
export { default as ResetGame } from './ResetGame';

View File

@@ -1,3 +0,0 @@
<svg width="52" height="52" viewBox="0 0 52 52" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.2284 2H48C49.1046 2 50 2.89543 50 4V18.7716C50 19.302 49.7893 19.8107 49.4142 20.1858L21.7213 47.8787C20.5497 49.0503 18.6502 49.0502 17.4787 47.8787L4.12132 34.5213C2.94974 33.3497 2.94974 31.4503 4.12132 30.2787L31.8142 2.58579C32.1893 2.21071 32.698 2 33.2284 2ZM47.3333 8C47.3333 9.84095 45.8409 11.3333 44 11.3333C42.159 11.3333 40.6667 9.84095 40.6667 8C40.6667 6.15905 42.159 4.66667 44 4.66667C45.8409 4.66667 47.3333 6.15905 47.3333 8ZM30.7334 14.6437L36.9045 20.8148L40.6771 17.0422L40.0142 16.3793L36.9889 19.4046L34.8916 17.3074L37.6759 14.5232L37.013 13.8602L34.2287 16.6445L32.1436 14.5593L35.1207 11.5822L34.4577 10.9193L30.7334 14.6437ZM23.1845 22.1926L24.0764 21.3007L31.2961 24.326L31.3684 24.2537L28.3431 17.0339L29.235 16.142L35.4062 22.3131L34.7071 23.0122L30.0185 18.3236L29.9582 18.3839L32.7183 25.0009L32.0434 25.6759L25.4263 22.9158L25.366 22.976L30.0546 27.6646L29.3556 28.3637L23.1845 22.1926ZM23.8745 33.8448L23.0911 34.6282L19.1859 26.1912L19.9573 25.4198L28.3944 29.3249L27.6109 30.1084L25.2428 28.9811L22.7472 31.4767L23.8745 33.8448ZM24.3446 28.5535L22.3196 30.5785L20.5238 26.8059L20.572 26.7577L24.3446 28.5535ZM22.1261 35.5932L15.9549 29.4221L15.2197 30.1574L20.0771 35.0147L20.0168 35.075L11.7846 33.5924L11.0614 34.3156L17.2326 40.4867L17.9798 39.7395L13.1346 34.8942L13.1948 34.8339L21.4029 36.3164L22.1261 35.5932Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -2,14 +2,12 @@ export type Player = {
lifeTotal: number;
index: number;
color: string;
iconTheme: 'light' | 'dark';
settings: PlayerSettings;
commanderDamage: CommanderDamage[];
extraCounters: ExtraCounter[];
isStartingPlayer: boolean;
hasLost: boolean;
isSide: boolean;
name: string;
};
export type PlayerSettings = {

View File

@@ -81,86 +81,6 @@ code {
}
}
@keyframes background-orb {
0% {
bottom: 10%;
}
50% {
bottom: 90%;
}
100% {
bottom: 10%;
}
}
@keyframes move-right-left {
0% {
rotate: 0deg;
right: 10%;
}
25% {
right: 70%;
}
50% {
rotate: 360deg;
right: 10%;
}
75% {
right: 90%;
}
100% {
rotate: 0deg;
right: 10%;
}
}
.spotlight1 {
background: theme('colors.background.default');
position: fixed;
height: 10vmax;
width: 30vmax;
border-radius: 100%;
transform: translate(50%, 50%);
animation-duration: 30s, 60s;
animation-name: background-orb, move-right-left;
animation-iteration-count: infinite, infinite;
animation-direction: alternate, alternate;
animation-timing-function: ease-in-out;
animation-delay: -15s, -15s;
opacity: 0.8;
mix-blend-mode: screen;
filter: blur(10vmax);
}
.spotlight2 {
background: theme('colors.background.default');
position: fixed;
height: 30vmax;
width: 10vmax;
border-radius: 100%;
transform: translate(50%, 50%);
animation-duration: 60s, 120s;
animation-name: background-orb, move-right-left;
animation-iteration-count: infinite, infinite;
animation-direction: reverse, reverse;
animation-timing-function: ease-in-out;
opacity: 0.8;
mix-blend-mode: screen;
filter: blur(10vmax);
}
input[type='range'] {
-webkit-appearance: none;
transition: background 0ms ease-in;
@@ -229,3 +149,92 @@ input[type='range']::-ms-thumb {
cursor: pointer;
margin-top: -3px;
}
.blob-container {
margin: auto;
position: absolute;
display: flex;
align-items: center;
width: 100vw;
height: 100vh;
filter: blur(10vmax) contrast(10);
z-index: 9;
background: theme('colors.background.default');
mix-blend-mode: screen;
opacity: 30%;
}
@keyframes background-orb {
0% {
bottom: 10%;
}
50% {
bottom: 70%;
}
100% {
bottom: 10%;
}
}
@keyframes move-right-left {
0% {
rotate: 0deg;
right: 10%;
}
25% {
right: 20%;
}
50% {
rotate: 360deg;
right: 10%;
}
75% {
right: 30%;
}
100% {
rotate: 0deg;
right: 10%;
}
}
.spotlight1 {
background: theme('colors.background.spotlight');
position: fixed;
height: 20vmax;
width: 70vmax;
border-radius: 100%;
transform: translate(50%, 50%);
animation-duration: 15s, 50s;
animation-name: background-orb, move-right-left;
animation-iteration-count: infinite, infinite;
animation-direction: alternate, alternate;
animation-timing-function: ease-in-out;
animation-delay: -15s, -15s;
/* filter: blur(5vmax); */
}
.spotlight2 {
background: theme('colors.background.spotlight');
position: fixed;
height: 70vmax;
width: 20vmax;
border-radius: 100%;
transform: translate(50%, 50%);
animation-duration: 30s, 100s;
animation-name: background-orb, move-right-left;
animation-iteration-count: infinite, infinite;
animation-direction: reverse, reverse;
animation-timing-function: ease-in-out;
/* filter: blur(5vmax); */
}

View File

@@ -13,7 +13,7 @@ export const baseColors = {
},
background: {
default: '#2E3041', // Orig: #35374B
spotlight: '#777BA7',
spotlight: 'hsl(110, 80.4%, 32.1%)',
backdrop: 'rgba(0, 0, 0, 0.3)',
settings: 'rgba(0, 0, 0, 0.8)',
},