Responsiveness of AI

feat/ai-tutor-redesign
Kamran Ahmed 2 days ago
parent 618e4c1233
commit ec458f2fd2
  1. 2
      src/components/AITutor/AIExploreCourseListing.tsx
  2. 33
      src/components/AITutor/AITutorLayout.tsx
  3. 103
      src/components/AITutor/AITutorSidebar.tsx
  4. 27
      src/components/GenerateCourse/AICourse.tsx

@ -86,7 +86,7 @@ export function AIExploreCourseListing() {
{!isExploreAiCoursesLoading && courses && courses.length > 0 && (
<div className="flex flex-col gap-2">
<div className="grid grid-cols-3 gap-2">
<div className="grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3">
{courses.map((course) => (
<AICourseCard
key={course._id}

@ -1,4 +1,7 @@
import { Menu } from 'lucide-react';
import { useState } from 'react';
import { AITutorSidebar, type AITutorTab } from './AITutorSidebar';
import { RoadmapLogoIcon } from '../ReactIcons/RoadmapLogo';
type AITutorLayoutProps = {
children: React.ReactNode;
@ -8,12 +11,32 @@ type AITutorLayoutProps = {
export function AITutorLayout(props: AITutorLayoutProps) {
const { children, activeTab } = props;
const [isSidebarFloating, setIsSidebarFloating] = useState(false);
return (
<div className="flex flex-grow flex-row">
<AITutorSidebar activeTab={activeTab} />
<div className="flex flex-grow h-screen overflow-y-scroll flex-col bg-gray-100 px-4 py-4">
{children}
<>
<div className="flex flex-row items-center justify-between border-b border-slate-200 px-4 py-3 lg:hidden">
<a href="/" className="flex flex-row items-center gap-1.5">
<RoadmapLogoIcon className="size-6 text-gray-500" color="black" />
</a>
<button
className="flex flex-row items-center gap-1"
onClick={() => setIsSidebarFloating(!isSidebarFloating)}
>
<Menu className="size-5 text-gray-500" />
</button>
</div>
<div className="flex flex-grow flex-row">
<AITutorSidebar
onClose={() => setIsSidebarFloating(false)}
isFloating={isSidebarFloating}
activeTab={activeTab}
/>
<div className="flex flex-grow flex-col overflow-y-scroll bg-gray-100 p-3 lg:px-4 lg:py-4">
{children}
</div>
</div>
</div>
</>
);
}

@ -1,8 +1,10 @@
import { BookOpen, Compass, Plus, Star, Users2 } from 'lucide-react';
import { BookOpen, Compass, Plus, Star, X } from 'lucide-react';
import { AITutorLogo } from '../ReactIcons/AITutorLogo';
type AITutorSidebarProps = {
isFloating: boolean;
activeTab: AITutorTab;
onClose: () => void;
};
const sidebarItems = [
@ -35,49 +37,68 @@ const sidebarItems = [
export type AITutorTab = (typeof sidebarItems)[number]['key'];
export function AITutorSidebar(props: AITutorSidebarProps) {
const { activeTab } = props;
const { activeTab, isFloating, onClose } = props;
return (
<aside className="hidden w-[255px] shrink-0 border-r border-slate-200 md:block">
<div className="flex flex-col items-start justify-center px-6 py-5">
<div className="flex flex-row items-center gap-1">
<AITutorLogo className="size-11 text-gray-500" color="black" />
<>
<aside
className={`w-[255px] shrink-0 border-r border-slate-200 ${
isFloating
? 'fixed top-0 bottom-0 left-0 z-50 block border-r-0 bg-white shadow-xl'
: 'hidden lg:block'
}`}
>
{isFloating && (
<button className="absolute top-3 right-3" onClick={onClose}>
<X
strokeWidth={3}
className="size-3.5 text-gray-400 hover:text-black"
/>
</button>
)}
<div className="flex flex-col items-start justify-center px-6 py-5">
<div className="flex flex-row items-center gap-1">
<AITutorLogo className="size-11 text-gray-500" color="black" />
</div>
<div className="my-3 flex flex-col">
<h2 className="-mb-px text-base font-semibold text-black">
AI Tutor
</h2>
<span className="text-xs text-gray-500">
by{' '}
<a href="/" className="underline-offset-2 hover:underline">
roadmap.sh
</a>
</span>
</div>
<p className="max-w-[150px] text-xs text-gray-500">
Your personalized learning companion for any topic
</p>
</div>
<div className="my-3 flex flex-col">
<h2 className="-mb-px text-base font-semibold text-black">
AI Tutor
</h2>
<span className="text-xs text-gray-500">
by{' '}
<a href="/" className="underline-offset-2 hover:underline">
roadmap.sh
</a>
</span>
</div>
<p className="max-w-[150px] text-xs text-gray-500">
Your personalized learning companion for any topic
</p>
</div>
<ul className="space-y-1">
{sidebarItems.map((item) => (
<li key={item.key}>
<a
href={item.href}
className={`font-regular flex w-full items-center border-r-2 px-5 py-2 text-sm transition-all ${
activeTab === item.key
? 'border-r-black bg-gray-100 text-black'
: 'border-r-transparent text-gray-500 hover:border-r-gray-300'
}`}
>
<span className="flex grow items-center">
<item.icon className="mr-2 size-4" />
{item.label}
</span>
</a>
</li>
))}
</ul>
</aside>
<ul className="space-y-1">
{sidebarItems.map((item) => (
<li key={item.key}>
<a
href={item.href}
className={`font-regular flex w-full items-center border-r-2 px-5 py-2 text-sm transition-all ${
activeTab === item.key
? 'border-r-black bg-gray-100 text-black'
: 'border-r-transparent text-gray-500 hover:border-r-gray-300'
}`}
>
<span className="flex grow items-center">
<item.icon className="mr-2 size-4" />
{item.label}
</span>
</a>
</li>
))}
</ul>
</aside>
{isFloating && (
<div className="fixed inset-0 z-40 bg-black/50" onClick={onClose} />
)}
</>
);
}

@ -72,11 +72,11 @@ export function AICourse(props: AICourseProps) {
}
return (
<div className="mx-auto flex w-full max-w-3xl flex-grow flex-col justify-center">
<h1 className="mb-2.5 text-center text-4xl font-semibold max-sm:mb-2 max-sm:text-left max-sm:text-xl">
<div className="mx-auto flex w-full max-w-3xl flex-grow flex-col pt-4 md:justify-center md:pt-10 lg:pt-0">
<h1 className="mb-0.5 text-center text-4xl font-semibold max-md:text-left max-md:text-xl lg:mb-3">
What can I help you learn?
</h1>
<p className="mb-6 text-center text-lg text-gray-600 max-sm:hidden max-sm:text-left max-sm:text-sm">
<p className="mb-3 text-balance text-center text-lg text-gray-600 max-md:text-left max-md:text-sm lg:mb-6">
Enter a topic below to generate a personalized course for it
</p>
@ -100,7 +100,7 @@ export function AICourse(props: AICourseProps) {
maxLength={50}
/>
<div className="flex flex-row items-center justify-between gap-2 px-4 pb-4">
<div className="flex flex-col items-start justify-between gap-2 px-4 pb-4 md:flex-row md:items-center">
<div className="flex flex-row items-center gap-2">
<div className="flex flex-row gap-2">
<DifficultyDropdown
@ -119,7 +119,8 @@ export function AICourse(props: AICourseProps) {
className="mr-1"
id="fine-tune-checkbox"
/>
Explain more for a better course
Explain more
<span className="hidden md:inline"> for a better course</span>
</label>
</div>
@ -127,7 +128,7 @@ export function AICourse(props: AICourseProps) {
type="submit"
disabled={!keyword.trim()}
className={cn(
'flex items-center justify-center rounded-full px-4 py-1 text-sm text-white transition-colors',
'hidden items-center justify-center rounded-full px-4 py-1 text-sm text-white transition-colors md:flex',
!keyword.trim()
? 'cursor-not-allowed bg-gray-400'
: 'bg-black hover:bg-gray-800',
@ -148,6 +149,20 @@ export function AICourse(props: AICourseProps) {
setGoal={setGoal}
setCustomInstructions={setCustomInstructions}
/>
<button
type="submit"
disabled={!keyword.trim()}
className={cn(
'mx-4 mb-3 flex items-center justify-center rounded-full px-4 py-1 text-sm text-white transition-colors md:hidden',
!keyword.trim()
? 'cursor-not-allowed bg-gray-400'
: 'bg-black hover:bg-gray-800',
)}
>
<WandIcon size={18} className="mr-2" />
Generate Course
</button>
</form>
</div>
</div>

Loading…
Cancel
Save