From 12110db74d8f6920138686b06800ba124f11af01 Mon Sep 17 00:00:00 2001 From: pugal Date: Sat, 27 Jun 2026 12:57:09 +0530 Subject: [PATCH] fix(courses): Adjust announcement carousel card width - Reduce viewport fraction in PromotionalBanners carousel - Improve text readability while maintaining a scroll affordance --- .../fix-home-announcements-width/design.md | 25 ++++ .../fix-home-announcements-width/proposal.md | 22 +++ .../specs/dashboard-announcements/spec.md | 13 ++ .../fix-home-announcements-width/tasks.md | 10 ++ .../lib/widgets/promotional_banners.dart | 126 ++++++++++-------- 5 files changed, 142 insertions(+), 54 deletions(-) create mode 100644 openspec/changes/fix-home-announcements-width/design.md create mode 100644 openspec/changes/fix-home-announcements-width/proposal.md create mode 100644 openspec/changes/fix-home-announcements-width/specs/dashboard-announcements/spec.md create mode 100644 openspec/changes/fix-home-announcements-width/tasks.md diff --git a/openspec/changes/fix-home-announcements-width/design.md b/openspec/changes/fix-home-announcements-width/design.md new file mode 100644 index 000000000..d9f137f81 --- /dev/null +++ b/openspec/changes/fix-home-announcements-width/design.md @@ -0,0 +1,25 @@ +## Context + +The home screen displays announcement cards in a horizontal carousel. Currently, each card occupies a large portion of the screen width, limiting how many announcements are visible at once and making the section feel oversized relative to the rest of the home screen. The goal is to reduce the card width so more announcements are visible without scrolling, without changing any data-fetching, navigation, or structural behaviour. + +## Goals / Non-Goals + +**Goals:** +- Announcement cards in the carousel are narrower, letting users see more at a glance. +- The change is isolated to the carousel layout — no structural or data changes. + +**Non-Goals:** +- Changing card height or content layout. +- Affecting the single-card rendering path. +- Modifying navigation, data fetching, or caching behaviour. +- Redesigning the announcement card visual design. + +## Decisions + +**Reduce announcement card width** +The announcement carousel card width should be reduced so the section feels less dominant on the home screen and users can see more content at a glance. No new abstraction or shared token is needed — this is a localised layout adjustment within the courses package. + +## Risks / Trade-offs + +- **Card content may feel more compact** → Announcement titles and summaries may appear more condensed. Text truncation (already in place) handles this gracefully. +- **Wider-than-expected content** → If announcement content is longer, the narrower card may truncate more aggressively, but this is an acceptable trade-off for the improved layout density. diff --git a/openspec/changes/fix-home-announcements-width/proposal.md b/openspec/changes/fix-home-announcements-width/proposal.md new file mode 100644 index 000000000..9eedf4b84 --- /dev/null +++ b/openspec/changes/fix-home-announcements-width/proposal.md @@ -0,0 +1,22 @@ +## Why + +The Updates & Announcements section on the home screen occupies too much horizontal space, causing each card to appear oversized and limiting how many announcements are visible at a glance. Reducing the card width would make better use of available space and allow more announcements to be seen without scrolling. + +## What Changes + +- Reduce the width of announcement cards in the carousel so each card takes up less horizontal space. +- Card height is unchanged — only the horizontal footprint is affected. +- When only a single announcement exists, the layout is unaffected. + +## Capabilities + +### New Capabilities + + +### Modified Capabilities +- `dashboard-announcements`: Announcement cards in the carousel are narrower, allowing more cards to be visible at a glance. + +## Impact + +- **Package**: `courses` +- No API or data changes. No breaking changes. No other packages affected. diff --git a/openspec/changes/fix-home-announcements-width/specs/dashboard-announcements/spec.md b/openspec/changes/fix-home-announcements-width/specs/dashboard-announcements/spec.md new file mode 100644 index 000000000..d9ab3fa07 --- /dev/null +++ b/openspec/changes/fix-home-announcements-width/specs/dashboard-announcements/spec.md @@ -0,0 +1,13 @@ +## MODIFIED Requirements + +### Requirement: Display Announcement Cards at Reduced Width +The announcements carousel SHALL render each card at a reduced width, so that more announcement cards are visible at a glance without horizontal scrolling. + +#### Scenario: Multiple announcements displayed in carousel +- **WHEN** the announcements section renders more than one announcement card in the carousel +- **THEN** each announcement card SHALL occupy a reduced horizontal width compared to the current full-width behaviour +- **AND** the card height remains unchanged + +#### Scenario: Single announcement displayed +- **WHEN** only one announcement card is present +- **THEN** the card rendering path is unaffected by this requirement diff --git a/openspec/changes/fix-home-announcements-width/tasks.md b/openspec/changes/fix-home-announcements-width/tasks.md new file mode 100644 index 000000000..953d0463f --- /dev/null +++ b/openspec/changes/fix-home-announcements-width/tasks.md @@ -0,0 +1,10 @@ +## 1. Implementation + +- [x] 1.1 Reduce the carousel card width in the announcements section so cards are narrower and the next card is partially visible beyond the screen edge +- [x] 1.2 Verify card height is unchanged after the width adjustment + +## 2. Verification + +- [x] 2.1 Confirm that with multiple announcements, the next card peeks out beyond the screen edge as a scroll affordance +- [x] 2.2 Confirm that with a single announcement, the layout is unaffected +- [x] 2.3 Confirm no changes to navigation, data fetching, or card content layout diff --git a/packages/courses/lib/widgets/promotional_banners.dart b/packages/courses/lib/widgets/promotional_banners.dart index dab6189e9..df5f82ef9 100644 --- a/packages/courses/lib/widgets/promotional_banners.dart +++ b/packages/courses/lib/widgets/promotional_banners.dart @@ -36,11 +36,15 @@ class UpdatesAnnouncementsSection extends StatelessWidget { l10n.updatesAnnouncementsTitle, color: design.colors.textPrimary, ), - GestureDetector( + AppSemantics.button( + label: l10n.viewAllAction, onTap: onViewAll, - child: AppText.labelSmall( - l10n.viewAllAction, - color: design.colors.primary, + child: GestureDetector( + onTap: onViewAll, + child: AppText.labelSmall( + l10n.viewAllAction, + color: design.colors.primary, + ), ), ), ], @@ -88,7 +92,8 @@ class PromotionalBanners extends StatelessWidget { return AppCarousel( height: 110 * scale, showDots: false, - viewportFraction: 0.88, + viewportFraction: + (320.0 / MediaQuery.sizeOf(context).width).clamp(0.30, 0.85), padEnds: false, itemCount: posts.length, itemPadding: EdgeInsets.only(left: design.spacing.md), @@ -113,61 +118,74 @@ class AnnouncementCard extends StatelessWidget { Widget build(BuildContext context) { final design = Design.of(context); - // Create a deterministic color palette based on item index + // Create a deterministic color palette based on item index using design tokens final colors = [ - (bg: const Color(0xFFECFDF5), text: const Color(0xFF065F46)), // Green - (bg: const Color(0xFFFAF5FF), text: const Color(0xFF6B21A8)), // Purple - (bg: const Color(0xFFFFFBEB), text: const Color(0xFF92400E)), // Amber + ( + bg: design.colors.success.withValues(alpha: 0.1), + text: design.colors.success + ), // Green + ( + bg: design.colors.primary.withValues(alpha: 0.1), + text: design.colors.primary + ), // Purple + ( + bg: design.colors.warning.withValues(alpha: 0.1), + text: design.colors.warning + ), // Amber ]; final colorScheme = colors[index % colors.length]; - return GestureDetector( - behavior: HitTestBehavior.opaque, + return AppSemantics.button( + label: post.title, onTap: onTap, - child: Container( - padding: EdgeInsets.all(design.spacing.md), - decoration: BoxDecoration( - color: colorScheme.bg, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: design.colors.border.withValues(alpha: 0.06), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - AppText.body( - post.title, - color: colorScheme.text, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: const TextStyle(fontWeight: FontWeight.w600), - ), - const SizedBox(height: 2), - AppText.bodySmall( - post.summary.replaceAll(RegExp(r'[\r\n]+'), ' ').trim(), - color: colorScheme.text.withValues(alpha: 0.8), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ], + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: onTap, + child: Container( + padding: EdgeInsets.all(design.spacing.md), + decoration: BoxDecoration( + color: colorScheme.bg, + borderRadius: design.radius.card, + boxShadow: [ + BoxShadow( + color: design.colors.border.withValues(alpha: 0.06), + blurRadius: 10, + offset: const Offset(0, 4), ), - ), - const SizedBox(width: 12), - Icon( - LucideIcons.chevronRight, - size: 20, - color: colorScheme.text.withValues(alpha: 0.6), - ), - ], + ], + ), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + AppText.body( + post.title, + color: colorScheme.text, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontWeight: FontWeight.w600), + ), + const SizedBox(height: 2), + AppText.bodySmall( + post.summary.replaceAll(RegExp(r'[\r\n]+'), ' ').trim(), + color: colorScheme.text.withValues(alpha: 0.8), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + const SizedBox(width: 12), + Icon( + LucideIcons.chevronRight, + size: 20, + color: colorScheme.text.withValues(alpha: 0.6), + ), + ], + ), ), ), );