Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Text Copy Field Laravel Package

waynestate/nova-text-copy-field

A Laravel Nova field that displays text with a one-click copy-to-clipboard button, letting admins quickly copy IDs, URLs, tokens, and other values directly from the dashboard. Simple to install and customize.

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm the platform version first. This field's major version tracks Nova's major version, not its own features. v3.x targets Nova 5 (Vue 3, Nova 5 field API); v2.x targets Nova 4. Installing the wrong line does not fail loudly — it typically resolves and then renders a blank cell — so verify before touching a resource:

composer show laravel/nova | grep versions
php artisan nova:version   # if available in your install

Then install on the matching line, pinned:

# Nova 5
composer require waynestate/nova-text-copy-field:^3.0

# Nova 4
composer require waynestate/nova-text-copy-field:^2.0

Find the class before you guess the namespace. This package ships no config file and no published docs beyond its README, so read the source directly — it is one PHP class plus a compiled Vue component:

composer show waynestate/nova-text-copy-field          # version, autoload namespace
ls vendor/waynestate/nova-text-copy-field/src          # field class
ls vendor/waynestate/nova-text-copy-field/dist         # compiled JS you'll be debugging
head -40 vendor/waynestate/nova-text-copy-field/src/*.php

That 30-second read tells you the exact namespace (typically Waynestate\NovaTextCopyField\TextCopy), the constructor signature, and whether the v3 refactor changed any chainables.

First use case — an operator needs the value, not the record. The canonical fit is a read-only identifier on a detail view: an API token, an invite code, a Stripe customer ID, a generated public URL.

// app/Nova/Account.php
use Waynestate\NovaTextCopyField\TextCopy;

public function fields(Request $request)
{
    return [
        ID::make()->sortable(),
        Text::make('Name'),

        // Before: operator triple-clicks, misses a character, opens a ticket.
        // After: one click.
        TextCopy::make('API Token', 'api_token')
            ->onlyOnDetail()
            ->canSee(fn () => $request->user()->can('viewSecrets', $this->resource)),
    ];
}

That is the whole integration: no migration, no config publish, no queue, no service provider registration. Swap the import, swap Text::make for TextCopy::make, deploy. Realistic effort is minutes of code and most of an hour validating in staging — reserve the time for verification, not implementation.

Implementation Patterns

Treat it as Text and migrate opportunistically. The field extends Nova's native text field, so resolveUsing, displayUsing, canSee, onlyOnDetail, onlyOnIndex, sortable, textAlign, default, and nullable all behave as you already expect. The lowest-risk adoption is mechanical: find the fields where an operator visibly retypes a value, and change only those. Do not blanket-replace every Text — a copy button next to a human-readable name is noise.

Prefer the raw-attribute constructor for anything already on the model.

// Attribute exists on the model — zero extra queries.
TextCopy::make('Tracking Number', 'tracking_number')
    ->onlyOnDetail()
    ->textAlign('left'),

Use resolveUsing for computed or assembled values (signed URLs, concatenated identifiers, values behind an accessor). This is the escape hatch that keeps you from adding a database column purely to make the field happy:

TextCopy::make('Webhook Endpoint')
    ->resolveUsing(fn () => route('webhooks.receive', $this->resource))
    ->onlyOnDetail(),

Verify empirically whether the copied payload follows displayUsing. Display formatting and copied text are conceptually two different values, and the package's copy target is not documented. Before you ship a displayUsing(fn ($v) => Str::limit($v, 8) . '…') field, click the button and paste somewhere to confirm you copied the truncated string (bad) rather than the real secret (good). If it copies the displayed value, drop displayUsing on copyable fields entirely and rely on onlyOnDetail to keep long values out of the index.

Gate secrets with canSee, and mean it. A copy button turns "technically visible in the DOM" into "one click from the clipboard." Pair every credential field with a policy check, and remember canSee is a server-side decision — it removes the field from the payload, unlike CSS hiding:

TextCopy::make('Webhook Signing Secret', 'signing_secret')
    ->onlyOnDetail()
    ->canSee(fn (Request $request) => $request->user()->hasRole('admin')),

Show identifiers on the index only when truncation is acceptable. The index is for scanning; the detail view is for retrieving. A long token squeezed into an index column gives you a copy button that copies something you may not want on a wide-open list screen:

TextCopy::make('Public ID', 'public_id')
    ->onlyOnIndex()
    ->textAlign('center'),

Standardize the affordance across resources. The main non-obvious benefit is consistency: once the copy interaction lives in one field class, the next developer adds TextCopy::make('Invite Code') instead of hand-rolling a Vue component, and every screen behaves identically. Write it into your Nova conventions doc (even a paragraph) so the pattern is discoverable.

Smoke-test it in a browser, not in PHPUnit. There is nothing server-side to assert — the failure mode is a Vue component that does not mount. A Laravel Dusk test (or a manual staging checklist) that loads one detail page rendering the field and asserts the button exists is worth more than a feature test on the resource class:

// tests/Browser/CopyFieldTest.php
$browser->loginAs($admin)
    ->visit('/nova/resources/accounts/1')
    ->assertPresent('[data-testid="copy-button"]');  // confirm selector in dist/ or DOM

Gotchas and Tips

Silent UI failure is the headline risk. A Vue mount failure renders an empty cell with an exception only in the browser console — no PHP exception, no log line, no 500. Your monitoring does not watch admin-panel JavaScript. When a field "just shows nothing" after an upgrade, open devtools first: a mismatch between the field's compiled asset and Nova's Vue version is the usual cause. Clear the Nova asset cache and rebuild if you vendor your assets (php artisan nova:publish, npm run dev / npm run prod).

Pin both sides exactly during a Nova upgrade. A floating ^3.0 on a package whose version number is a proxy for the Nova major is a landmine. Pin this field and Nova together in composer.json, and sequence the bump inside the Nova 4 → 5 change window — never ahead of it. On Nova 4, composer update will either refuse to resolve or silently produce the blank-cell failure above.

Copy needs a secure context. navigator.clipboard requires HTTPS or localhost. If your team hits staging over plain-HTTP on an internal hostname, the button may appear to do nothing. Check that the URL bar shows a secure origin before filing a bug against the package.

The refactor in v3.0.0 is undocumented. Release notes say "Nova 5 Support" and "refactor to nova v5" — no migration guide, no deprecations, no compatibility matrix. Diff the v2.0.5...v3.0.0 tag for the field class before upgrading, and confirm the constructor signature and any chainables you actually use survived. This is a five-minute diff that replaces an hour of confusion.

Re-check the native alternative. Nova 5 changed every field definition anyway; if Nova now ships a copyable text primitive that covers a plain value-plus-button, the correct move is to delete this field from your resources, not upgrade the dependency. One fewer vendor to track, no lockstep constraint on the next Nova major. Do this check during the upgrade, while the files are already open — it is the cheapest moment you will ever have.

A copy button does not give you audit, bulk, or formatting semantics. No copy logging, no multi-field clipboard, no permission-gated reveal beyond canSee, no toast customization. If a requirement demands any of those, this field is not the answer and you should write the ~30–100 line in-house field instead — which is also the live fallback if upstream stalls (two contributors, one institution, 1 star, no security SLA). Keep that fallback written down; replacement cost is genuinely low and documenting it prevents this from becoming a ceiling on future Nova upgrades.

Sorting is database-only. sortable() sorts on the underlying column. A resolveUsing value that does not exist in the schema will not sort meaningfully — omit sortable() on computed copy fields rather than shipping a sort control that appears to work.

Name an owner. When this breaks after a Nova upgrade, someone has to answer. It should be whoever owns admin tooling, not "whoever touched it last."

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums