Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
sqlite3: 8d708bc63e9f4ce48f0ad9d6269e478c5ced1d9b
sqlite3_flutter_libs: d13b8b3003f18f596e542bcb9482d105577eff41
sqlite3_flutter_libs: c7b32a4d17d2cbad19895873ccc815f276b1f125

PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e

Expand Down
13 changes: 5 additions & 8 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:testpress/testpress.dart';
import 'package:courses/providers/dashboard_providers.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
Expand All @@ -13,26 +14,22 @@ void main() async {
/// 1. Change the primary color below
/// 2. Save the file (hot reload)
/// 3. See the UI update immediately
class CortexAppRoot extends StatefulWidget {
class CortexAppRoot extends ConsumerWidget {
const CortexAppRoot({super.key});

@override
State<CortexAppRoot> createState() => _CortexAppRootState();
}

class _CortexAppRootState extends State<CortexAppRoot> {
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, WidgetRef ref) {
// 🎨 DARK MODE SUPPORT: Both configs are now passed to DesignProvider.
final lightConfig = DesignConfig.light();
final darkConfig = DesignConfig.dark();
final mode = ref.watch(designModeProvider);

// 🌍 LOCALIZATION SUPPORT: Wrapping the root with LocalizationProvider.
return LocalizationProvider(
child: DesignProvider(
config: lightConfig,
darkConfig: darkConfig,
mode: DesignMode.system,
mode: mode,
child: const CortexApp(),
),
);
Expand Down
2 changes: 2 additions & 0 deletions app/macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import FlutterMacOS
import Foundation

import package_info_plus
import sqlite3_flutter_libs

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin"))
}
40 changes: 40 additions & 0 deletions app/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.1"
http:
dependency: transitive
description:
name: http
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
url: "https://pub.dev"
source: hosted
version: "1.6.0"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.dev"
source: hosted
version: "4.1.2"
intl:
dependency: transitive
description:
Expand Down Expand Up @@ -281,6 +297,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "9.3.0"
package_info_plus:
dependency: transitive
description:
name: package_info_plus
sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968"
url: "https://pub.dev"
source: hosted
version: "8.3.1"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
url: "https://pub.dev"
source: hosted
version: "3.2.1"
path:
dependency: transitive
description:
Expand Down Expand Up @@ -493,6 +525,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.1"
win32:
dependency: transitive
description:
name: win32
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
url: "https://pub.dev"
source: hosted
version: "5.15.0"
xdg_directories:
dependency: transitive
description:
Expand Down
2 changes: 2 additions & 0 deletions openspec/changes/lms-home-drawer/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-02-25
53 changes: 53 additions & 0 deletions openspec/changes/lms-home-drawer/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Design: Home Screen Sidebar Menu (`lms-home-drawer`)

## Overview
The `AppDrawer` is a custom-built side navigation component. Unlike the standard Material `Drawer`, it is designed to be platform-agnostic, using custom animations and the Cortex design system tokens for all visual attributes.

## Visual Design

### Layering & Layout
- **Backdrop**: A full-screen overlay with a semi-transparent black color (`Colors.black54` or equivalent from tokens).
- **Drawer Container**:
- **Width**: `design.layout.drawerWidth` (default: `280px`).
- **Height**: Full screen height (must overlay bottom navigation).
- **Background**: `design.colors.surface` or `design.colors.card` (consistent with dashboard headers).
- **Shadow**: `BoxShadow` with large blur radius and high spread to separate it from the content layer.
- **Border**: 1px solid border on the right edge in light mode for crisp definition.

### Sections & Hierarchy
The drawer is divided into three distinct vertical sections separated by a thin divider (`design.colors.border`).

1. **Section 1: Learning Tools**
- Items: Bookmark, Posts, Analytics, Forum, Doubts, Custom Exam, Your Report.
2. **Section 2: Account & Settings**
- Items: Profile, App Settings, Login Activity, Logout (Highlight with `design.colors.error`).
3. **Section 3: App Status & System**
- Items: Privacy Policy, Theme Toggle (Light/Dark), Version Info (Disabled/Label-only).

### Typography & Iconography
- **Header**: Use `AppText.title("Menu")`.
- **Labels**: Use `AppText.body()` for item labels.
- **Icons**: Use `LucideIcons` (consistent with the rest of the app). Size set to `20px`.
- **Colors**:
- Labels: `design.colors.textPrimary`.
- Icons: `design.colors.textSecondary`.
- Colors (Logout): `design.colors.error`.

## Design Layout Tokens
| Token | Value | Description |
|-------|-------|-------------|
| `drawerWidth` | `280.0` | Base width of the home navigation drawer. |
| `maxDrawerWidth` | `400.0` | Maximum width allowed when using responsive sizing. |

## Interaction & State
- **Trigger**: Tapping the hamburger icon in `DashboardHeader`.
- **Animation**:
- Backdrop: Fade-in.
- Drawer: Slide-in from left.
- **Layering**: The drawer MUST be placed above the `AppTabBar` (bottom navigation) in the widget hierarchy. This is achieved by hosting the drawer in the `AppShell` level.

## Component Integration
- **`AppDrawer` (core)**: Stateless widget that accepts a list of sections.
- **`AppShell` (core)**: Updated to accept an optional `drawer` widget and display it in a `Stack` over the main content and navigation.
- **`appRouter` (testpress)**: Configured to pass the `AppDrawer` into the `AppShell`, using Riverpod to sync state between the `DashboardHeader` and the `AppShell`.
- **`DashboardHeader` (courses)**: Continues to manage the drawer state via `isHomeDrawerOpenProvider`.
21 changes: 21 additions & 0 deletions openspec/changes/lms-home-drawer/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Proposal: Home Screen Sidebar Menu (`lms-home-drawer`)

## Problem
The current `DashboardHeader` contains a hamburger menu icon that is not functional. Users need a persistent navigation drawer to access secondary features such as Analytics, Bookmarks, Profile, and Settings, as well as system controls like Theme Switching and Logout.

## Proposed Solution
Implement a high-fidelity `AppDrawer` component in `packages/core` and integrate it with the `DashboardHeader` in `packages/courses`. The drawer will follow the design and section organization defined in the design specifications, ensuring a custom, platform-agnostic look and feel that aligns with the Cortex design system.

## Key Features
- **Sectioned Navigation**:
- Section 1: Learning tools (Bookmarks, Posts, Analytics, Forum, Doubts, Custom Exam, Reports).
- Section 2: Account management (Profile, Settings, Login Activity, Logout).
- Section 3: App info & System (Privacy, Theme Toggle, Version).
- **Custom Visuals**: Custom backdrop and drawer slide transitions to avoid default platform-specific behaviors.
- **Theme Support**: Full integration with the Design System for light/dark mode variants.
- **Semantic Typography**: Usage of `AppText` roles for labels and headers.
- **Design Governance**: Integration of layout tokens (drawer width) into the `DesignConfig` to avoid hardcoded dimensions and support future responsiveness.

## Impact
- **Packages**: `core` (new widget), `courses` (integration).
- **User Experience**: Provides access to essential navigation items that were previously unreachable through a custom-built, brand-consistent interface.
49 changes: 49 additions & 0 deletions openspec/changes/lms-home-drawer/specs/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Specs: Home Screen Sidebar Menu (`lms-home-drawer`)

## Requirements

### Requirement: Custom Drawer Shell
The system SHALL provide a custom-built navigation drawer that avoids default platform-specific (Material/Cupertino) UI behaviors.

#### Scenario: Visual Parity
- **WHEN** the drawer is opened
- **THEN** it MUST use `design.layout.drawerWidth` for its width
- **AND** it MUST use `design.colors.card` for its background and `design.colors.border` for section separators.

---

### Requirement: Functional Sectioning
The drawer MUST be organized into three logical sections with specific items as defined in the design reference.

#### Scenario: Learning Tools Section
- **WHEN** the first section is rendered
- **THEN** it MUST contain: Bookmark, Posts, Analytics, Forum, Doubts, Custom Exam, and Your Report.
- **AND** each item MUST display its corresponding `LucideIcon`.

#### Scenario: Account Management Section
- **WHEN** the second section is rendered
- **THEN** it MUST contain: Profile, App Settings, Login Activity, and Logout.
- **AND** the "Logout" item MUST use `design.colors.error` for its text and icon.

#### Scenario: Theme Information Section
- **WHEN** the third section is rendered
- **THEN** it MUST contain a Theme Toggle (Light/Dark Mode) and Version Information.

---

### Requirement: Dynamic Theme Switching
The drawer MUST allow the user to toggle between Light and Dark modes without closing the drawer immediately.

#### Scenario: Theme Toggle Interaction
- **WHEN** the user taps the Theme Toggle item
- **THEN** the application theme MUST switch immediately
- **AND** the drawer MUST remain open to allow the user to see the transition.

---

### Requirement: Integration with DashboardHeader
The existing `DashboardHeader` MUST be the designated trigger for opening the drawer.

#### Scenario: Hamburger Trigger
- **WHEN** the hamburger menu icon in `DashboardHeader` is tapped
- **THEN** it MUST trigger the opening of the `AppDrawer`.
24 changes: 24 additions & 0 deletions openspec/changes/lms-home-drawer/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Tasks: Home Screen Sidebar Menu (`lms-home-drawer`)

## 1. Core Component Development (`packages/core`)

- [x] 1.1 Implement `AppDrawer` base widget with custom slide-in animation and backdrop overlay.
- [x] 1.2 Implement `AppDrawerItem` for individual list items with hover/press states and custom coloring for errors.
- [x] 1.3 Implement `AppDrawerDivider` using `design.colors.border`.
- [x] 1.4 Add Theme Toggle logic within the drawer to interact with `DesignProvider`.
- [x] 1.5 Implement `DesignLayout` tokens in `DesignConfig`.
- [x] 1.6 Refactor `AppDrawer` to use `design.layout.drawerWidth`.


## 2. Integration & Dashboard Updates (`packages/courses`)

- [x] 2.1 Update `DashboardHeader` to accept an `onMenuPressed` callback or integrate with a scaffold key.
- [x] 2.2 Define the menu data structure based on the specifications (Sections 1, 2, and 3).
- [x] 2.3 Integrate `AppDrawer` into `PaidActiveHomeScreen`.

## 3. Verification & Polish

- [x] 3.1 Verify item spacing and font sizes match the 15px/semantic role requirements.
- [x] 3.2 Ensure "Logout" and "Red" items use the correct error tokens in both themes.
- [x] 3.3 Verify backdrop tap-to-close behavior.
- [x] 3.4 Check accessibility labels for all navigation items.
2 changes: 2 additions & 0 deletions packages/core/lib/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export 'design/design_provider.dart';

// Icons
export 'package:lucide_icons/lucide_icons.dart';
export 'package:package_info_plus/package_info_plus.dart';

// Tokens (legacy tokens removed - use Design.of(context))

Expand All @@ -28,6 +29,7 @@ export 'widgets/app_subject_chip.dart';
export 'widgets/typography_gallery_screen.dart';
export 'widgets/app_carousel.dart';
export 'widgets/app_loading_indicator.dart';
export 'widgets/app_drawer.dart';

// Shell
export 'shell/app_shell.dart';
Expand Down
Loading