mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-13 16:40:01 +00:00
Start theming implementation
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
export class Theme {
|
||||
constructor(
|
||||
public readonly name: string,
|
||||
public readonly primary: string,
|
||||
public readonly secondary?: string,
|
||||
public readonly tertiary?: string
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import {Theme} from "Frontend/components/theming/Theme";
|
||||
import {Typography} from "@material-tailwind/react";
|
||||
|
||||
export default function ThemePreview({theme}: { theme: Theme }) {
|
||||
return (
|
||||
<div className={`
|
||||
size-full bg-background
|
||||
grid grid-rows-3
|
||||
rounded-lg
|
||||
border-2 border-on-background
|
||||
p-4 gap-4
|
||||
`}>
|
||||
<div className="bg-primary flex grow rounded-lg"></div>
|
||||
<div className="bg-secondary flex grow rounded-lg"></div>
|
||||
<div className="bg-tertiary flex grow rounded-lg"></div>
|
||||
<Typography variant="paragraph" className="text-center">{theme.name}</Typography>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import {Theme} from "Frontend/components/theming/Theme";
|
||||
|
||||
export class Themes {
|
||||
public static LIGHT_DEFAULT = new Theme(
|
||||
"Light default",
|
||||
"#000000"
|
||||
)
|
||||
|
||||
public static DARK_DEFAULT = new Theme(
|
||||
"Dark default",
|
||||
"#ffffff"
|
||||
)
|
||||
|
||||
public static all = [
|
||||
Themes.LIGHT_DEFAULT,
|
||||
Themes.DARK_DEFAULT
|
||||
];
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
import React, {useState} from "react";
|
||||
import React, {ReactNode, useState} from "react";
|
||||
import {Form, Formik, FormikBag, FormikHelpers} from "formik";
|
||||
import {Button, Spinner, Step, Stepper} from "@material-tailwind/react";
|
||||
import {ArrowLeft, ArrowRight, Check} from "@phosphor-icons/react";
|
||||
|
||||
const Wizard = ({children, initialValues, onSubmit}: { children: any, initialValues: any, onSubmit: any }) => {
|
||||
const Wizard = ({children, initialValues, onSubmit}: {
|
||||
children: ReactNode,
|
||||
initialValues: any,
|
||||
onSubmit: (values: any, bag: FormikHelpers<any> | FormikBag<any, any>) => Promise<void>
|
||||
}) => {
|
||||
const [stepNumber, setStepNumber] = useState(0);
|
||||
const steps = React.Children.toArray(children);
|
||||
const [snapshot, setSnapshot] = useState(initialValues);
|
||||
@@ -73,7 +77,7 @@ const Wizard = ({children, initialValues, onSubmit}: { children: any, initialVal
|
||||
type="submit"
|
||||
>
|
||||
{formik.isSubmitting ?
|
||||
<Spinner className="h-5 w-5"/> : isLastStep ? <Check/> : <ArrowRight/>
|
||||
<Spinner className="size-5"/> : isLastStep ? <Check/> : <ArrowRight/>
|
||||
}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
const WizardStep = ({children}: { children: any }) => children;
|
||||
import {JSX, ReactNode} from "react";
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export default WizardStep;
|
||||
export default function WizardStep({children, icon, validationSchema}: {
|
||||
children: ReactNode,
|
||||
icon: JSX.Element,
|
||||
validationSchema?: Yup.Schema,
|
||||
onSubmit?: (...values: any) => Promise<void>
|
||||
}) {
|
||||
return children;
|
||||
}
|
||||
|
||||
//const WizardStep = ({children}: { children: Component }) => children;
|
||||
//export default WizardStep;
|
||||
@@ -1,58 +1,74 @@
|
||||
import React from 'react';
|
||||
import {useFormikContext} from 'formik';
|
||||
import * as Yup from 'yup';
|
||||
import Wizard from "Frontend/components/wizard/Wizard";
|
||||
import WizardStep from "Frontend/components/wizard/WizardStep";
|
||||
import {Card, Typography} from "@material-tailwind/react";
|
||||
import Input from "Frontend/components/Input";
|
||||
import {GearFine, HandWaving, User} from "@phosphor-icons/react";
|
||||
import {GearFine, HandWaving, Palette, User} from "@phosphor-icons/react";
|
||||
import {Themes} from "Frontend/components/theming/Themes";
|
||||
import ThemePreview from "Frontend/components/theming/ThemePreview";
|
||||
|
||||
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
function WelcomeStep() {
|
||||
return (
|
||||
<div className="flex flex-col size-full gap-12 items-center">
|
||||
<Typography variant="h4">Welcome to Gameyfin 👋</Typography>
|
||||
<p className="place-content-center text-justify">
|
||||
Gameyfin is a cutting-edge software tailored for gamers seeking efficient management of their
|
||||
video
|
||||
game collections. <br/><br/> With its intuitive interface and comprehensive features, Gameyfin
|
||||
simplifies the organization of game libraries. Users can effortlessly add games through manual
|
||||
input
|
||||
or
|
||||
automated recognition, categorize them based on various criteria like genre or platform, track
|
||||
in-game
|
||||
progress, and share achievements with friends. <br/><br/> Notably, Gameyfin stands out for its
|
||||
user-friendly
|
||||
design and adaptability, offering ample customization options to meet diverse user preferences.
|
||||
</p>
|
||||
<Typography variant="h5">Let's get started!</Typography>
|
||||
<div className="flex flex-col size-full items-center">
|
||||
<div className="flex flex-col w-1/2 min-w-[468px] gap-12 items-center">
|
||||
<Typography variant="h4">Welcome to Gameyfin 👋</Typography>
|
||||
<p className="place-content-center text-justify">
|
||||
Gameyfin is a cutting-edge software tailored for gamers seeking efficient management of their
|
||||
video
|
||||
game collections. <br/><br/> With its intuitive interface and comprehensive features, Gameyfin
|
||||
simplifies the organization of game libraries. Users can effortlessly add games through manual
|
||||
input
|
||||
or
|
||||
automated recognition, categorize them based on various criteria like genre or platform, track
|
||||
in-game
|
||||
progress, and share achievements with friends. <br/><br/> Notably, Gameyfin stands out for its
|
||||
user-friendly
|
||||
design and adaptability, offering ample customization options to meet diverse user preferences.
|
||||
</p>
|
||||
<Typography variant="h5">Let's get started!</Typography>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function UserStep() {
|
||||
const formik = useFormikContext();
|
||||
function ThemeStep() {
|
||||
return (
|
||||
<div className="flex flex-col size-full gap-12 items-center">
|
||||
<Typography variant="h4">Create your account</Typography>
|
||||
<Typography className="-mt-8">This will set up the initial admin user account.</Typography>
|
||||
<div className="mb-1 flex flex-col w-full gap-6">
|
||||
<Input
|
||||
label="Username"
|
||||
name="username"
|
||||
type="text"
|
||||
/>
|
||||
<Input
|
||||
label="Password"
|
||||
name="password"
|
||||
type="password"
|
||||
/>
|
||||
<Input
|
||||
label="Password (repeat)"
|
||||
name="passwordRepeat"
|
||||
type="password"
|
||||
/>
|
||||
<div className="flex flex-col size-full items-center">
|
||||
<div className="size-full grid grid-cols-3 grid-rows-2 w-1/2 min-w-[468px] gap-12 items-center">
|
||||
{Themes.all.map((theme => (
|
||||
<ThemePreview key={theme.name} theme={theme}/>
|
||||
)))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function UserStep() {
|
||||
return (
|
||||
<div className="flex flex-col size-full items-center">
|
||||
<div className="flex flex-col w-1/2 min-w-[468px] gap-12 items-center">
|
||||
<Typography variant="h4">Create your account</Typography>
|
||||
<Typography className="-mt-8">This will set up the initial admin user account.</Typography>
|
||||
<div className="mb-1 flex flex-col w-full gap-6">
|
||||
<Input
|
||||
label="Username"
|
||||
name="username"
|
||||
type="text"
|
||||
/>
|
||||
<Input
|
||||
label="Password"
|
||||
name="password"
|
||||
type="password"
|
||||
/>
|
||||
<Input
|
||||
label="Password (repeat)"
|
||||
name="passwordRepeat"
|
||||
type="password"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -60,9 +76,11 @@ function UserStep() {
|
||||
|
||||
function SettingsStep() {
|
||||
return (
|
||||
<div className="flex flex-col items-center">
|
||||
<Typography variant="h4">Settings</Typography>
|
||||
<Typography>Configure your settings</Typography>
|
||||
<div className="flex flex-col size-full items-center">
|
||||
<div className="flex flex-col w-1/2 min-w-[468px] gap-12 items-center">
|
||||
<Typography variant="h4">Settings</Typography>
|
||||
<Typography>Configure your settings</Typography>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -77,13 +95,13 @@ const SetupView = () => (
|
||||
sleep(300).then(() => alert(JSON.stringify(values, null, 2)))
|
||||
}
|
||||
>
|
||||
<WizardStep
|
||||
// @ts-ignore
|
||||
icon={<HandWaving/>}>
|
||||
<WizardStep icon={<HandWaving/>}>
|
||||
<WelcomeStep/>
|
||||
</WizardStep>
|
||||
<WizardStep icon={<Palette/>}>
|
||||
<ThemeStep/>
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
// @ts-ignore
|
||||
validationSchema={Yup.object({
|
||||
username: Yup.string()
|
||||
.required('Required'),
|
||||
@@ -98,10 +116,7 @@ const SetupView = () => (
|
||||
>
|
||||
<UserStep/>
|
||||
</WizardStep>
|
||||
<WizardStep
|
||||
//@ts-ignore
|
||||
icon={<GearFine/>}
|
||||
>
|
||||
<WizardStep icon={<GearFine/>}>
|
||||
<SettingsStep/>
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
|
||||
Generated
+110
@@ -53,6 +53,7 @@
|
||||
"rollup-plugin-brotli": "3.1.0",
|
||||
"rollup-plugin-visualizer": "5.9.2",
|
||||
"strip-css-comments": "5.0.0",
|
||||
"tailwind-material-colors": "^2.0.2",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"transform-ast": "2.4.4",
|
||||
"typescript": "5.3.3",
|
||||
@@ -2829,6 +2830,12 @@
|
||||
"react-dom": "^16 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/@material/material-color-utilities": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@material/material-color-utilities/-/material-color-utilities-0.2.7.tgz",
|
||||
"integrity": "sha512-0FCeqG6WvK4/Cc06F/xXMd/pv4FeisI0c1tUpBbfhA2n9Y8eZEv4Karjbmf2ZqQCPUWMrGp8A571tCjizxoTiQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@motionone/animation": {
|
||||
"version": "10.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.17.0.tgz",
|
||||
@@ -5597,6 +5604,19 @@
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/color": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1",
|
||||
"color-string": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
@@ -5612,6 +5632,34 @@
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/color-string": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "^1.0.0",
|
||||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/color/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "2.0.20",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
|
||||
@@ -9247,6 +9295,21 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-swizzle": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-arrayish": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-swizzle/node_modules/is-arrayish": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sonic-boom": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz",
|
||||
@@ -9703,11 +9766,49 @@
|
||||
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
|
||||
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
|
||||
},
|
||||
"node_modules/tailwind-material-colors": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-material-colors/-/tailwind-material-colors-2.0.2.tgz",
|
||||
"integrity": "sha512-T2Nf+o8MOCRBFFYAtt0Ddi3paXNzxwIHuHAawZXNOzCA2ZkcMtxhd+fbPExLyxtM4Y8P0cLY0lWHU46fiB9IaQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@material/material-color-utilities": "^0.2.0",
|
||||
"tailwind-material-surfaces": "^3.0.2",
|
||||
"tailwind-mode-aware-colors": "1.4.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tailwindcss": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwind-material-surfaces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-material-surfaces/-/tailwind-material-surfaces-3.0.2.tgz",
|
||||
"integrity": "sha512-ZElG3IPbSrFr2nzxQ++JvNYtJ2ffDfCc/9idAezXYznHrf9vpO0rV9gH1dPUVmXVSkhHerL34Boz14FGZ2H8uw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tailwindcss-color-mix": "0.0.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tailwindcss": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwind-merge": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.8.1.tgz",
|
||||
"integrity": "sha512-+fflfPxvHFr81hTJpQ3MIwtqgvefHZFUHFiIHpVIRXvG/nX9+gu2P7JNlFu2bfDMJ+uHhi/pUgzaYacMoXv+Ww=="
|
||||
},
|
||||
"node_modules/tailwind-mode-aware-colors": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-mode-aware-colors/-/tailwind-mode-aware-colors-1.4.2.tgz",
|
||||
"integrity": "sha512-9PbWN/glpWZypyJvtTgerfDI8XS300hgNTFLheoFFm51ZLNly/tFE2oCtMFm9DkIVGwS3tBn3STTUXdRQYX1SA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color": "^4.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tailwindcss": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz",
|
||||
@@ -9745,6 +9846,15 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss-color-mix": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss-color-mix/-/tailwindcss-color-mix-0.0.8.tgz",
|
||||
"integrity": "sha512-agTN7BAA9eny2WABRX6jpHciQoBoSYGkZfLM1PpHAyNBPErQKFWUm1o1HjwNsZkilJL3hhUi2+H9MoCg+HT89A==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"tailwindcss": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/temp-dir": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
|
||||
|
||||
+2
-1
@@ -48,6 +48,7 @@
|
||||
"rollup-plugin-brotli": "3.1.0",
|
||||
"rollup-plugin-visualizer": "5.9.2",
|
||||
"strip-css-comments": "5.0.0",
|
||||
"tailwind-material-colors": "^2.0.2",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"transform-ast": "2.4.4",
|
||||
"typescript": "5.3.3",
|
||||
@@ -130,6 +131,6 @@
|
||||
"workbox-core": "7.0.0",
|
||||
"workbox-precaching": "7.0.0"
|
||||
},
|
||||
"hash": "4a15d7e79e5a115970b30fcf67cfdd2edab987a6419ed93f8f80f6969d884b1d"
|
||||
"hash": "9223d4c6f4cf3a6fd28b853d824fddc00718dbc1a3474e986f4dc2d69f294b6e"
|
||||
}
|
||||
}
|
||||
|
||||
+16
-11
@@ -1,15 +1,20 @@
|
||||
import withMT from "@material-tailwind/react/utils/withMT";
|
||||
import {withMaterialColors} from "tailwind-material-colors";
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default withMT({
|
||||
content: ["./frontend/index.html", "./frontend/**/*.{js,ts,jsx,tsx}"],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
'gf-primary': '#2332c8',
|
||||
'gf-secondary': '#6441a5'
|
||||
},
|
||||
export default withMaterialColors(withMT({
|
||||
content: ["./frontend/index.html", "./frontend/**/*.{js,ts,jsx,tsx}"],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
'gf-primary': '#2332c8',
|
||||
'gf-secondary': '#6441a5'
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
});
|
||||
plugins: [],
|
||||
}),
|
||||
{
|
||||
primary: "#2332c8"
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user