Skip to main content

Social Components

Social components enable user interactions, content sharing, and community engagement in BookWish.

LineCard

A card displaying a user's "line" (post) about a book, with likes, replies, and sharing capabilities.

Usage

LineCard(
line: line,
isNested: false, // true for reply threads
)

Props

PropertyTypeRequiredDefaultDescription
lineLineYes-Line model with content, author, book reference
isNestedboolNofalseWhether line is a reply (affects styling)

Anatomy

Header

  • UserChip: Displays author avatar and name
  • Timestamp: Relative time (via timeAgo() utility)

Content

  • Text: Line content with edit functionality for authors
  • Edit Mode: TextField with Save/Cancel buttons when editing
  • Character Limit: 1000 characters

Book Reference (parent lines only)

  • BookMiniChip: Shows book thumbnail, title, and authors
  • Tap: Opens BookInfoOverlay

Context Tags (parent lines only)

  • Club badge: Shows "Book Club" with person icon
  • Challenge badge: Shows "Challenge" with rosette icon

Actions

  • Like Button: Heart icon with count, animated
  • Reply Button: Chat bubble icon with count (parent lines only)
  • Share Button: Share via share_plus package
  • Menu: Report and Edit (for authors) options

Replies Section (parent lines only)

  • Reply Input: TextField for authenticated users
  • Reply List: Nested LineCards with isNested: true
  • Character Limit: 500 characters for replies

States

  • Normal: White background, elevation 2
  • Nested: Parchment background, no elevation, 8px border radius
  • Editing: Shows TextField with action buttons
  • Submitting: Shows loading spinner on buttons

Features

  • Inline Editing: Authors can edit their posts
  • Threaded Replies: Expandable reply sections with nested cards
  • Like Animation: Heart icon scales on tap
  • Real-time Updates: Watches lineRepliesNotifierProvider and feedNotifierProvider
  • Auth-gated Actions: Reply input only shown for logged-in users

Styling

Parent Line

  • Padding: 16px all
  • Border radius: 12px
  • Elevation: 2

Nested Reply

  • Padding: 12px all
  • Border radius: 8px
  • Background: AppColors.parchment
  • Left border: 2px ink blue at 0.2 alpha

ReviewCard

A card displaying a book review with star rating and like functionality.

Usage

ReviewCard(
review: review,
)

Props

PropertyTypeRequiredDescription
reviewReviewYesReview model with rating, content, book reference

Anatomy

Header

  • UserChip: Review author
  • Rating Stars: 1-5 filled/outlined stars (18px, amber color)

Metadata

  • Timestamp: Relative time display

Content

  • Review Text: Optional text content in AppTypography.cardBody
  • Max Lines: No limit (full text displayed)

Book Reference

  • BookMiniChip: Same as LineCard
  • Tap: Opens BookInfoOverlay

Actions

  • Like Button: Shared component with count
  • Menu: Report option

Rating Stars

The _RatingStars internal widget generates 5 stars:

  • Filled: CupertinoIcons.star_fill for rating value
  • Outlined: CupertinoIcons.star for remaining
  • Color: Colors.amber
  • Size: 18px

Styling

  • Padding: 16px all
  • Border radius: 12px
  • Elevation: 2
  • Background: White

Features

  • Like Toggle: Via reviewServiceProvider
  • Report: Opens ReportDialog
  • Feed Integration: Refreshes feedNotifierProvider on actions

UserChip

A compact user avatar and name display with tap-to-profile functionality.

Usage

UserChip(
user: user,
onTap: () => customAction(), // Optional override
)

Props

PropertyTypeRequiredDescription
userUserYesUser model with avatar, displayName, username
onTapVoidCallback?NoCustom tap handler (defaults to profile overlay)

Anatomy

  • Avatar: CircleAvatar with 16px radius
    • With image: NetworkImage from user.avatarUrl
    • Without image: Initial letter of name in AppTypography.cardLabel
  • Name: Display name or username, 12px font size
  • Weight: 600 font weight

Default Behavior

Tapping opens ProfileOverlay with user details unless custom onTap provided.

Styling

  • Row layout with 8px gap
  • Avatar radius: 16px (32px diameter)
  • Text style: AppTypography.cardLabel with bold weight

UserAvatar

UserAvatar functionality is embedded in UserChip and NotificationTile.

Badge Types

While not explicitly a separate component, avatar badges appear in:

NotificationTile

  • Type-specific background colors
  • Icon overlays for notification types
  • Falls back to actor's avatar if available

Badge Colors (in NotificationTile):

  • Order Update: Blue
  • New Follower: Purple
  • Line Reply: Green
  • Line Like: Red
  • Review Like: Orange
  • Stock Alert: Teal
  • Club Invite: Indigo
  • Club Book Added: Deep Purple
  • Challenge Start: Amber
  • Challenge Ending: Deep Orange

ActivityFeedItem

Activity feed items use LineCard and ReviewCard based on content type.

Activity Types

The feed renders different components:

  • Lines: LineCard component
  • Reviews: ReviewCard component
  • Notifications: NotificationTile component

Feed Implementation

// In FeedProvider/SharePage
feedState.when(
data: (items) => ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
if (item is Line) return LineCard(line: item);
if (item is Review) return ReviewCard(review: review);
// ...
},
),
)

CommentThread

Comment threads are implemented via LineCard's reply system.

Usage

Replies are displayed when _showReplies is true in parent LineCard.

Features

  • Threading: Single level of nesting (parent → replies)
  • Reply Input: Text field with send button
  • Loading States: Shows spinner while fetching replies
  • Error States: Displays error message if fetch fails
  • Empty State: "No replies yet" for authenticated users

Styling

Thread Container

  • Left border: 2px ink blue at 0.2 alpha
  • Left padding: 12px
  • Top padding: 12px

Reply Input

  • Background: AppColors.parchment
  • Border radius: 8px
  • Padding: 12px horizontal, 8px vertical
  • Max lines: 3, min lines: 1

LikeButton

Shared button component for likes across Line and Review cards.

Usage

LikeButton(
isLiked: item.isLikedByMe,
count: item.likeCount,
onToggle: () => toggleLike(),
)

Props

PropertyTypeRequiredDescription
isLikedboolYesCurrent like state
countintYesNumber of likes
onToggleVoidCallbackYesCallback when toggled

Features

  • Animation: Scale animation from 1.0 to 1.3 on tap
  • Icon: Filled heart when liked (red), outlined when not
  • Count Display: Only shows count if > 0
  • Duration: 200ms animation

Styling

  • Icon size: 20px
  • Liked color: Colors.red
  • Unlike color: Theme default
  • Padding: 8px horizontal, 4px vertical
  • Border radius: 20px (circular ripple)

BookMiniChip

Internal component used in LineCard and ReviewCard for book references.

Anatomy

  • Thumbnail: 32x48px book cover
  • Title: 2-line max, AppTypography.bookTitleSmall
  • Authors: 1-line max, 11px font size
  • Container: Rounded 8px, surface container color
  • Padding: 8px all

Behavior

  • Tappable to open BookInfoOverlay
  • Fallback icon if no thumbnail

Common Patterns

Interaction Flows

Like Flow

  1. User taps LikeButton
  2. Animation plays (scale up/down)
  3. API call to like/unlike service
  4. Feed provider refreshes
  5. UI updates with new count

Reply Flow

  1. User taps reply button
  2. Reply section expands
  3. User types in input field
  4. Submit button posts reply
  5. Reply appears in nested list

Edit Flow (LineCard only)

  1. Author taps Edit in menu
  2. TextField replaces content
  3. User edits text
  4. Save updates via lineService
  5. Feed refreshes with new content

State Management

All social components use Riverpod providers:

  • feedNotifierProvider: Main activity feed
  • lineRepliesNotifierProvider: Thread replies
  • lineServiceProvider: Line CRUD operations
  • reviewServiceProvider: Review operations
  • authNotifierProvider: User authentication state

Error Handling

Components show SnackBar messages for:

  • Failed like/unlike operations
  • Failed reply submissions
  • Failed content updates
  • API errors

Typography

  • Card Heading: AppTypography.cardHeading
  • Card Body: AppTypography.cardBody
  • Card Caption: AppTypography.cardCaption (timestamps, metadata)
  • Card Label: AppTypography.cardLabel (buttons, badges)

Color Palette

  • Ink Blue: AppColors.inkBlue (primary text, icons)
  • Parchment: AppColors.parchment (reply backgrounds)
  • Forest Green: AppColors.forestGreen (success messages)
  • Coral Spine: AppColors.coralSpine (error messages)
  • Teal Edge: AppColors.tealEdge (primary buttons)