copyable_widget 1.2.0 copy "copyable_widget: ^1.2.0" to clipboard
copyable_widget: ^1.2.0 copied to clipboard

Zero-boilerplate clipboard copy for any Flutter widget or text, with haptic feedback and SnackBar confirmation.

copyable_widget #

pub package License: MIT platforms

Zero-boilerplate clipboard copy for any Flutter widget or text — tap, with haptic feedback and SnackBar confirmation out of the box.

Live Demo →


The problem #

Every Flutter screen with copyable data forces you to write the same boilerplate over and over:

GestureDetector(
  onLongPress: () {
    Clipboard.setData(ClipboardData(text: value));
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Copied!')),
    );
  },
  child: widget,
)

copyable_widget eliminates all of it.


Installation #

dependencies:
  copyable_widget: ^1.2.0
import 'package:copyable_widget/copyable_widget.dart';

Quick start #

// Drop-in text shorthand — tap to copy, shows "Copied!" SnackBar
Copyable.text("TXN-9182736")

// Show a label but copy a different value
Copyable.text(
  "Copy card number",
  value: cardNumber,
)

// Wrap any widget — value and child are deliberately decoupled
Copyable(
  value: accountNumber,
  child: AccountNumberRow(...),
)

// Wrap only the copy icon, leaving the rest of the row non-interactive
Row(
  children: [
    Text(accountNumber),
    Copyable(
      value: accountNumber,
      child: Icon(Icons.copy_rounded),
    ),
  ],
)

API reference #

Copyable widget #

Parameter Type Default Description
value String required String written to the clipboard
child Widget required Widget displayed to the user
mode CopyableActionMode? tap tap or longPress (null defaults to tap on all platforms)
feedback CopyableFeedback snackBar() What happens after copy
haptic HapticFeedbackStyle lightImpact Haptic style fired after copy
clearAfter Duration? null Clears clipboard after this duration (falls back to CopyableTheme)
onError void Function(Object)? null Called when Clipboard.setData throws

Copyable.text factory #

Parameter Type Default Description
data String required Text string displayed to the user
value String? null String written to the clipboard. When omitted, data is copied instead — use this to show a label (e.g. "Copy card number") while copying a different value
mode CopyableActionMode? tap tap or longPress (null defaults to tap on all platforms)
feedback CopyableFeedback snackBar() What happens after copy
haptic HapticFeedbackStyle lightImpact Haptic style fired after copy
clearAfter Duration? null Clears clipboard after this duration (falls back to CopyableTheme)
onError void Function(Object)? null Called when Clipboard.setData throws

Also accepts all standard Text parameters (style, textAlign, overflow, maxLines, etc.).

CopyableFeedback options #

Constructor Behaviour
CopyableFeedback.snackBar({text, duration}) Shows a SnackBar styled by your ThemeData.snackBarTheme
CopyableFeedback.custom(fn) Calls fn(BuildContext, CopyableEvent) — you own 100% of the UI
CopyableFeedback.none() Silent — clipboard write and haptic only

CopyableActionMode #

Value Description
tap Default on all platforms
longPress Pass explicitly when long-press behaviour is needed

CopyableEvent (passed to custom callback) #

Field Type Description
value String The string copied to the clipboard
timestamp DateTime When the copy occurred
mode CopyableActionMode Whether triggered by tap or longPress

Usage examples #

// 1. Minimal — all defaults
Copyable.text("TXN-9182736")

// 2. Label + value — display one string, copy another
Copyable.text(
  "Copy card number",
  value: cardNumber,
  feedback: CopyableFeedback.snackBar(text: 'Card number copied!'),
)

// 3. Wrap only the copy icon — row itself stays non-interactive
Row(
  children: [
    Text(accountNumber, style: TextStyle(fontFamily: 'monospace')),
    const Spacer(),
    Copyable(
      value: accountNumber,
      feedback: CopyableFeedback.snackBar(text: 'Copied!'),
      child: Icon(Icons.copy_rounded),
    ),
  ],
)

// 4. Wrap the entire row
Copyable(
  value: accountNumber,
  child: AccountNumberRow(...),
)

// 5. Custom SnackBar message
Copyable.text(
  "TXN-9182736",
  feedback: CopyableFeedback.snackBar(text: "Transaction ID copied"),
)

// 6. Fully custom feedback using event context
Copyable(
  value: walletAddress,
  feedback: CopyableFeedback.custom(
    (context, event) => ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Copied: ${event.value.substring(0, 6)}…')),
    ),
  ),
  child: WalletAddressTile(...),
)

// 7. Silent copy — manage your own state
Copyable(
  value: apiKey,
  feedback: CopyableFeedback.none(),
  child: ApiKeyCard(...),
)

// 8. Long-press mode (explicit)
Copyable.text(
  "Hold to copy",
  mode: CopyableActionMode.longPress,
)

CopyableTheme #

CopyableTheme is an InheritedWidget that sets app-wide defaults for all Copyable and CopyableBuilder widgets. Per-widget values always override theme values.

CopyableTheme(
  data: CopyableThemeData(
    snackBarText: 'Copied to clipboard',
    snackBarDuration: Duration(seconds: 3),
    clearAfter: Duration(seconds: 30), // global secure clear
  ),
  child: Scaffold(
    body: Column(
      children: [
        // Uses theme snackBarText and clearAfter automatically
        Copyable.text('TXN-9182736'),
        // Per-widget overrides the theme
        Copyable.text(
          'Quick copy',
          feedback: CopyableFeedback.snackBar(text: 'Done!'),
          clearAfter: Duration(seconds: 5),
        ),
      ],
    ),
  ),
)

CopyableThemeData #

Field Type Default Description
snackBarText String 'Copied!' Default SnackBar message when no per-widget text is set
snackBarDuration Duration Duration(seconds: 2) Default SnackBar duration
clearAfter Duration? null Default clipboard clear delay for all widgets

clearAfter — Automatic Clipboard Security #

For FinTech, crypto, and any app that handles sensitive data, clearAfter automatically overwrites the clipboard with an empty string after a specified duration:

// Clears clipboard 30 seconds after copy — per widget
Copyable(
  value: privateKey,
  clearAfter: Duration(seconds: 30),
  child: PrivateKeyCard(...),
)

// Or set it globally via CopyableTheme
CopyableTheme(
  data: CopyableThemeData(clearAfter: Duration(seconds: 30)),
  child: MyApp(),
)

CopyableBuilder #

CopyableBuilder gives you full control over the copy UI by exposing an isCopied boolean via a builder function. No SnackBar is shown — you own 100% of the visual feedback.

// GitHub-style icon toggle
CopyableBuilder(
  value: walletAddress,
  builder: (context, isCopied) => AnimatedSwitcher(
    duration: const Duration(milliseconds: 200),
    child: isCopied
        ? const Icon(Icons.check, key: ValueKey('check'), color: Colors.green)
        : const Icon(Icons.copy_rounded, key: ValueKey('copy')),
  ),
)

// Animated copy button
CopyableBuilder(
  value: apiKey,
  resetAfter: Duration(seconds: 3),
  clearAfter: Duration(seconds: 60),
  onCopied: (event) => print('Copied at ${event.timestamp}'),
  builder: (context, isCopied) => ElevatedButton(
    onPressed: null, // tap handled by CopyableBuilder
    child: Text(isCopied ? 'Copied!' : 'Copy API Key'),
  ),
)

CopyableBuilder parameters #

Parameter Type Default Description
value String required String written to the clipboard
builder Widget Function(BuildContext, bool) required Builder receiving isCopied state
mode CopyableActionMode? tap tap or longPress
haptic HapticFeedbackStyle lightImpact Haptic style fired after copy
resetAfter Duration Duration(seconds: 2) How long isCopied stays true
clearAfter Duration? null Clears clipboard after this duration
onError void Function(Object)? null Called when clipboard write fails
onCopied void Function(CopyableEvent)? null Called after successful copy with full event context

Platform support #

Feature Android iOS Web macOS Windows Linux
Clipboard write ✅ ¹
Haptic feedback no-op no-op no-op no-op
SnackBar feedback
Default mode tap tap tap tap tap tap

¹ Web clipboard write is initiated from a user gesture, which is guaranteed.

No conditional platform code required — Flutter's own APIs degrade gracefully.


SnackBar styling #

The package applies no custom style to the SnackBar. All styling — color, shape, elevation, behavior — is controlled by your existing ThemeData.snackBarTheme:

MaterialApp(
  theme: ThemeData(
    snackBarTheme: SnackBarThemeData(
      behavior: SnackBarBehavior.floating,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(12),
      ),
    ),
  ),
)

CopyableFeedback.snackBar() requires a Scaffold ancestor. Use CopyableFeedback.custom() or CopyableFeedback.none() when no Scaffold is present.


Dependencies #

Zero external dependencies. Only Flutter SDK (flutter/services, flutter/material).


Contributing #

Issues and pull requests are welcome at github.com/RamaArif/copyable_widget.

License #

MIT

0
likes
160
points
169
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Zero-boilerplate clipboard copy for any Flutter widget or text, with haptic feedback and SnackBar confirmation.

Repository (GitHub)
View/report issues

Topics

#clipboard #clipboard-widget #copy #copyable #copyable-widget

License

MIT (license)

Dependencies

flutter

More

Packages that depend on copyable_widget