Skip to content

Commit

Permalink
feat: add mobile layouts
Browse files Browse the repository at this point in the history
  • Loading branch information
tomwisecodes committed Aug 29, 2024
1 parent 6b0839c commit b4d4eb2
Show file tree
Hide file tree
Showing 16 changed files with 279 additions and 60 deletions.
6 changes: 1 addition & 5 deletions apps/nextjs/src/app/aila/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { auth } from "@clerk/nextjs/server";
import { redirect } from "next/navigation";

import { ChatStart } from "@/components/AppComponents/Chat/chat-start";
import { MobileSupportBlocker } from "@/components/AppComponents/Chat/mobile-support-blocker";
import Layout from "@/components/AppComponents/Layout";
import { serverSideFeatureFlag } from "@/utils/serverSideFeatureFlag";

Expand All @@ -26,10 +25,7 @@ export default async function IndexPage() {
<SignedIn>
{userCanViewFeature && (
<Layout featureFlag={userCanViewFeature}>
<div className="hidden md:block">
<ChatStart />
</div>
<MobileSupportBlocker />
<ChatStart />
</Layout>
)}
</SignedIn>
Expand Down
4 changes: 4 additions & 0 deletions apps/nextjs/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,12 @@ export default function RootLayout({ children }: Readonly<RootLayoutProps>) {
<CookieConsentProvider>
<AnalyticsProvider
avoOptions={{
webDebugger: false,
inspector: undefined,
webDebuggerOptions: {
position: WebDebuggerPosition.BottomLeft({
// stop this from being displayed at all

bottom: 0,
left: 0,
}),
Expand Down
22 changes: 22 additions & 0 deletions apps/nextjs/src/components/AiIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const AiIcon = () => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.2404 3C10.4641 3 10.6332 3.13202 10.6932 3.37407C10.7915 3.77565 10.8788 4.17722 10.9824 4.5788C11.1843 5.35995 11.4244 6.13009 11.7845 6.85623C12.2537 7.79141 12.963 8.47353 13.9342 8.88061C14.9054 9.28769 15.9094 9.56274 16.9297 9.78828C17.017 9.80479 17.0988 9.82679 17.1807 9.8543C17.3662 9.92031 17.4862 10.0853 17.4917 10.2889C17.4971 10.4704 17.388 10.6519 17.2079 10.718C16.9515 10.8115 16.6787 10.8445 16.4168 10.9105C15.4074 11.158 14.4089 11.4386 13.4868 11.9392C12.7557 12.3353 12.2101 12.9129 11.8281 13.6555C11.3644 14.5577 11.1025 15.5259 10.8678 16.5051C10.8133 16.7416 10.7587 16.9781 10.6987 17.2147C10.6332 17.4622 10.4641 17.6053 10.2404 17.6053C10.0221 17.6053 9.84753 17.4567 9.78751 17.2037C9.62928 16.4996 9.47105 15.8009 9.2528 15.1133C9.08912 14.6017 8.89815 14.1011 8.64717 13.628C8.15065 12.6818 7.38133 12.0602 6.41558 11.6531C5.46075 11.2461 4.46226 11.004 3.45832 10.7675C3.41467 10.7565 3.36557 10.7455 3.32192 10.729C3.13095 10.674 3 10.4979 3 10.3109C3 10.1238 3.12004 9.93131 3.311 9.8763C3.5729 9.79929 3.84025 9.74428 4.10215 9.67826C5.05699 9.44172 5.99545 9.16116 6.88481 8.72108C7.71416 8.3085 8.31434 7.67038 8.72355 6.84523C9.06729 6.1466 9.291 5.39845 9.48196 4.63931C9.58563 4.23223 9.6893 3.82516 9.7766 3.41258C9.84207 3.13202 9.99485 3 10.2404 3ZM10.2567 15.2233C10.2677 15.1903 10.2786 15.1683 10.284 15.1463C10.4477 14.5027 10.6987 13.8976 10.9824 13.2979C11.3753 12.4728 11.9482 11.8237 12.712 11.3341C13.3559 10.9215 14.0597 10.6464 14.7854 10.4209C14.8945 10.3879 15.0036 10.3494 15.1455 10.3054C15.0746 10.2779 15.0418 10.2669 15.0036 10.2559C14.5235 10.1128 14.0488 9.94781 13.5905 9.74978C12.6793 9.3592 11.9045 8.78159 11.3425 7.94544C10.9715 7.39533 10.726 6.78472 10.5077 6.1631C10.4204 5.91555 10.344 5.6625 10.2567 5.40946C10.2131 5.43696 10.2076 5.48097 10.1967 5.51398C10.044 6.02557 9.8639 6.52617 9.65656 7.01576C9.1655 8.17098 8.35799 9.02914 7.23947 9.57924C6.67748 9.8543 6.09912 10.0798 5.49894 10.2559C5.4662 10.2669 5.4171 10.2614 5.40073 10.3109C6.02819 10.5089 6.6502 10.7345 7.23947 11.0315C8.07427 11.4496 8.77266 12.0272 9.2528 12.8414C9.62928 13.485 9.92937 14.1616 10.1313 14.8822C10.164 14.9978 10.1913 15.1078 10.2567 15.2233Z"
fill="#222222"
/>
<path
d="M12.6029 17.2752C12.6029 17.0387 12.7448 16.8681 13.0121 16.8076C13.3286 16.7306 13.6396 16.6591 13.9506 16.5656C14.2452 16.4775 14.5235 16.3675 14.8018 16.241C15.331 15.9935 15.6529 15.5534 15.8766 15.0363C16.0949 14.5412 16.204 14.0186 16.324 13.496C16.324 13.4795 16.3295 13.463 16.335 13.4465C16.4004 13.1879 16.5641 13.0339 16.7769 13.0339C17.0061 13.0339 17.1861 13.1824 17.2516 13.441C17.3607 13.8866 17.4535 14.3321 17.6062 14.7612C17.7099 15.0528 17.8518 15.3278 18.0209 15.5864C18.321 16.032 18.7684 16.2685 19.2595 16.4445C19.6687 16.5931 20.0943 16.6756 20.5144 16.7801C20.569 16.7911 20.6235 16.8076 20.6726 16.8241C20.8691 16.8956 20.9891 17.0552 20.9945 17.2532C20.9945 17.4402 20.88 17.6328 20.689 17.6933C20.4216 17.7758 20.1488 17.8363 19.876 17.9078C19.5214 18.0068 19.1722 18.1169 18.8393 18.2709C18.2992 18.5184 17.9445 18.9365 17.7263 19.4811C17.5353 19.9707 17.4044 20.4768 17.2789 20.9884C17.2625 21.0489 17.2461 21.1094 17.2298 21.1699C17.1643 21.368 17.0061 21.489 16.8042 21.4945C16.6187 21.5 16.4495 21.39 16.3731 21.1974C16.3022 21.0159 16.2749 20.8179 16.2313 20.6308C16.144 20.2953 16.0567 19.9597 15.9366 19.6351C15.6529 18.8595 15.1182 18.3479 14.3434 18.0894C13.9069 17.9408 13.465 17.8308 13.0176 17.7263C12.7448 17.6658 12.5975 17.4952 12.5975 17.2697L12.6029 17.2752ZM14.769 17.2642C15.7457 17.6383 16.4495 18.2819 16.7987 19.2996C17.1534 18.2874 17.8299 17.6163 18.8284 17.2697C18.3483 17.0882 17.9172 16.8626 17.5681 16.4996C17.2189 16.1365 16.9952 15.6964 16.7878 15.1958C16.4604 16.2575 15.7675 16.9121 14.769 17.2697V17.2642Z"
fill="#222222"
/>
</svg>
);
};

export default AiIcon;
2 changes: 0 additions & 2 deletions apps/nextjs/src/components/AppComponents/Chat/Chat/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import DialogContents from "@/components/DialogControl/DialogContents";
import { DialogRoot } from "@/components/DialogControl/DialogRoot";

import { DesktopChatLayout } from "../desktop-layout";
import { MobileSupportBlocker } from "../mobile-support-blocker";
import ChatModeration from "./ChatModeration";
import ChatUserAccessCheck from "./ChatUserAccessCheck";

Expand Down Expand Up @@ -34,7 +33,6 @@ export function Chat({
isShared={isShared}
/>
<DesktopChatLayout className={className} />
<MobileSupportBlocker />
</DialogRoot>
</ChatModeration>
</ChatUserAccessCheck>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function basedOnTitle(basedOn: string | BasedOnOptional) {
}

const displayStyles = cva(
"relative flex flex-col space-y-10 px-24 pb-28 pt-29 opacity-100",
"relative flex flex-col space-y-10 px-14 pb-28 opacity-100 sm:px-24 sm:pt-29",
);

const organiseSections = [
Expand Down Expand Up @@ -66,10 +66,12 @@ export const LessonPlanDisplay = ({
chatEndRef,
sectionRefs,
documentContainerRef,
showLessonMobile,
}: {
chatEndRef: React.MutableRefObject<HTMLDivElement | null>;
sectionRefs: Record<string, React.MutableRefObject<HTMLDivElement | null>>;
documentContainerRef: React.MutableRefObject<HTMLDivElement | null>;
showLessonMobile: boolean;
}) => {
const chat = useLessonChat();
const { lessonPlan, ailaStreamingStatus, lastModeration } = chat;
Expand Down Expand Up @@ -121,21 +123,26 @@ export const LessonPlanDisplay = ({
<div className={displayStyles()}>
{lessonPlan["title"] && (
<Flex direction="column" gap="2">
<Flex direction="row" gap="2">
<Flex direction="row" gap="2" className="opacity-90">
{notEmpty(lessonPlan.keyStage) && (
<Text className="font-bold">
{keyStageToTitle(lessonPlan.keyStage ?? "")}
</Text>
)}
<span></span>
{notEmpty(lessonPlan.subject) && (
<Text className="font-bold">
{subjectToTitle(lessonPlan.subject ?? "")}
</Text>
)}
</Flex>
<h1 className="pb-12 pt-8 text-4xl font-bold">{lessonPlan.title}</h1>{" "}
<h1 className="text-2xl font-bold sm:pb-12 sm:pt-8 sm:text-4xl">
{lessonPlan.title}
</h1>{" "}
{notEmpty(lessonPlan) && lessonPlan.topic !== lessonPlan.title && (
<h2 className="text-lg font-bold">{lessonPlan.topic}</h2>
<h2 className="text-lg font-bold placeholder-opacity-90">
{lessonPlan.topic}
</h2>
)}
</Flex>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const ChatPanelArea = ({
return (
<div
ref={chatAreaRef}
className={`relative mb-11 ${demo.isDemoUser && !isDemoLocked ? "h-[calc(100vh-448px)]" : "h-[calc(100vh-400px)]"} w-[calc(100%+12px)] overflow-y-auto rounded-tl-lg rounded-tr-lg pr-9 `}
className={`relative mb-11 h-[calc(100vh-340px)] ${demo.isDemoUser && !isDemoLocked ? "sm:h-[calc(100vh-448px)]" : "sm:h-[calc(100vh-400px)]"} w-[calc(100%+12px)] overflow-y-auto rounded-tl-lg rounded-tr-lg pr-9 `}
>
{children}
</div>
Expand Down
4 changes: 3 additions & 1 deletion apps/nextjs/src/components/AppComponents/Chat/chat-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ export function ChatPanel({
/>
)}
{isDemoLocked && <LockedPromptForm />}
<ChatPanelDisclaimer size="sm" />
<span className="hidden w-full sm:block">
<ChatPanelDisclaimer size="sm" />
</span>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function ChatStartForm({

return (
<form onSubmit={handleSubmit} ref={formRef}>
<div className="relative flex max-h-60 w-full grow flex-col overflow-hidden border-2 border-black bg-white pr-20 sm:rounded-md">
<div className="relative flex max-h-60 w-full grow flex-col overflow-hidden rounded-md border-2 border-black bg-white pr-20">
<Textarea
required
data-testid="chat-input"
Expand All @@ -52,12 +52,12 @@ export function ChatStartForm({
rows={1}
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder={"Type a subject, key stage and title"}
placeholder={"Subject, key stage and title"}
spellCheck={false}
className="min-h-[60px] w-full resize-none bg-transparent px-10 py-[1.3rem] focus-within:outline-none"
className="min-h-[60px] w-full resize-none bg-transparent px-10 py-[1.3rem] text-lg focus-within:outline-none"
disabled={isSubmitting}
/>
<div className="absolute bottom-10 right-0 top-10 flex items-center justify-center sm:right-10">
<div className="absolute bottom-10 right-10 top-10 flex items-center justify-center ">
<Tooltip>
<TooltipTrigger asChild>
{isSubmitting ? (
Expand Down
6 changes: 3 additions & 3 deletions apps/nextjs/src/components/AppComponents/Chat/chat-start.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export function ChatStart() {
className="h-[100vh] min-h-screen bg-lavender30 pt-26"
>
<div className="flex h-full justify-between">
<div className="h-full w-[66%] overflow-y-scroll p-18 px-10">
<div className="h-full w-full overflow-y-scroll p-18 px-10 sm:w-[66%]">
<div className="mx-auto flex h-full max-w-[580px] flex-col justify-between">
<div className="flex h-full flex-col justify-center gap-18">
<div>
Expand Down Expand Up @@ -141,7 +141,7 @@ export function ChatStart() {
await submit(message.message);
}}
>
<span className="pb-7 text-base font-light underline">
<span className="mt-14 pb-7 text-left text-base font-light underline sm:mt-0">
{message.heading}
</span>
</Button>
Expand All @@ -152,7 +152,7 @@ export function ChatStart() {
<ChatPanelDisclaimer size="sm" />
</div>
</div>
<div className="flex h-full w-[34%] items-center overflow-y-scroll bg-white px-25 pb-9">
<div className="hidden h-full w-[34%] items-center overflow-y-scroll bg-white px-25 pb-9 sm:flex">
<div className="relative -mt-45 w-full">
<p className="mb-10 text-xl font-bold">Lesson downloads</p>
<div className="absolute inset-x-0 top-full">
Expand Down
87 changes: 60 additions & 27 deletions apps/nextjs/src/components/AppComponents/Chat/desktop-layout.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { useEffect, useRef, useState } from "react";

import { useRouter } from "#next/navigation";
import { OakIcon } from "@oaknational/oak-components";
import { Flex } from "@radix-ui/themes";
import { useDemoLocking } from "hooks/useDemoLocking";
import { useMobileLessonPullOutControl } from "hooks/useMobileLessonPullOutControl";

import AiIcon from "@/components/AiIcon";
import Button from "@/components/Button";
import { useLessonChat } from "@/components/ContextProviders/ChatProvider";
import { useDemoUser } from "@/components/ContextProviders/Demo";
import { cn } from "@/lib/utils";
Expand All @@ -14,6 +18,8 @@ import { ChatPanel } from "./chat-panel";
import { ChatPanelArea } from "./chat-panel-area";
import QuickActionButtons from "./chat-quick-buttons";
import ExportButtons from "./export-buttons";
import { LessonPlanProgressBar } from "./export-buttons/LessonPlanProgressBar";
import { LessonPlanProgressDropdown } from "./export-buttons/LessonPlanProgressDropdown";
import ChatButton from "./ui/chat-button";

export interface DesktopChatLayoutProps {
Expand All @@ -25,17 +31,27 @@ export const DesktopChatLayout = ({
}: Readonly<DesktopChatLayoutProps>) => {
const chat = useLessonChat();

const { messages, isLoading, chatAreaRef, lessonPlan } = chat;
const { messages, isLoading, chatAreaRef, lessonPlan, ailaStreamingStatus } =
chat;

const chatEndRef = useRef<HTMLDivElement>(null);
const [hasStarted, setHasStarted] = useState(false);

const [showScrollButton, setShowScrollButton] = useState(false);
const sectionRefs = {};
const documentContainerRef = useRef<HTMLDivElement>(null);
const router = useRouter();
const demo = useDemoUser();
const isDemoLocked = useDemoLocking(messages, isLoading);

const {
showLessonMobile,
setShowLessonMobile,
setUserHasOverRiddenAutoPullOut,
} = useMobileLessonPullOutControl({
ailaStreamingStatus,
messages,
});

const scrollToBottom = () => {
if (chatEndRef.current) {
setShowScrollButton(false);
Expand All @@ -54,14 +70,6 @@ export const DesktopChatLayout = ({
}
}, [setShowScrollButton, chatEndRef, lessonPlan]);

useEffect(() => {
if (!hasStarted) {
if (messages.length > 0) {
setHasStarted(true);
}
}
}, [messages, hasStarted, setHasStarted]);

const endOfDocRef = useRef<HTMLDivElement>(null);

const handleScroll = () => {
Expand All @@ -78,23 +86,18 @@ export const DesktopChatLayout = ({
};

return (
<div
className={cn(
"fixed bottom-0 left-0 right-0 top-0 z-30 hidden md:block",
className,
)}
>
<div className={cn("fixed bottom-0 left-0 right-0 top-0 z-30 ", className)}>
<div
className={`flex h-full flex-row justify-start ${demo.isDemoUser ? "pt-22" : ""}`}
>
<Flex
direction="column"
gap="4"
className="w-[50%] bg-[#ECEFF8] pl-24 pr-24 pt-28 lg:w-[600px] lg:min-w-[600px]"
className="w-full bg-[#ECEFF8] px-13 pt-28 sm:w-[50%] sm:px-24 lg:w-[600px] lg:min-w-[600px]"
height="100%"
position="relative"
>
<Flex align="center" gap="2" justify="between" mt="1">
<div className="mt-6 hidden items-center justify-between gap-5 sm:flex">
<p className="text-2xl font-bold">Aila</p>

<ChatButton
Expand All @@ -106,7 +109,16 @@ export const DesktopChatLayout = ({
>
New lesson
</ChatButton>
</Flex>
</div>
<div className="mt-6 flex justify-end">
<button
onClick={() => setShowLessonMobile(!showLessonMobile)}
className="flex items-center gap-5"
>
<AiIcon />{" "}
<span className="text-base font-bold">View lesson &gt;</span>
</button>
</div>
<div>
<ChatPanelArea
chatAreaRef={chatAreaRef}
Expand All @@ -122,29 +134,50 @@ export const DesktopChatLayout = ({
isEmptyScreen={!!messages.length}
isDemoLocked={isDemoLocked}
/>
<span className="absolute right-0 top-[-70px] z-10 h-[calc(100vh+100px)] w-3 bg-black" />
<span className="absolute right-0 top-[-70px] z-10 hidden h-[calc(100vh+100px)] w-3 bg-black sm:block" />
</Flex>

<div
className="relative w-[50%] lg:w-full "
className={`fixed bottom-0 ${showLessonMobile ? `right-0` : `right-[-100%]`} right-0 top-0 z-30 w-[95%] bg-white duration-300 sm:relative sm:z-0 sm:w-[50%] lg:w-full`}
ref={documentContainerRef}
onScroll={handleScroll}
style={{ overflowY: "auto" }}
>
<ExportButtons
sectionRefs={sectionRefs}
documentContainerRef={documentContainerRef}
/>
<div className="w-full pt-20">
<div className="hidden sm:block">
<ExportButtons
sectionRefs={sectionRefs}
documentContainerRef={documentContainerRef}
/>
</div>
<div className="ml-[-10px] mt-30 flex px-14 sm:hidden">
<button
onClick={() => {
setShowLessonMobile(false);
setUserHasOverRiddenAutoPullOut(true);
}}
className="flex items-center justify-center gap-3"
>
<span className="scale-75">
<OakIcon iconName="cross" />
</span>
<span className="text-base font-bold">Hide lesson</span>
</button>
</div>
<div className="px-14 pb-9 pt-12">
<LessonPlanProgressBar lessonPlan={lessonPlan} />
</div>

<div className="w-full pt-9 sm:pt-20">
<LessonPlanDisplay
showLessonMobile={showLessonMobile}
chatEndRef={chatEndRef}
sectionRefs={sectionRefs}
documentContainerRef={documentContainerRef}
/>
</div>

<span
className={`sticky left-0 right-0 flex justify-center duration-500 ${showScrollButton ? "bottom-10 z-10 opacity-100" : "bottom-0 z-30 opacity-0"} `}
className={`sticky left-0 right-0 hidden justify-center duration-500 sm:flex ${showScrollButton ? "bottom-10 z-10 opacity-100" : "bottom-0 z-30 opacity-0"} `}
>
<ChatButton
variant="primary"
Expand Down
Loading

0 comments on commit b4d4eb2

Please sign in to comment.