Files
buzz/mobile/lib/shared/widgets/reconnect_capsule.dart
klopez4212 5b738eb647 Restyle mobile organization sign-in prompts as toasts (#9050)
Replace the mobile organization sign-in bottom card with the existing
top toast treatment. Use shorter status copy, a solid-red Cancel button
with white text in both modes, and stacked Retry / Use a different
account buttons for denied access with 12 pt side and bottom padding.
The account-switch action uses a dark secondary treatment. Recovery
callbacks and visibility rules are preserved.

Validation: `just mobile-install mobile-check mobile-test`; widget
journeys cover sign-in/cancel/completion, saved-session errors, account
switching at 200% text size, and transient-toast coordination. The
cancel regression was verified to fail with its callback disabled.

Local Flutter previews using production widgets, with synthetic state;
not device captures. Manual test: sign in, cancel, retry, and switch
accounts after denied access; verify each action remains reachable and
the toast clears after successful sign-in.

Before:

![Previous organization
banner](https://github.com/user-attachments/assets/4aceabd1-c9bc-491f-888b-7ee5cf005afa)

| Light mode · 375 pt | Dark mode · 375 pt |
| --- | --- |
| ![Light mode
states](https://github.com/user-attachments/assets/b00bc956-8d27-4b99-ac1e-1f68349c2aa3)
| ![Dark mode
states](https://github.com/user-attachments/assets/930d84d7-b11f-4585-b5d7-77d1c78367ec)
|

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz>
2026-11-04 16:02:07 +00:00

54 lines
1.6 KiB
Dart

part of 'buzz_toast.dart';
/// Parent-owned persistent feedback with the same motion as transient toasts.
class ReconnectCapsule extends HookWidget {
const ReconnectCapsule({
super.key,
required this.onSignIn,
this.visible = true,
this.message = 'Reconnect to Builderlab',
this.actionLabel = 'Sign in',
this.destructiveAction = false,
this.secondaryAction,
this.islandOrigin,
this.islandSpeed = 0.75,
});
final VoidCallback onSignIn;
final bool visible;
/// Persistent status displayed beside or above the actions.
final String message;
/// Label for the primary recovery action.
final String actionLabel;
/// Uses the theme error colors for the primary action.
final bool destructiveAction;
/// Adds a second recovery action and stacks both buttons below the message.
final ({String label, VoidCallback onPressed})? secondaryAction;
final Rect? islandOrigin;
final double islandSpeed;
@override
Widget build(BuildContext context) {
final transientVisible = useValueListenable(_toastCoordinator(context));
// Remove immediately so neither text nor island surfaces overlap.
// Remounting after dismissal restarts the persistent entrance if needed.
if (transientVisible) return const SizedBox.shrink();
return _ToastBubble(
message: message,
actionLabel: actionLabel,
destructiveAction: destructiveAction,
secondaryAction: secondaryAction,
onRetry: onSignIn,
onDismiss: () {},
persistent: true,
visible: visible,
islandOrigin: islandOrigin,
islandSpeed: islandSpeed,
);
}
}