Finish movie's header rework

This commit is contained in:
Zoe Roux 2022-12-13 14:13:15 +09:00
parent e5b236f51c
commit 1b76bbf6c2
14 changed files with 464 additions and 283 deletions

View File

@ -31,7 +31,7 @@
"react-native-safe-area-context": "4.4.1", "react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0", "react-native-screens": "~3.18.0",
"react-native-svg": "13.4.0", "react-native-svg": "13.4.0",
"yoshiki": "0.2.11" "yoshiki": "0.3.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.19.3", "@babel/core": "^7.19.3",

View File

@ -41,7 +41,7 @@
"react-native-web": "^0.18.10", "react-native-web": "^0.18.10",
"solito": "^2.0.5", "solito": "^2.0.5",
"superjson": "^1.11.0", "superjson": "^1.11.0",
"yoshiki": "0.2.11", "yoshiki": "0.3.1",
"zod": "^3.19.1" "zod": "^3.19.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -19,7 +19,7 @@
*/ */
import { View, ViewProps } from "react-native"; import { View, ViewProps } from "react-native";
import { useYoshiki } from "yoshiki/native"; import { percent, px, useYoshiki } from "yoshiki/native";
export const Container = (props: ViewProps) => { export const Container = (props: ViewProps) => {
const { css } = useYoshiki(); const { css } = useYoshiki();
@ -29,12 +29,13 @@ export const Container = (props: ViewProps) => {
{...css( {...css(
{ {
display: "flex", display: "flex",
paddingHorizontal: "15px", paddingHorizontal: px(15),
marginHorizontal: "auto", marginHorizontal: "auto",
width: { width: {
sm: "540px", xs: percent(100),
md: "880px", sm: px(540),
lg: "1170px", md: px(880),
lg: px(1170),
}, },
}, },
props, props,

View File

@ -0,0 +1,56 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { HR as EHR } from "@expo/html-elements";
import { percent, px, Stylable, useYoshiki } from "yoshiki/native";
import { alpha, ts } from ".";
export const HR = ({
orientation,
...props
}: { orientation: "vertical" | "horizontal" } & Stylable) => {
const { css } = useYoshiki();
return (
<EHR
{...css(
[
{
bg: (theme) => alpha(theme.overlay0, 0.7),
borderWidth: 0,
},
orientation === "vertical" && {
width: px(1),
height: "auto",
marginVertical: ts(1),
marginHorizontal: ts(2),
},
orientation === "horizontal" && {
height: px(1),
width: "auto",
marginHorizontal: ts(1),
marginVertical: ts(2),
},
],
props,
)}
/>
);
};

View File

@ -18,7 +18,7 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>. * along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/ */
export { Header, Main, Nav, Footer } from "@expo/html-elements"; export { Header, Main, Nav, Footer, UL } from "@expo/html-elements";
export * from "./text"; export * from "./text";
export * from "./themes"; export * from "./themes";
export * from "./icons"; export * from "./icons";
@ -28,11 +28,13 @@ export * from "./image";
export * from "./skeleton"; export * from "./skeleton";
export * from "./tooltip"; export * from "./tooltip";
export * from "./container"; export * from "./container";
export * from "./divider";
export * from "./animated"; export * from "./animated";
export * from "./utils/breakpoints"; export * from "./utils/breakpoints";
export * from "./utils/nojs"; export * from "./utils/nojs";
export * from "./utils/head";
import { px } from "yoshiki/native"; import { px } from "yoshiki/native";

View File

@ -43,10 +43,13 @@ export const A = ({
textProps={css( textProps={css(
{ {
// TODO: use a real font here. // TODO: use a real font here.
fontFamily: Platform.OS === "web" ? theme.fonts.paragraph : undefined, // fontFamily: theme.fonts.paragraph,
color: theme.paragraph, color: theme.link,
},
{
selectable: true,
...props,
}, },
props,
)} )}
> >
{children} {children}
@ -83,8 +86,8 @@ export const Link = ({
})} })}
> >
{Platform.select<ReactNode>({ {Platform.select<ReactNode>({
android: <View {...props}>{children}</View>, android: <View {...noFocusProps}>{children}</View>,
ios: <View {...props}>{children}</View>, ios: <View {...noFocusProps}>{children}</View>,
default: children, default: children,
})} })}
</LinkCore> </LinkCore>

View File

@ -46,11 +46,13 @@ export const SkeletonCss = () => (
export const Skeleton = ({ export const Skeleton = ({
children, children,
show: forcedShow, show: forcedShow,
lines = 1,
variant = "text", variant = "text",
...props ...props
}: Omit<ViewProps, "children"> & { }: Omit<ViewProps, "children"> & {
children?: JSX.Element | JSX.Element[] | boolean | null; children?: JSX.Element | JSX.Element[] | boolean | null;
show?: boolean; show?: boolean;
lines?: number;
variant?: "text" | "round" | "custom"; variant?: "text" | "round" | "custom";
}) => { }) => {
const { css, theme } = useYoshiki(); const { css, theme } = useYoshiki();
@ -65,12 +67,13 @@ export const Skeleton = ({
[ [
{ {
position: "relative", position: "relative",
overflow: "hidden",
borderRadius: px(6),
}, },
variant === "text" && { lines === 1 && { overflow: "hidden", borderRadius: px(6) },
variant === "text" &&
lines === 1 && {
width: percent(75), width: percent(75),
height: rem(1.2), height: rem(1.2),
marginBottom: rem(0.5),
}, },
variant === "round" && { variant === "round" && {
borderRadius: 9999999, borderRadius: 9999999,
@ -81,23 +84,35 @@ export const Skeleton = ({
> >
<AnimatePresence> <AnimatePresence>
{children} {children}
{(forcedShow || !children || children === true) && ( {(forcedShow || !children || children === true) &&
[...Array(lines)].map((_, i) => (
<MotiView <MotiView
key="skeleton" key={`skeleton_${i}`}
// No clue why it is a number on mobile and a string on web but /shrug // No clue why it is a number on mobile and a string on web but /shrug
animate={{ opacity: Platform.OS === "web" ? "1" : 1 }} animate={{ opacity: Platform.OS === "web" ? "1" : 1 }}
exit={{ opacity: 0 }} exit={{ opacity: 0 }}
transition={{ type: "timing" }} transition={{ type: "timing" }}
onLayout={(e) => setWidth(e.nativeEvent.layout.width)} onLayout={(e) => setWidth(e.nativeEvent.layout.width)}
{...css( {...css(
[
{ {
bg: (theme) => theme.overlay0, bg: (theme) => theme.overlay0,
},
lines === 1 && {
position: "absolute", position: "absolute",
top: 0, top: 0,
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0, right: 0,
}, },
lines !== 1 && {
width: i === lines - 1 ? percent(40) : percent(100),
height: rem(1.2),
marginBottom: rem(0.5),
overflow: "hidden",
borderRadius: px(6),
},
],
hiddenIfNoJs, hiddenIfNoJs,
)} )}
> >
@ -130,7 +145,7 @@ export const Skeleton = ({
])} ])}
/> />
</MotiView> </MotiView>
)} ))}
</AnimatePresence> </AnimatePresence>
</View> </View>
); );

View File

@ -19,8 +19,8 @@
*/ */
import { ComponentType, ComponentProps } from "react"; import { ComponentType, ComponentProps } from "react";
import { Platform, TextProps } from "react-native"; import { Platform, Text, TextProps, TextStyle } from "react-native";
import { rem, useYoshiki } from "yoshiki/native"; import { percent, px, rem, useYoshiki } from "yoshiki/native";
import { import {
H1 as EH1, H1 as EH1,
H2 as EH2, H2 as EH2,
@ -29,11 +29,14 @@ import {
H5 as EH5, H5 as EH5,
H6 as EH6, H6 as EH6,
P as EP, P as EP,
LI as ELI,
} from "@expo/html-elements"; } from "@expo/html-elements";
import { ts } from ".";
const styleText = ( const styleText = (
Component: ComponentType<ComponentProps<typeof EP>>, Component: ComponentType<ComponentProps<typeof EP>>,
type?: "header" | "sub", type?: "header" | "sub",
custom?: TextStyle,
) => { ) => {
const Text = (props: ComponentProps<typeof EP>) => { const Text = (props: ComponentProps<typeof EP>) => {
const { css, theme } = useYoshiki(); const { css, theme } = useYoshiki();
@ -43,16 +46,13 @@ const styleText = (
{...css( {...css(
[ [
{ {
// TODO: use custom fonts on mobile also. marginTop: 0,
fontFamily: marginBottom: rem(0.5),
Platform.OS === "web" // fontFamily: type === "header" ? theme.fonts.heading : theme.fonts.paragraph,
? type === "header"
? theme.fonts.heading
: theme.fonts.paragraph
: undefined,
color: type === "header" ? theme.heading : theme.paragraph, color: type === "header" ? theme.heading : theme.paragraph,
}, },
type === "sub" && { fontWeight: "300", opacity: 0.8, fontSize: rem(0.8) }, type === "sub" && { fontWeight: "300", opacity: 0.8, fontSize: rem(0.8) },
custom,
], ],
props as TextProps, props as TextProps,
)} )}
@ -62,12 +62,31 @@ const styleText = (
return Text; return Text;
}; };
export const H1 = styleText(EH1, "header"); export const H1 = styleText(EH1, "header", { fontSize: rem(3) });
export const H2 = styleText(EH2, "header"); export const H2 = styleText(EH2, "header", { fontSize: rem(2) });
export const H3 = styleText(EH3, "header"); export const H3 = styleText(EH3, "header");
export const H4 = styleText(EH4, "header"); export const H4 = styleText(EH4, "header");
export const H5 = styleText(EH5, "header"); export const H5 = styleText(EH5, "header");
export const H6 = styleText(EH6, "header"); export const H6 = styleText(EH6, "header");
export const Heading = styleText(EP, "header"); export const Heading = styleText(EP, "header");
export const P = styleText(EP); export const P = styleText(EP, undefined, { fontSize: rem(1) });
export const SubP = styleText(EP, "sub"); export const SubP = styleText(EP, "sub");
export const LI = ({ children, ...props }: TextProps) => {
const { css } = useYoshiki();
return (
<P accessibilityRole="listitem" {...props}>
<Text
{...css({
height: percent(100),
marginBottom: rem(0.5),
paddingRight: ts(1),
})}
>
{String.fromCharCode(0x2022)}
</Text>
{children}
</P>
);
};

View File

@ -31,6 +31,7 @@ export const catppuccin: ThemeBuilder = {
appbar: "#e64553", appbar: "#e64553",
overlay0: "#9ca0b0", overlay0: "#9ca0b0",
overlay1: "#7c7f93", overlay1: "#7c7f93",
link: "#1e66f5",
default: { default: {
background: "#eff1f5", background: "#eff1f5",
accent: "#ea76cb", accent: "#ea76cb",
@ -61,6 +62,7 @@ export const catppuccin: ThemeBuilder = {
appbar: "#94e2d5", appbar: "#94e2d5",
overlay0: "#6c7086", overlay0: "#6c7086",
overlay1: "#9399b2", overlay1: "#9399b2",
link: "#89b4fa",
default: { default: {
background: "#1e1e2e", background: "#1e1e2e",
accent: "#f5c2e7", accent: "#f5c2e7",

View File

@ -37,6 +37,7 @@ type Mode = {
appbar: Property.Color; appbar: Property.Color;
overlay0: Property.Color; overlay0: Property.Color;
overlay1: Property.Color; overlay1: Property.Color;
link: Property.Color;
variant: Variant; variant: Variant;
colors: { colors: {
red: Property.Color; red: Property.Color;
@ -64,13 +65,13 @@ declare module "yoshiki" {
user: Mode & Variant; user: Mode & Variant;
} }
} }
// declare module "yoshiki/native" { declare module "yoshiki/native" {
// export interface Theme extends ThemeSettings, Mode, Variant { export interface Theme extends ThemeSettings, Mode, Variant {
// light: Mode & Variant; light: Mode & Variant;
// dark: Mode & Variant; dark: Mode & Variant;
// user: Mode & Variant; user: Mode & Variant;
// } }
// } }
export type { Theme } from "yoshiki"; export type { Theme } from "yoshiki";
export type ThemeBuilder = ThemeSettings & { export type ThemeBuilder = ThemeSettings & {
@ -158,5 +159,5 @@ export const ContrastArea = ({
}; };
export const alpha = (color: Property.Color, alpha: number) => { export const alpha = (color: Property.Color, alpha: number) => {
return color + (alpha * 255).toString(16); return color + Math.round(alpha * 255).toString(16);
}; };

View File

@ -0,0 +1,23 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
export const Head = ({ title, description }: { title?: string | null; description?: string | null }) => {
return null;
};

View File

@ -0,0 +1,30 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import NextHead from "next/head";
export const Head = ({ title, description }: { title?: string | null; description?: string | null }) => {
return (
<NextHead>
{title && <title>{title + "- Kyoo"}</title>}
{description && <meta name="description" content={description} />}
</NextHead>
);
};

View File

@ -18,7 +18,7 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>. * along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { Movie, QueryIdentifier, Show, getDisplayDate } from "@kyoo/models"; import { Movie, QueryIdentifier, Show, getDisplayDate, Genre, Studio } from "@kyoo/models";
import { import {
Container, Container,
H1, H1,
@ -31,43 +31,40 @@ import {
Link, Link,
IconButton, IconButton,
IconFab, IconFab,
Head,
HR,
H2,
UL,
LI,
A,
ts,
} from "@kyoo/primitives"; } from "@kyoo/primitives";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Platform, StyleSheet, View } from "react-native"; import { StyleSheet, View } from "react-native";
import { em, percent, rem, vh, useYoshiki, Stylable } from "yoshiki/native"; import {
import { Fetch, WithLoading } from "../fetch"; Theme,
sm,
md,
px,
min,
max,
em,
percent,
rem,
vh,
useYoshiki,
Stylable,
} from "yoshiki/native";
import { Fetch } from "../fetch";
import { Navbar } from "../navbar"; import { Navbar } from "../navbar";
// const StudioText = ({
// studio,
// loading = false,
// sx,
// }: {
// studio?: Studio | null;
// loading?: boolean;
// sx?: SxProps;
// }) => {
// const { t } = useTranslation("browse");
// if (!loading && !studio) return null;
// return (
// <Typography sx={sx}>
// {t("show.studio")}:{" "}
// {loading ? (
// <Skeleton width="5rem" sx={{ display: "inline-flex" }} />
// ) : (
// <Link href={`/studio/${studio!.slug}`}>{studio!.name}</Link>
// )}
// </Typography>
// );
// };
const TitleLine = ({ const TitleLine = ({
isLoading, isLoading,
slug, slug,
name, name,
date, date,
poster, poster,
studio,
...props ...props
}: { }: {
isLoading: boolean; isLoading: boolean;
@ -75,6 +72,7 @@ const TitleLine = ({
name?: string; name?: string;
date?: string; date?: string;
poster?: string | null; poster?: string | null;
studio?: Studio | null;
} & Stylable) => { } & Stylable) => {
const { css, theme } = useYoshiki(); const { css, theme } = useYoshiki();
const { t } = useTranslation(); const { t } = useTranslation();
@ -83,11 +81,17 @@ const TitleLine = ({
<Container <Container
{...css( {...css(
{ {
flexDirection: { xs: "column", sm: "row" }, flexDirection: { xs: "column", md: "row" },
alignItems: { xs: "center", sm: "flex-start" },
}, },
props, props,
)} )}
>
<View
{...css({
flexDirection: { xs: "column", sm: "row" },
alignItems: { xs: "center", sm: "flex-start" },
flexGrow: 1,
})}
> >
<Poster <Poster
src={poster} src={poster}
@ -104,18 +108,16 @@ const TitleLine = ({
alignItems: { xs: "center", sm: "flex-start" }, alignItems: { xs: "center", sm: "flex-start" },
paddingLeft: { sm: em(2.5) }, paddingLeft: { sm: em(2.5) },
flexShrink: 1, flexShrink: 1,
flexGrow: 1,
})} })}
> >
<Skeleton {...css({ width: rem(15), height: rem(3), marginBottom: rem(0.5) })}> <Skeleton {...css({ width: rem(15), height: rem(3) })}>
{isLoading || ( {isLoading || (
<H1 <H1
{...css({ {...css({
fontWeight: { md: "900" }, fontWeight: { md: "900" },
fontSize: rem(3), textAlign: { xs: "center", sm: "left" },
marginTop: 0, color: (theme: Theme) => ({ xs: theme.user.heading, md: theme.heading }),
marginBottom: rem(0.5),
textAlign: { xs: "center", sm: "flex-start" },
color: (theme) => ({ xs: theme.user.heading, md: theme.heading }),
})} })}
> >
{name} {name}
@ -127,7 +129,6 @@ const TitleLine = ({
{...css({ {...css({
width: rem(5), width: rem(5),
height: rem(1.5), height: rem(1.5),
marginBottom: rem(0.5),
})} })}
> >
{isLoading || ( {isLoading || (
@ -136,10 +137,8 @@ const TitleLine = ({
fontWeight: "300", fontWeight: "300",
fontSize: rem(1.5), fontSize: rem(1.5),
letterSpacing: 0, letterSpacing: 0,
marginTop: 0, textAlign: { xs: "center", sm: "left" },
marginBottom: rem(0.5), color: (theme: Theme) => ({ xs: theme.user.heading, md: theme.heading }),
textAlign: { xs: "center", sm: "flex-start" },
color: (theme) => ({ xs: theme.user.heading, md: theme.heading }),
})} })}
> >
{date} {date}
@ -147,7 +146,7 @@ const TitleLine = ({
)} )}
</Skeleton> </Skeleton>
)} )}
<View {...css({ flexDirection: "row" })} /*sx={{ "& > *": { m: ".3rem !important" } }} */> <View {...css({ flexDirection: "row" })}>
<IconFab <IconFab
icon="play-arrow" icon="play-arrow"
as={Link} as={Link}
@ -163,82 +162,116 @@ const TitleLine = ({
/> />
</View> </View>
</View> </View>
{/* <View */} </View>
{/* {...css({ */} <View
{/* display: { xs: "none", md: "flex" }, */} {...css([
{/* flexDirection: "column", */} {
{/* alignSelf: "flex-end", */} paddingTop: { xs: ts(3), sm: ts(8) },
{/* paddingRight: px(15), */} alignSelf: { xs: "flex-start", md: "flex-end" },
{/* })} */} justifyContent: "flex-end",
{/* > */} flexDirection: "column",
{/* {(isLoading || logo || true) && ( */} },
{/* <Image */} md({
{/* src={logo} */} position: "absolute",
{/* alt="" */} top: 0,
{/* layout={{ */} bottom: 0,
{/* width: "100%", */} right: 0,
{/* height: px(100), */} width: percent(25),
{/* }} */} height: percent(100),
{/* // sx={{ display: { xs: "none", lg: "unset" } }} */} paddingRight: ts(3),
{/* /> */} }),
{/* )} */} ])}
{/* {/1* <StudioText loading={!data} studio={data?.studio} sx={{ mt: "auto", mb: 3 }} /> *1/} */} >
{/* </View> */} <P
{...css({
color: (theme) => theme.user.paragraph,
})}
>
{t("show.studio")}:{" "}
{isLoading ? (
<Skeleton />
) : (
<A href={`/studio/${studio!.slug}`} {...css({ color: (theme) => theme.user.link })}>
{studio!.name}
</A>
)}
</P>
</View>
</Container> </Container>
); );
}; };
// const Tata = () => { const Description = ({
// return ( isLoading,
// <Container sx={{ pt: 2 }}> overview,
// <Typography align="justify" sx={{ flexBasis: 0, flexGrow: 1, pt: { sm: 2 } }}> genres,
// {data ...props
// ? data.overview ?? t("show.noOverview") }: {
// : [...Array(4)].map((_, i) => <Skeleton key={i} />)} isLoading: boolean;
// </Typography> overview?: string | null;
// <Divider genres?: Genre[];
// orientation="vertical" } & Stylable) => {
// variant="middle" const { t } = useTranslation();
// flexItem const { css } = useYoshiki();
// sx={{ mx: 2, display: { xs: "none", sm: "block" } }}
// />
// <Box sx={{ flexBasis: "25%", display: { xs: "none", sm: "block" } }}>
// <StudioText
// loading={!data}
// studio={data?.studio}
// sx={{ display: { xs: "none", sm: "block", md: "none" }, pb: 2 }}
// />
// <Typography variant="h4" component="h2"> return (
// {t("show.genre")} <Container {...css({ flexDirection: { xs: "column", sm: "row" } }, props)}>
// </Typography> <P
// {!data || data.genres?.length ? ( {...css({
// <ul> display: { xs: "flex", sm: "none" },
// {(data ? data.genres! : [...Array(3)]).map((genre, i) => ( color: (theme: Theme) => theme.user.paragraph,
// <li key={genre?.id ?? i}> })}
// <Typography> >
// {genre ? <Link href={`/genres/${genre.slug}`}>{genre.name}</Link> : <Skeleton />} {t("show.genre")}:{" "}
// </Typography> {(isLoading ? [...Array(3)] : genres!).map((genre, i) => (
// </li> <>
// ))} {i !== 0 && ", "}
// </ul> {isLoading ? (
// ) : ( <Skeleton key={i} />
// <Typography>{t("show.genre-none")}</Typography> ) : (
// )} <A key={genre.slug} href={`/genres/${genre.slug}`}>
// </Box> {genre.name}
// </Container> </A>
// ); )}
// }; </>
))}
</P>
const min = Platform.OS === "web" <Skeleton
? (...values: number[]): number => `min(${values.join(", ")})` as unknown as number lines={4}
: (...values: number[]): number => Math.min(...values); {...css({ width: percent(100), flexBasis: 0, flexGrow: 1, paddingTop: ts(4) })}
const max = Platform.OS === "web" >
? (...values: number[]): number => `max(${values.join(", ")})` as unknown as number {isLoading || (
: (...values: number[]): number => Math.max(...values); <P {...css({ flexBasis: 0, flexGrow: 1, textAlign: "justify", paddingTop: ts(4) })}>
const px = Platform.OS === "web" {overview ?? t("show.noOverview")}
? (value: number): number => `${value}px` as unknown as number </P>
: (value: number): number => value; )}
</Skeleton>
<HR
orientation="vertical"
{...css({ marginX: ts(2), display: { xs: "none", sm: "flex" } })}
/>
<View {...css({ flexBasis: percent(25), display: { xs: "none", sm: "flex" } })}>
<H2>{t("show.genre")}</H2>
{isLoading || genres?.length ? (
<UL>
{(isLoading ? [...Array(3)] : genres!).map((genre, i) => (
<LI key={genre?.id ?? i}>
{isLoading ? (
<Skeleton {...css({ marginBottom: 0 })} />
) : (
<A href={`/genres/${genre.slug}`}>{genre.name}</A>
)}
</LI>
))}
</UL>
) : (
<P>{t("show.genre-none")}</P>
)}
</View>
</Container>
);
};
export const ShowHeader = ({ export const ShowHeader = ({
query, query,
@ -256,19 +289,22 @@ export const ShowHeader = ({
<Navbar {...css({ bg: "transparent" })} /> <Navbar {...css({ bg: "transparent" })} />
<Fetch query={query}> <Fetch query={query}>
{({ isLoading, ...data }) => ( {({ isLoading, ...data }) => (
<> <Main {...css(StyleSheet.absoluteFillObject)}>
{/* TODO: HEAD element for SEO*/} <Head title={data?.name} description={data?.overview} />
{/* TODO: Add a shadow on navbar items */} {/* TODO: Add a shadow on navbar items */}
{/* TODO: Put the navbar outside of the scrollbox */} {/* TODO: Put the navbar outside of the scrollbox */}
<ImageBackground <ImageBackground
src={data?.thumbnail} src={data?.thumbnail}
alt="" alt=""
as={Main}
containerStyle={{ containerStyle={{
height: { xs: vh(40), sm: min(vh(60), px(750)), lg: vh(70) }, height: {
minHeight: { xs: px(350), sm: px(500), lg: px(600) }, xs: vh(40),
sm: min(vh(60), px(750)),
md: min(vh(60), px(680)),
lg: vh(70),
},
minHeight: { xs: px(350), sm: px(300), md: px(400), lg: px(600) },
}} }}
{...css(StyleSheet.absoluteFillObject)}
> >
<TitleLine <TitleLine
isLoading={isLoading} isLoading={isLoading}
@ -276,31 +312,24 @@ export const ShowHeader = ({
name={data?.name} name={data?.name}
date={data ? getDisplayDate(data as any) : undefined} date={data ? getDisplayDate(data as any) : undefined}
poster={data?.poster} poster={data?.poster}
studio={data?.studio}
{...css({ {...css({
marginTop: { xs: max(vh(20), px(200)), sm: vh(45), md: vh(35) } marginTop: {
xs: max(vh(20), px(200)),
sm: vh(45),
md: max(vh(30), px(150)),
lg: max(vh(35), px(200)),
},
})} })}
/> />
{/* <Container sx={{ display: { xs: "block", sm: "none" }, pt: 3 }}> */}
{/* <StudioText loading={!data} studio={data?.studio} sx={{ mb: 1 }} /> */}
{/* <Typography sx={{ mb: 1 }}> */}
{/* {t("show.genre")} */}
{/* {": "} */}
{/* {!data ? ( */}
{/* <Skeleton width="10rem" sx={{ display: "inline-flex" }} /> */}
{/* ) : data?.genres && data.genres.length ? ( */}
{/* data.genres.map((genre, i) => [ */}
{/* i > 0 && ", ", */}
{/* <Link key={genre.id} href={`/genres/${genre.slug}`}> */}
{/* {genre.name} */}
{/* </Link>, */}
{/* ]) */}
{/* ) : ( */}
{/* t("show.genre-none") */}
{/* )} */}
{/* </Typography> */}
{/* </Container> */}
</ImageBackground> </ImageBackground>
</> <Description
isLoading={isLoading}
overview={data?.overview}
genres={data?.genres}
{...css({ paddingTop: { xs: 0, md: ts(2) } })}
/>
</Main>
)} )}
</Fetch> </Fetch>
</> </>

View File

@ -9682,7 +9682,7 @@ __metadata:
react-native-screens: ~3.18.0 react-native-screens: ~3.18.0
react-native-svg: 13.4.0 react-native-svg: 13.4.0
typescript: ^4.6.3 typescript: ^4.6.3
yoshiki: 0.2.11 yoshiki: 0.3.1
languageName: unknown languageName: unknown
linkType: soft linkType: soft
@ -13319,7 +13319,7 @@ __metadata:
superjson: ^1.11.0 superjson: ^1.11.0
typescript: ^4.9.3 typescript: ^4.9.3
webpack: ^5.75.0 webpack: ^5.75.0
yoshiki: 0.2.11 yoshiki: 0.3.1
zod: ^3.19.1 zod: ^3.19.1
languageName: unknown languageName: unknown
linkType: soft linkType: soft
@ -13644,9 +13644,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"yoshiki@npm:0.2.11": "yoshiki@npm:0.3.1":
version: 0.2.11 version: 0.3.1
resolution: "yoshiki@npm:0.2.11" resolution: "yoshiki@npm:0.3.1"
dependencies: dependencies:
"@types/node": 18.x.x "@types/node": 18.x.x
"@types/react": 18.x.x "@types/react": 18.x.x
@ -13661,7 +13661,7 @@ __metadata:
optional: true optional: true
react-native-web: react-native-web:
optional: true optional: true
checksum: 5a2bbb62b2270d3456f114cfbb24a84ad6b8a94b147687929ccffe2d179560ef40b46df1d4054eda91310d295a9a674bbb201765deb86dc96a2133bfd702235a checksum: 9448b628b61bbcc4485af7aed667a1c0f8490a2066fa35953b4a02126f1d31d94f90e27a592797f8ecedc0ce2220976a7651ba989f4ff3c68513496b2f9fdd0b
languageName: node languageName: node
linkType: hard linkType: hard