mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Rework chip to support links and skeletons
This commit is contained in:
parent
0272b82166
commit
9304c7ad2f
@ -28,7 +28,7 @@ export const Button = ({
|
||||
text,
|
||||
...props
|
||||
}: { text: string } & ComponentProps<typeof PressableFeedback>) => {
|
||||
const { css } = useYoshiki();
|
||||
const { css } = useYoshiki("button");
|
||||
|
||||
return (
|
||||
<PressableFeedback
|
||||
|
@ -18,54 +18,88 @@
|
||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { px, rem, Stylable, Theme, useYoshiki } from "yoshiki/native";
|
||||
import { px, rem, Theme, useYoshiki } from "yoshiki/native";
|
||||
import { Link } from "./links";
|
||||
import { P } from "./text";
|
||||
import { ts } from "./utils";
|
||||
import { A } from "./links";
|
||||
import { ComponentType } from "react";
|
||||
import { capitalize, ts } from "./utils";
|
||||
import { EnhancedStyle } from "yoshiki/src/native/type";
|
||||
import { TextProps, TextStyle, ViewStyle } from "react-native";
|
||||
import { Skeleton } from "./skeleton";
|
||||
|
||||
export const Chip = <AsProps = { label: string },>({
|
||||
export const Chip = ({
|
||||
color,
|
||||
size = "medium",
|
||||
outline = false,
|
||||
as,
|
||||
label,
|
||||
href,
|
||||
replace,
|
||||
target,
|
||||
textProps,
|
||||
...props
|
||||
}: {
|
||||
color?: string;
|
||||
size?: "small" | "medium" | "large";
|
||||
outline?: boolean;
|
||||
as?: ComponentType<AsProps>;
|
||||
} & AsProps) => {
|
||||
const { css } = useYoshiki();
|
||||
label?: string;
|
||||
href?: string;
|
||||
replace?: boolean;
|
||||
target?: string;
|
||||
textProps?: TextProps;
|
||||
}) => {
|
||||
const { css } = useYoshiki("chip");
|
||||
|
||||
textProps ??= {};
|
||||
|
||||
const sizeMult = size == "medium" ? 1 : size == "small" ? 0.5 : 1.5;
|
||||
|
||||
const As = as ?? (P as any);
|
||||
// @ts-ignore backward compatibilty
|
||||
if (!as && props.label) props.children = props.label;
|
||||
|
||||
return (
|
||||
<As
|
||||
<Link
|
||||
href={href}
|
||||
replace={replace}
|
||||
target={target}
|
||||
{...css(
|
||||
[
|
||||
{
|
||||
pY: ts(1 * sizeMult),
|
||||
pX: ts(2.5 * sizeMult),
|
||||
borderRadius: ts(3),
|
||||
fontSize: rem(0.8),
|
||||
},
|
||||
!outline && {
|
||||
color: (theme: Theme) => theme.alternate.contrast,
|
||||
bg: color ?? ((theme: Theme) => theme.accent),
|
||||
overflow: "hidden",
|
||||
},
|
||||
outline && {
|
||||
borderColor: color ?? ((theme: Theme) => theme.accent),
|
||||
borderStyle: "solid",
|
||||
borderWidth: px(1),
|
||||
fover: {
|
||||
self: {
|
||||
bg: (theme: Theme) => theme.accent,
|
||||
},
|
||||
text: {
|
||||
color: (theme: Theme) => theme.alternate.contrast,
|
||||
},
|
||||
},
|
||||
},
|
||||
!outline && {
|
||||
bg: color ?? ((theme: Theme) => theme.accent),
|
||||
},
|
||||
],
|
||||
props,
|
||||
)}
|
||||
/>
|
||||
>
|
||||
<P
|
||||
{...css(
|
||||
[
|
||||
"text",
|
||||
{
|
||||
marginVertical: 0,
|
||||
fontSize: rem(0.8),
|
||||
color: (theme: Theme) => (outline ? theme.contrast : theme.alternate.contrast),
|
||||
},
|
||||
],
|
||||
textProps,
|
||||
)}
|
||||
>
|
||||
{label ? capitalize(label) : <Skeleton {...css({ width: rem(3) })} />}
|
||||
</P>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
import { forwardRef, ReactNode } from "react";
|
||||
import { Platform, Pressable, TextProps, View, PressableProps } from "react-native";
|
||||
import { Platform, Pressable, TextProps, View, PressableProps, Linking } from "react-native";
|
||||
import { TextLink, useLink } from "solito/link";
|
||||
import { useTheme, useYoshiki } from "yoshiki/native";
|
||||
import { alpha } from "./themes";
|
||||
@ -107,7 +107,16 @@ export const Link = ({
|
||||
// @ts-ignore Missing hrefAttrs type definition.
|
||||
linkProps.hrefAttrs = { ...linkProps.hrefAttrs, target };
|
||||
return (
|
||||
<PressableFeedback {...linkProps} {...props}>
|
||||
<PressableFeedback
|
||||
{...linkProps}
|
||||
{...props}
|
||||
onPress={(e?: any) => {
|
||||
props?.onPress?.(e);
|
||||
if (e?.defaultPrevented) return;
|
||||
if (Platform.OS !== "web" && href?.includes("://")) Linking.openURL(href);
|
||||
else linkProps.onPress(e);
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</PressableFeedback>
|
||||
);
|
||||
|
@ -30,7 +30,7 @@ export const Rating = ({ rating, color }: { rating?: number; color: Breakpoint<s
|
||||
<View {...css({ flexDirection: "row", alignItems: "center" })}>
|
||||
<Icon icon={Star} color={color} {...css({ marginRight: ts(0.5) })} />
|
||||
<Skeleton {...css({ width: rem(2) })}>
|
||||
{rating !== undefined && <P {...css({ color })}>{rating ? rating / 10 : "??"} / 10</P>}
|
||||
{rating !== undefined && <P {...css({ color, verticalAlign: "middle" })}>{rating ? rating / 10 : "??"} / 10</P>}
|
||||
</Skeleton>
|
||||
</View>
|
||||
);
|
||||
|
@ -172,7 +172,7 @@ export const EpisodeLine = ({
|
||||
watchedStatus: WatchStatusV | null;
|
||||
}> &
|
||||
Stylable) => {
|
||||
const { css } = useYoshiki();
|
||||
const { css } = useYoshiki("episode-line");
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
|
@ -52,7 +52,7 @@ import {
|
||||
} from "@kyoo/primitives";
|
||||
import { Fragment } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ImageStyle, Platform, View } from "react-native";
|
||||
import { ImageStyle, Platform, Text, View } from "react-native";
|
||||
import {
|
||||
Theme,
|
||||
md,
|
||||
@ -458,28 +458,17 @@ export const Header = ({
|
||||
<P {...css({ marginRight: ts(0.5), textAlign: "center" })}>{t("show.links")}:</P>
|
||||
{(!isLoading
|
||||
? Object.entries(data.externalId!).filter(([_, data]) => data.link)
|
||||
: [...Array(3)].map((_, i) => [i, undefined] as const)
|
||||
).map(([name, data]) => (
|
||||
: [...Array(3)].map((_) => [undefined, undefined] as const)
|
||||
).map(([name, data], i) => (
|
||||
<Chip
|
||||
key={name}
|
||||
as={A}
|
||||
href={data?.link}
|
||||
key={name ?? i}
|
||||
label={name}
|
||||
href={data?.link || undefined}
|
||||
target="_blank"
|
||||
size="small"
|
||||
outline
|
||||
{...(css({
|
||||
m: ts(0.5),
|
||||
color: (theme: Theme) => theme.contrast,
|
||||
fover: {
|
||||
self: {
|
||||
color: (theme: Theme) => theme.alternate.contrast,
|
||||
bg: (theme: Theme) => theme.accent,
|
||||
},
|
||||
},
|
||||
}) as any)}
|
||||
>
|
||||
{data ? capitalize(name) : <Skeleton {...css({ width: rem(3) })} />}
|
||||
</Chip>
|
||||
{...css({ m: ts(0.5) })}
|
||||
/>
|
||||
))}
|
||||
</Container>
|
||||
{type === "show" && (data.watchStatus as ShowWatchStatus)?.nextEpisode && (
|
||||
|
@ -166,9 +166,7 @@ export const ItemDetails = ({
|
||||
{(isLoading || genres) && (
|
||||
<ScrollView horizontal {...css({ alignItems: "center" })}>
|
||||
{(genres || [...Array(3)])?.map((x, i) => (
|
||||
<Chip key={x ?? i} size="small" {...css({ mX: ts(0.5) })}>
|
||||
{x ?? <Skeleton {...css({ width: rem(3), height: rem(0.8) })} />}
|
||||
</Chip>
|
||||
<Chip key={x ?? i} label={x} size="small" {...css({ mX: ts(0.5) })} />
|
||||
))}
|
||||
</ScrollView>
|
||||
)}
|
||||
|
Loading…
x
Reference in New Issue
Block a user