mirror of
https://github.com/movie-web/movie-web.git
synced 2024-12-27 09:31:50 +01:00
Add full layout and styling for the first step in onboarding
Co-authored-by: Jip Frijlink <JipFr@users.noreply.github.com>
This commit is contained in:
parent
3b2be31691
commit
dc95bd7455
@ -12,9 +12,9 @@ export function Stepper(props: StepperProps) {
|
|||||||
<p className="mb-2">
|
<p className="mb-2">
|
||||||
{props.current}/{props.steps}
|
{props.current}/{props.steps}
|
||||||
</p>
|
</p>
|
||||||
<div className="max-w-full h-1 w-32 bg-white rounded-full overflow-hidden">
|
<div className="max-w-full h-1 w-32 bg-onboarding-bar rounded-full overflow-hidden">
|
||||||
<div
|
<div
|
||||||
className="h-full bg-blue-500 transition-[width] rounded-full"
|
className="h-full bg-onboarding-barFilled transition-[width] rounded-full"
|
||||||
style={{
|
style={{
|
||||||
width: `${percentage.toFixed(0)}%`,
|
width: `${percentage.toFixed(0)}%`,
|
||||||
}}
|
}}
|
||||||
|
@ -26,7 +26,7 @@ export function CenterContainer(props: ThinContainerProps) {
|
|||||||
props.classNames,
|
props.classNames,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="w-[600px] max-w-full">{props.children}</div>
|
<div className="w-[700px] max-w-full">{props.children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,24 @@
|
|||||||
|
import classNames from "classnames";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { Button } from "@/components/buttons/Button";
|
import { Button } from "@/components/buttons/Button";
|
||||||
import { Stepper } from "@/components/layout/Stepper";
|
import { Stepper } from "@/components/layout/Stepper";
|
||||||
import { CenterContainer } from "@/components/layout/ThinContainer";
|
import { CenterContainer } from "@/components/layout/ThinContainer";
|
||||||
import { Modal, ModalCard, useModal } from "@/components/overlays/Modal";
|
import { Modal, ModalCard, useModal } from "@/components/overlays/Modal";
|
||||||
import { Heading2, Paragraph } from "@/components/utils/Text";
|
import { Heading1, Heading2, Paragraph } from "@/components/utils/Text";
|
||||||
import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout";
|
import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout";
|
||||||
import { useRedirectBack } from "@/pages/onboarding/onboardingHooks";
|
import { useRedirectBack } from "@/pages/onboarding/onboardingHooks";
|
||||||
|
import { Card, CardContent, Link } from "@/pages/onboarding/utils";
|
||||||
import { PageTitle } from "@/pages/parts/util/PageTitle";
|
import { PageTitle } from "@/pages/parts/util/PageTitle";
|
||||||
|
|
||||||
|
function VerticalLine(props: { className?: string }) {
|
||||||
|
return (
|
||||||
|
<div className={classNames("w-full grid justify-center", props.className)}>
|
||||||
|
<div className="w-px h-10 bg-onboarding-divider" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function OnboardingPage() {
|
export function OnboardingPage() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const skipModal = useModal("skip");
|
const skipModal = useModal("skip");
|
||||||
@ -20,7 +30,7 @@ export function OnboardingPage() {
|
|||||||
<Modal id={skipModal.id}>
|
<Modal id={skipModal.id}>
|
||||||
<ModalCard>
|
<ModalCard>
|
||||||
<ModalCard>
|
<ModalCard>
|
||||||
<Heading2 className="!mt-0">Lorem ipsum</Heading2>
|
<Heading1 className="!mt-0">Lorem ipsum</Heading1>
|
||||||
<Paragraph>Lorem ipsum Lorem ipsum Lorem ipsum</Paragraph>
|
<Paragraph>Lorem ipsum Lorem ipsum Lorem ipsum</Paragraph>
|
||||||
<Button theme="secondary" onClick={skipModal.hide}>
|
<Button theme="secondary" onClick={skipModal.hide}>
|
||||||
Lorem ipsum
|
Lorem ipsum
|
||||||
@ -33,15 +43,60 @@ export function OnboardingPage() {
|
|||||||
</Modal>
|
</Modal>
|
||||||
<CenterContainer>
|
<CenterContainer>
|
||||||
<Stepper steps={2} current={1} className="mb-12" />
|
<Stepper steps={2} current={1} className="mb-12" />
|
||||||
<Heading2 className="!mt-0">Lorem ipsum</Heading2>
|
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
|
||||||
<Paragraph>Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum</Paragraph>
|
Let's get you set up with movie-web
|
||||||
<Button onClick={() => navigate("/onboarding/proxy")}>
|
</Heading2>
|
||||||
|
<Paragraph className="max-w-[320px]">
|
||||||
|
To get the best streams possible, you will need to choose which
|
||||||
|
streaming method you want to use.
|
||||||
|
</Paragraph>
|
||||||
|
|
||||||
|
<div className="w-full grid grid-cols-[1fr,auto,1fr] gap-3">
|
||||||
|
<Card onClick={() => navigate("/onboarding/proxy")}>
|
||||||
|
<CardContent
|
||||||
|
colorClass="!text-onboarding-good"
|
||||||
|
title="Custom proxy"
|
||||||
|
subtitle="Good quality"
|
||||||
|
description="Set up a proxy in only 5 minutes and gain access to great sources."
|
||||||
|
>
|
||||||
|
<Link>Set up proxy</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
<div className="grid grid-rows-[1fr,auto,1fr] justify-center gap-4">
|
||||||
|
<VerticalLine className="items-end" />
|
||||||
|
<span className="text-xs uppercase font-bold">or</span>
|
||||||
|
<VerticalLine />
|
||||||
|
</div>
|
||||||
|
<Card onClick={() => navigate("/onboarding/extension")}>
|
||||||
|
<CardContent
|
||||||
|
colorClass="!text-onboarding-best"
|
||||||
|
title="Browser extension — best quality"
|
||||||
|
subtitle="Best quality"
|
||||||
|
description="Install browser extension and gain access to the best sources."
|
||||||
|
>
|
||||||
|
<Link>Install extension</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-center mt-12">
|
||||||
|
I don't want good quality, <br />
|
||||||
|
<a
|
||||||
|
onClick={skipModal.show}
|
||||||
|
type="button"
|
||||||
|
className="text-onboarding-link cursor-pointer"
|
||||||
|
>
|
||||||
|
use the default setup
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* <Button onClick={() => navigate("/onboarding/proxy")}>
|
||||||
Custom proxy
|
Custom proxy
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => navigate("/onboarding/extension")}>
|
<Button onClick={() => navigate("/onboarding/extension")}>
|
||||||
Extension
|
Extension
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={skipModal.show}>Default</Button>
|
<Button onClick={skipModal.show}>Default</Button> */}
|
||||||
</CenterContainer>
|
</CenterContainer>
|
||||||
</MinimalPageLayout>
|
</MinimalPageLayout>
|
||||||
);
|
);
|
||||||
|
59
src/pages/onboarding/utils.tsx
Normal file
59
src/pages/onboarding/utils.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import classNames from "classnames";
|
||||||
|
|
||||||
|
import { Icon, Icons } from "@/components/Icon";
|
||||||
|
import { Heading2, Heading3, Paragraph } from "@/components/utils/Text";
|
||||||
|
|
||||||
|
export function Card(props: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
onClick: () => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="bg-onboarding-card hover:bg-onboarding-cardHover transition-colors duration-300 border border-onboarding-border rounded-lg p-7 cursor-pointer "
|
||||||
|
onClick={props.onClick}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CardContent(props: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
subtitle: string;
|
||||||
|
colorClass: string;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="grid grid-rows-[1fr,auto] h-full">
|
||||||
|
<div>
|
||||||
|
<Icon
|
||||||
|
icon={Icons.RISING_STAR}
|
||||||
|
className={classNames("text-4xl mb-8 block", props.colorClass)}
|
||||||
|
/>
|
||||||
|
<Heading3
|
||||||
|
className={classNames(
|
||||||
|
"!mt-0 !mb-0 !text-xs uppercase",
|
||||||
|
props.colorClass,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{props.subtitle}
|
||||||
|
</Heading3>
|
||||||
|
<Heading2 className="!mb-0 !mt-1 !text-base">{props.title}</Heading2>
|
||||||
|
<Paragraph className="max-w-[320px] !my-4">
|
||||||
|
{props.description}
|
||||||
|
</Paragraph>
|
||||||
|
</div>
|
||||||
|
<div>{props.children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Link(props: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<a className="text-onboarding-link cursor-pointer flex gap-2 items-center">
|
||||||
|
{props.children}
|
||||||
|
<Icon icon={Icons.ARROW_RIGHT} />
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
@ -228,10 +228,24 @@ export const defaultTheme = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Utilities
|
||||||
utils: {
|
utils: {
|
||||||
divider: tokens.ash.c300,
|
divider: tokens.ash.c300,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Onboarding
|
||||||
|
onboarding: {
|
||||||
|
bar: tokens.shade.c400,
|
||||||
|
barFilled: tokens.purple.c300,
|
||||||
|
divider: tokens.shade.c200,
|
||||||
|
card: tokens.shade.c800,
|
||||||
|
cardHover: tokens.shade.c700,
|
||||||
|
border: tokens.shade.c600,
|
||||||
|
good: tokens.purple.c100,
|
||||||
|
best: tokens.semantic.yellow.c100,
|
||||||
|
link: tokens.purple.c100,
|
||||||
|
},
|
||||||
|
|
||||||
// Error page
|
// Error page
|
||||||
errors: {
|
errors: {
|
||||||
card: tokens.shade.c800,
|
card: tokens.shade.c800,
|
||||||
|
Loading…
Reference in New Issue
Block a user