feat(dashboard): improve student course sidebar navigation (#814)
* docs(prototypes): add course sidebar navigation HTML prototypes Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * docs(prototypes): add downloadable zip for course sidebar mockups Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * feat(dashboard): improve student course sidebar navigation Collapse all sections except the active one for students, show section completion as counts (e.g. 3/4), and replace the footer progress card with prev/next controls plus a thin progress bar. Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * fix(dashboard): address PR review and remove sidebar prototypes Remove HTML prototype files from the PR. Match content IDs as exact path segments for active-item resolution, and use content-neutral prev/next labels. Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * fix(dashboard): keep ClassroomIO brand untranslated in powered-by footer Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * fix(dashboard): restore progress summary in course sidebar footer Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * fix(dashboard): move progress bar below summary in sidebar footer Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * feat(course): add mobile student bottom nav with outline sheet Implement prototype 3 mobile navigation for course learners: a fixed bottom bar with progress ring, prev/next controls, and a sheet showing the progress card plus collapsible course outline with scroll-to-active. Extends public-course UI primitives (ring bottom nav, collapsible sidebar sections, mobile sheet progress slot) and wires them into the authenticated course layout for isCourseLearnerView on lesson/exercise routes. Hides duplicate header prev/next and progress popover on mobile. Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * fix(course): address review feedback and exclude prototypes - Add .coderabbit.yaml and .greptile/config.json to skip prototypes/** - Document prototypes/ as out-of-scope in AGENTS.md and Greptile rules - Render locked mobile outline rows without href navigation targets - Replace nested IconButton in collapsible section trigger with chevron icon - Reset public-course sidebar section collapse on every mobile sheet reopen Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> ---------
This commit is contained in:
co-authored by
Rotimi Best
parent
bf3a7e7057
commit
55ae6dd4fe
@@ -26,6 +26,10 @@
|
||||
import { profile } from '$lib/utils/store/user';
|
||||
import { isOrgAdmin } from '$lib/utils/store/org';
|
||||
import { isCourseLearnerView } from '$lib/utils/store/app';
|
||||
import { isMobileStore } from '@cio/ui/hooks/is-mobile.svelte';
|
||||
import { CourseMobileBottomNav } from '$features/course/components/mobile';
|
||||
import { getCourseProgress } from '$features/course/utils/content';
|
||||
import { isCourseMobileBottomNavVisible } from '$features/course/utils/mobile-bottom-nav';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
import { ContentType } from '@cio/utils/constants/content';
|
||||
import type { CourseMember } from '$features/course/utils/types';
|
||||
@@ -108,6 +112,18 @@
|
||||
sidePanel.activePanelId !== AI_ASSISTANT_PANEL_ID
|
||||
);
|
||||
|
||||
const courseProgress = $derived(getCourseProgress(courseApi.course));
|
||||
const showMobileBottomNav = $derived(
|
||||
isCourseMobileBottomNavVisible({
|
||||
isCourseLearnerView: $isCourseLearnerView,
|
||||
isMobile: isMobileStore.current,
|
||||
isLessonOrExercisePage,
|
||||
courseProgress
|
||||
})
|
||||
);
|
||||
|
||||
const contentAskAiBarBottomClass = $derived(showMobileBottomNav ? 'bottom-16' : 'bottom-4');
|
||||
|
||||
function clampSidebarWidth(width: number) {
|
||||
return Math.min(COURSE_SIDEBAR_MAX_WIDTH, Math.max(COURSE_SIDEBAR_MIN_WIDTH, width));
|
||||
}
|
||||
@@ -200,7 +216,7 @@
|
||||
onSidebarWidthChange={handleSidebarWidthChange}
|
||||
/>
|
||||
|
||||
<Sidebar.Inset class="ui:min-w-0 ui:flex-1">
|
||||
<Sidebar.Inset class="ui:min-w-0 ui:flex-1 {showMobileBottomNav ? 'pb-24' : ''}">
|
||||
<CourseHeader />
|
||||
<ContentCreateModal />
|
||||
<CourseCompletionModal />
|
||||
@@ -223,7 +239,11 @@
|
||||
{@render children?.()}
|
||||
|
||||
{#if showContentAskAiBar}
|
||||
<ContentAskAiBar class={contentAskAiWidthClass} />
|
||||
<ContentAskAiBar class={contentAskAiWidthClass} bottomClass={contentAskAiBarBottomClass} />
|
||||
{/if}
|
||||
|
||||
{#if showMobileBottomNav}
|
||||
<CourseMobileBottomNav courseId={data.courseId} {path} />
|
||||
{/if}
|
||||
{/if}
|
||||
</Sidebar.Inset>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
footerNextLabel={$t('public_course.footer_nav.next')}
|
||||
courseSlug={data.tree.course.slug}
|
||||
poweredByLabel={$t('public_course.powered_by.label')}
|
||||
poweredByBrand={$t('public_course.powered_by.brand')}
|
||||
poweredByBrand="ClassroomIO"
|
||||
onItemClick={navigateTo}
|
||||
onPrev={() => navigateTo(prevItem)}
|
||||
onNext={() => navigateTo(nextItem)}
|
||||
|
||||
Reference in New Issue
Block a user