diff --git a/front/src/components/navbar.tsx b/front/src/components/navbar.tsx index 331df71f..6146c77f 100644 --- a/front/src/components/navbar.tsx +++ b/front/src/components/navbar.tsx @@ -38,18 +38,17 @@ import { Library, LibraryP, Page, Paged } from "~/models"; import { QueryIdentifier, useFetch } from "~/utils/query"; import { ErrorSnackbar } from "./errors"; -const KyooTitle = (props: { sx: SxProps }) => { +const KyooTitle = () => { const { t } = useTranslation("common"); return ( @@ -57,7 +56,7 @@ const KyooTitle = (props: { sx: SxProps }) => { { - + {isSuccess @@ -110,7 +109,7 @@ export const Navbar = (barProps: AppBarProps) => { ))} - + diff --git a/front/src/components/primitives/text.tsx b/front/src/components/primitives/text.tsx new file mode 100644 index 00000000..3c26a657 --- /dev/null +++ b/front/src/components/primitives/text.tsx @@ -0,0 +1,67 @@ +/* + * Kyoo - A portable and vast media library solution. + * Copyright (c) Kyoo. + * + * See AUTHORS.md and LICENSE file in the project root for full license information. + * + * Kyoo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * Kyoo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Kyoo. If not, see . + */ + +import { forwardRef } from "react"; + +export const Heading = forwardRef< + HTMLHeadingElement, + { + variant: "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; + children?: JSX.Element | JSX.Element[]; + } +>(function Heading({ variant = "h1", children, ...props }, ref) { + const H = variant; + return ( + ({ + font: theme.fonts.heading, + color: theme.heading, + })} + className={`Heading Heading-${variant}`} + > + {children} + + ); +}); + + +export const Paragraph = forwardRef< + HTMLParagraphElement, + { + variant: "normal" | "subtext"; + children?: JSX.Element | JSX.Element[]; + } +>(function Paragraph({ variant, children, ...props }, ref) { + return ( +

({ + font: theme.fonts.paragraph, + color: variant === "normal" ? theme.paragraph : theme.subtext, + })} + className={`Paragraph Paragraph-${variant}`} + > + {children} +

+ ); +}); diff --git a/front/src/pages/_app.tsx b/front/src/pages/_app.tsx index c677300f..ba299414 100755 --- a/front/src/pages/_app.tsx +++ b/front/src/pages/_app.tsx @@ -18,59 +18,83 @@ * along with Kyoo. If not, see . */ -import React, { useState } from "react"; +import React, { ReactNode, useState } from "react"; import appWithI18n from "next-translate/appWithI18n"; -import { ThemeProvider } from "@mui/material"; +import { ThemeProvider, useTheme } from "@emotion/react"; +import { createTheme, ThemeProvider as MTheme } from "@mui/material"; import NextApp, { AppContext } from "next/app"; import type { AppProps } from "next/app"; import { Hydrate, QueryClientProvider } from "react-query"; import { createQueryClient, fetchQuery, QueryIdentifier, QueryPage } from "~/utils/query"; -import { defaultTheme } from "~/utils/themes/default-theme"; import superjson from "superjson"; import Head from "next/head"; import { useMobileHover } from "~/utils/utils"; +import { catppuccin } from "~/utils/themes/catppuccin"; +import { selectMode } from "~/utils/themes/theme"; // Simply silence a SSR warning (see https://github.com/facebook/react/issues/14927 for more details) if (typeof window === "undefined") { React.useLayoutEffect = React.useEffect; } +const ThemeSelector = ({ children }: { children?: ReactNode | ReactNode[] }) => { + // TODO: Handle user selected mode (light, dark, auto) + // TODO: Hande theme change. + return ( + + + {children} + + + ) +} + +const GlobalCssTheme = () => { + const theme = useTheme(); + + return ( + + ); +}; + const App = ({ Component, pageProps }: AppProps) => { const [queryClient] = useState(() => createQueryClient()); - const { queryState, ...props } = superjson.deserialize(pageProps ?? {}); + const { queryState, ...props } = superjson.deserialize(pageProps ?? { json: {} }); const getLayout = (Component as QueryPage).getLayout ?? ((page) => page); useMobileHover(); return ( <> - Kyoo - {getLayout()} + + + {getLayout()} + diff --git a/front/src/utils/themes/catppuccin.ts b/front/src/utils/themes/catppuccin.ts index 5d565649..c1199412 100644 --- a/front/src/utils/themes/catppuccin.ts +++ b/front/src/utils/themes/catppuccin.ts @@ -18,36 +18,17 @@ * along with Kyoo. If not, see . */ -import { Property } from "csstype"; +import { ThemeBuilder } from "./theme"; -// TODO: Add specifics colors -export type Theme = { - fonts: { - heading: string, - paragraph: string, - }, - light: { - appbar: Property.Color, - default: { - background: Property.Color, - accent: Property.Color, - divider: Property.Color, - heading: Property.Color, - paragraph: Property.Color, - subtext: Property.Color, - }, - variant: Theme["light"]["default"], - }, - dark: Theme["light"] -} - -export const catppuccin: Theme = { +export const catppuccin: ThemeBuilder = { fonts: { heading: "Pacifico", paragraph: "Poppins", }, light: { appbar: "#e64553", + contrast: "#cdd6f4", + subcontrast: "#bac2de", default: { background: "#eff1f5", accent: "#ea76cb", @@ -63,10 +44,12 @@ export const catppuccin: Theme = { heading: "#4c4f69", paragraph: "#5c5f77", subtext: "#6c6f85", - } + }, }, dark: { appbar: "#94e2d5", + contrast: "#cdd6f4", + subcontrast: "#bac2de", default: { background: "#1e1e2e", accent: "##f5c2e7", @@ -83,5 +66,5 @@ export const catppuccin: Theme = { paragraph: "#bac2de", subtext: "#a6adc8", }, - } -} + }, +}; diff --git a/front/src/utils/themes/theme.tsx b/front/src/utils/themes/theme.tsx new file mode 100644 index 00000000..bb0de6a4 --- /dev/null +++ b/front/src/utils/themes/theme.tsx @@ -0,0 +1,86 @@ +/* + * Kyoo - A portable and vast media library solution. + * Copyright (c) Kyoo. + * + * See AUTHORS.md and LICENSE file in the project root for full license information. + * + * Kyoo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * Kyoo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Kyoo. If not, see . + */ + +import { Property } from "csstype"; +import "@emotion/react"; +import { Theme, ThemeProvider, useTheme } from "@emotion/react"; + +type ThemeSettings = { + fonts: { + heading: string; + paragraph: string; + }; +}; + +type Mode = Variant & { + appbar: Property.Color; + /* + * The color used in texts or button that are hover black shades on images (ShowHeader, player...) + */ + contrast: Property.Color; + subcontrast: Property.Color; + variant: Variant; +}; + +type Variant = { + background: Property.Color; + accent: Property.Color; + divider: Property.Color; + heading: Property.Color; + paragraph: Property.Color; + subtext: Property.Color; +}; + +declare module "@emotion/react" { + // TODO: Add specifics colors + export interface Theme extends ThemeSettings, Mode {} +} + +export type { Theme } from "@emotion/react"; +export type ThemeBuilder = ThemeSettings & { + light: Mode; + dark: Mode; +}; + +export const selectMode = (theme: ThemeBuilder, mode: "light" | "dark"): Theme => { + const value = (mode === "light" ? theme.light : theme.dark); + return { fonts: theme.fonts, ...(value.default), variant: value.variant }; +}; + +export const switchVariant = (theme: Theme) => { + return { + ...theme, + ...theme.variant, + variant: { + background: theme.background, + accent: theme.accent, + divider: theme.divider, + heading: theme.heading, + paragraph: theme.paragraph, + subtext: theme.subtext, + }, + }; +}; + +export const SwitchVariant = ({ children }: { children?: JSX.Element | JSX.Element[] }) => { + const theme = useTheme(); + + return {children}; +};