Light mode and UI changes

feat/course
Kamran Ahmed 2 weeks ago
parent a91b43244a
commit f69b619288
  1. 71
      src/components/Course/Chapter.tsx
  2. 6
      src/components/Course/CourseLayout.tsx
  3. 24
      src/components/Course/CourseSidebar.tsx
  4. 2
      src/components/Course/CourseView.tsx
  5. 6
      src/components/Resizable.tsx
  6. 12
      src/data/courses/sql/chapters/introduction/lessons/intro-to-sql.md
  7. 7
      src/styles/global.css

@ -7,6 +7,12 @@ import { CheckIcon } from '../ReactIcons/CheckIcon';
import { getPercentage } from '../../helper/number';
import { useIsMounted } from '../../hooks/use-is-mounted';
function LeftBorder() {
return (
<span className="absolute left-[17px] top-0 h-full w-0.5 bg-gray-200"></span>
);
}
type ChapterProps = ChapterFileType & {
index: number;
isActive?: boolean;
@ -76,31 +82,33 @@ export function Chapter(props: ChapterProps) {
<div>
<button
className={cn(
'relative z-10 flex w-full items-center gap-2 border-b border-zinc-800 p-2 text-sm',
isActive && 'text-white',
'relative z-10 flex w-full items-center gap-2 border-b px-2 py-4 text-base',
{
'text-black': true,
},
)}
onClick={onChapterClick}
>
<div className="flex size-5 items-center justify-center rounded-full bg-zinc-700 text-xs text-white">
<div className="text-400 flex h-[21px] w-[21px] flex-shrink-0 items-center justify-center rounded-full bg-gray-400/70 text-xs text-white">
{index}
</div>
<span className="truncate text-left">{title}</span>
{/*Right check of completion*/}
{isChapterCompleted && lessons.length > 0 && (
<CheckIcon additionalClasses="h-4 w-4 ml-auto" />
<CheckIcon additionalClasses="h-4 w-4 ml-auto flex-shrink-0" />
)}
{/* active background indicator */}
<div
className="absolute inset-0 -z-10 w-[var(--completed-percentage)] bg-zinc-800 transition-[width] duration-150 will-change-[width]"
style={
{
'--completed-percentage': `${completedPercentage}%`,
} as CSSProperties
}
className="absolute inset-0 -z-10 bg-gray-100"
style={{
width: `${completedPercentage}%`,
}}
/>
</button>
{isActive && (
<div className="flex flex-col border-b border-zinc-800">
<div className="flex flex-col border-b">
{lessons.length > 0 && (
<>
<LessonList
@ -113,11 +121,11 @@ export function Chapter(props: ChapterProps) {
/>
<div className="relative">
<label className="relative z-10 my-2 ml-2 block max-w-max rounded-md bg-zinc-800 p-1 px-2 text-xs">
<label className="relative z-10 my-2 ml-2 block max-w-max rounded-md bg-gray-200 p-1 px-2 text-xs">
Exercises
</label>
<span className="absolute left-[17px] top-0 h-full w-0.5 bg-zinc-700"></span>
<LeftBorder />
</div>
<LessonList
@ -162,13 +170,14 @@ function LessonList(props: LessonListProps) {
return (
<div>
{lessons.map((lesson) => {
{lessons.map((lesson, counter) => {
const isActive =
activeLessonId === lesson.id && chapterId === activeChapterId;
const isCompleted = completedLessonSet.has(`${chapterId}/${lesson.id}`);
return (
<Lesson
counter={counter + 1}
key={lesson.id}
{...lesson}
courseId={activeCourseId}
@ -186,6 +195,7 @@ type LessonProps = LessonFileType & {
isActive?: boolean;
isCompleted?: boolean;
courseId: string;
counter: number;
chapterId: string;
};
@ -196,6 +206,7 @@ export function Lesson(props: LessonProps) {
courseId,
chapterId,
id: lessonId,
counter,
isCompleted,
} = props;
const { title } = frontmatter;
@ -207,20 +218,36 @@ export function Lesson(props: LessonProps) {
return (
<a
className={cn(
'relative flex w-full items-center gap-2 p-2 text-sm text-zinc-600',
isActive && 'bg-zinc-800/50 text-white',
'relative flex w-full items-center gap-2 p-2 text-sm hover:bg-gray-100',
{
'bg-gray-100': isActive,
},
)}
href={href}
>
<div className="relative z-10 flex size-5 items-center justify-center rounded-full bg-zinc-700 text-xs text-white">
{isCompleted && <Check className="h-3 w-3 stroke-[3]" />}
{isLoading && isMounted && (
<Loader2 className="h-3 w-3 animate-spin stroke-[3] opacity-60" />
<div
className={cn(
'relative z-10 flex size-5 flex-shrink-0 items-center justify-center rounded-full bg-gray-400/70 text-xs text-white',
)}
>
{counter}
</div>
<span className="flex-grow truncate text-left">{title}</span>
{isCompleted && (
<div
className={cn(
'relative z-10 flex size-5 flex-shrink-0 items-center justify-center rounded-full text-xs text-white',
{
'bg-black': isCompleted,
},
)}
>
<Check className="h-3 w-3 stroke-[3] text-white" />
</div>
<span className="truncate text-left">{title}</span>
)}
<span className="absolute left-[17px] top-0 h-full w-0.5 bg-zinc-700"></span>
{!isActive && <LeftBorder />}
</a>
);
}

@ -1,6 +1,6 @@
import { ChevronLeft, ChevronRight, Loader2 } from 'lucide-react';
import { CourseSidebar, type CourseSidebarProps } from './CourseSidebar';
import { useEffect, useMemo, useState } from 'react';
import {type ReactNode, useEffect, useMemo, useState} from 'react';
import {
useCompleteLessonMutation,
useCourseProgress,
@ -14,7 +14,7 @@ import { CourseNotes } from '../CourseNotes/CourseNotes';
import { CourseAI } from '../CourseAI/CourseAI';
export type CourseLayoutProps = {
children: React.ReactNode;
children: ReactNode;
} & Omit<CourseSidebarProps, 'completedPercentage'>;
export function CourseLayout(props: CourseLayoutProps) {
@ -123,7 +123,7 @@ export function CourseLayout(props: CourseLayoutProps) {
<section
className={cn(
'grid h-screen grid-rows-[1fr_60px] overflow-hidden bg-zinc-900 text-zinc-50',
'grid h-screen grid-rows-[1fr_60px] overflow-hidden bg-white text-black',
activeChapterId && activeLessonId
? 'grid-rows-[1fr_60px]'
: 'grid-rows-1',

@ -27,21 +27,17 @@ export function CourseSidebar(props: CourseSidebarProps) {
const [openedChapterId, setOpenedChapterId] = useState(activeChapterId);
const ceritificateUrl = `/learn/${activeCourseId}/certificate`;
const certificateUrl = `/learn/${activeCourseId}/certificate`;
return (
<aside className="border-r border-zinc-800">
<div className="border-b border-zinc-800 p-4">
<h2 className="text-lg font-semibold">{title}</h2>
<div className="mt-4">
<span>{completedPercentage}% Completed</span>
<div className="relative mt-2 h-1 w-full overflow-hidden rounded-md bg-zinc-800">
<div
className="absolute inset-0 rounded-md bg-zinc-500 transition-[width] duration-150 will-change-[width]"
style={{ width: `${completedPercentage}%` }}
/>
</div>
<aside className="border-r">
<div className="border-b p-4">
<h2 className="mb-1.5 text-2xl font-semibold">{title}</h2>
<div className="text-sm">
<span className="rounded-lg bg-yellow-300 px-1.5 py-0.5 text-black">
{completedPercentage}%
</span>{' '}
Completed
</div>
</div>
@ -72,7 +68,7 @@ export function CourseSidebar(props: CourseSidebarProps) {
<a
className="flex items-center gap-2 p-2 text-sm text-zinc-500 hover:bg-zinc-800 hover:text-white"
href={ceritificateUrl}
href={certificateUrl}
>
<StickyNote className="h-4 w-4 stroke-[2.5]" />
Certificate

@ -49,7 +49,7 @@ export function CourseView(props: CourseViewProps) {
<div className="relative h-full">
<div className="absolute inset-0 overflow-y-auto [scrollbar-color:#3f3f46_#27272a;]">
<div className="mx-auto max-w-xl p-4">
<div className="course-content prose prose-lg prose-invert mt-8 text-zinc-300 prose-headings:mb-3 prose-headings:mt-8 prose-code:text-zinc-100 prose-li:my-1 prose-thead:border-zinc-800 prose-tr:border-zinc-800">
<div className="course-content prose prose-lg mt-8 text-black prose-headings:mb-3 prose-headings:mt-8 prose-li:my-1 prose-thead:border-zinc-800 prose-tr:border-zinc-800">
{children}
</div>
</div>

@ -26,14 +26,14 @@ const ResizableHandle = ({
}) => (
<ResizablePrimitive.PanelResizeHandle
className={cn(
'focus-visible:ring-ring relative flex w-px items-center justify-center bg-zinc-800 after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
'focus-visible:ring-ring relative flex w-px items-center justify-center bg-gray-300 after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
className,
)}
{...props}
>
{withHandle && (
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border border-zinc-800 bg-zinc-800">
<GripVertical className="h-2.5 w-2.5 text-zinc-500" />
<div className="z-10 flex h-[30px] w-3 items-center justify-center rounded-sm bg-gray-200 text-black hover:bg-gray-300">
<GripVertical className="size-5" />
</div>
)}
</ResizablePrimitive.PanelResizeHandle>

@ -5,6 +5,18 @@ order: 100
type: lesson
---
## What is SQL
The SQL language is widely used today across web frameworks and database applications. Knowing SQL gives you the freedom to explore your data, and the power to make better decisions. By learning SQL, you will also learn concepts that apply to nearly every data storage system.
The statements covered in this course use SQLite Relational Database Management System (RDBMS). You can also access a glossary of all the SQL commands taught in this course.
We have some code sample here for users to test. For example this is an example of `inline-code` entry and below is an example of a code block:
```javascript
const someVariable = 'xyz';
console.log(someVariable);
```

@ -71,9 +71,10 @@ a > code:before {
.course-content h1 > code,
.course-content h2 > code,
.course-content h3 > code {
background: transparent !important;
background: #282A36 !important;
color: #f4f4f5 !important;
font-size: inherit !important;
padding: 2px 4px;
border-radius: 5px;
}
.course-content.prose ul li > code:before,
@ -82,7 +83,7 @@ a > code:before {
.course-content p > code:after,
.course-content a > code:after,
.course-content a > code:before {
content: '`' !important;
content: '' !important;
}
.note-content-editor[contenteditable] ~ grammarly-extension,

Loading…
Cancel
Save