Weave Code
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

Tabbed Laravel Package

jibaymcs/tabbed

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require jibaymcs/tabbed
    

    Add to PanelProvider:

    use JibayMcs\Tabbed\TabbedPlugin;
    
    public function panel(Panel $panel): Panel {
        return $panel->plugins([TabbedPlugin::make()]);
    }
    
  2. First Use Case: Add HasTabbedActions trait to a resource (e.g., UserResource):

    use JibayMcs\Tabbed\Traits\HasTabbedActions;
    
    class UserResource extends Resource {
        use HasTabbedActions;
    }
    

    Now, every table row will have an "Open in Tab" action.


Implementation Patterns

1. Automatic Tab Integration

  • Use Case: Quickly enable tabs for all resources.
  • Pattern:
    use JibayMcs\Tabbed\Traits\HasTabbedActions;
    
    class PostResource extends Resource {
        use HasTabbedActions; // Auto-adds "Open in Tab" to all rows
    }
    
    • Pros: Zero configuration for basic use.
    • Cons: Limited customization per action.

2. Manual Action with Customization

  • Use Case: Fine-grained control over tab behavior (e.g., custom labels, colors, or permissions).
  • Pattern:
    use JibayMcs\Tabbed\Actions\OpenInTabAction;
    
    public static function table(Table $table): Table {
        return $table->recordActions([
            OpenInTabAction::make()
                ->tabName(fn ($record) => "Draft: {$record->title}")
                ->tabColor(Color::Yellow)
                ->background(), // Open without switching
        ]);
    }
    
    • Key Methods:
      • tabName(): Customize tab labels dynamically.
      • tabColor()/tabBackground(): Visual hierarchy (e.g., urgent tabs in red).
      • openFor(): Resolve related records (e.g., open a Comment from a Post).
      • confirmOnClose(): Prevent accidental closure of unsaved tabs.

3. Related Record Tabs

  • Use Case: Open tabs for related models (e.g., "View Author" from a Post).
  • Pattern:
    OpenInTabAction::make()
        ->resource(AuthorResource::class)
        ->openFor(fn ($post) => $post->author) // Resolve related record
        ->tabName(fn ($author) => $author->name);
    
    • Critical: Always gate visibility with ->visible(fn ($post) => $post->author) to avoid null errors.

4. Tab Permissions

  • Use Case: Restrict actions (e.g., prevent renaming/pinning for certain users).
  • Pattern:
    OpenInTabAction::make()
        ->canRename(fn ($record) => auth()->user()->isAdmin())
        ->canPin(fn ($record) => $record->is_pinned);
    
    • Global vs. Per-Tab: Global settings (e.g., allowReorder(false) in TabbedPlugin) act as master switches.

5. Hover Cards for Context

  • Use Case: Show rich previews (e.g., user avatars, status badges).
  • Pattern:
    OpenInTabAction::make()
        ->hoverCardContent(fn ($record) => view('filament.tab-preview', ['record' => $record]))
        ->hoverCardPosition(HoverCardPosition::Bottom);
    
    • Security: Escape dynamic content with e() or htmlspecialchars().

6. Programmatic Control

  • Use Case: Open/close tabs via JavaScript (e.g., after API calls).
  • Pattern:
    // Open a tab
    window.dispatchEvent(new CustomEvent('tabbed:open', {
        detail: {
            resource: 'App\\Filament\\Resources\\UserResource',
            recordId: 1,
            label: 'User Profile',
        }
    }));
    
    // Close a tab
    window.dispatchEvent(new CustomEvent('tabbed:close', { detail: { id: 'tab-uuid' } }));
    
    • Events: Listen to tabbed:tab-opened, tabbed:tab-closed, etc., for reactivity.

7. Performance Optimization

  • Use Case: Reduce memory usage for inactive tabs.
  • Pattern:
    TabbedPlugin::make()
        ->lazyLoad()       // Load content only on activation
        ->destroyInactive(); // Unmount components when not visible
    
    • Tradeoff: Lazy loading adds a slight delay on first tab switch.

8. Keyboard Shortcuts

  • Use Case: Power-user workflows (e.g., Alt+W to close tabs).
  • Pattern:
    TabbedPlugin::make()->keyboardShortcuts([
        closeTab: 'ctrl+w', // Override defaults
    ]);
    
    • Note: Shortcuts are disabled when inputs are focused.

Gotchas and Tips

Pitfalls

  1. openFor Misuse:

    • Issue: Forgetting to resolve related records leads to 404s.
    • Fix: Always pair openFor with visible() checks:
      ->openFor(fn ($parent) => $parent->relation)
      ->visible(fn ($parent) => $parent->relation)
      
  2. Dirty State Conflicts:

    • Issue: Unsaved changes in tabs may trigger duplicate confirmation modals.
    • Fix: Use confirmOnClose() sparingly or disable globally:
      TabbedPlugin::make()->confirmClose(false);
      
  3. Lazy Loading + Redirects:

    • Issue: Post-save redirects may break tab persistence.
    • Fix: Enable redirect interception:
      TabbedPlugin::make()->interceptRedirects();
      
  4. CSS Conflicts:

    • Issue: Custom theme styles may override tab colors.
    • Fix: Use !important in your CSS or inspect the generated classes (e.g., .tabbed-tab--active).
  5. LocalStorage Key Collisions:

    • Issue: Multiple panels with default keys (tabbed_tabs) overwrite each other.
    • Fix: Customize the key:
      TabbedPlugin::make()->persistKey('panel_name_tabs');
      

Debugging Tips

  1. Tab Not Opening?

    • Check the browser console for tabbed:open event errors.
    • Verify the resource/page/recordId payload matches Filament’s routing.
  2. Hover Cards Not Showing?

    • Ensure hoverCardDelay isn’t set too high (default: 600ms).
    • Test with static content first:
      ->hoverCardContent(fn () => "Test")
      
  3. Drag & Drop Not Working?

    • Confirm allowReorder(true) is set in TabbedPlugin.
    • Check for conflicting jQuery UI or Alpine.js drag handlers.
  4. Permissions Overrides:

    • Global settings (e.g., allowPin(false)) take precedence over per-tab closures.
    • Debug with:
      dd(TabbedPlugin::make()->getOptions());
      

Extension Points

  1. Custom Tab Components:

    • Override the tab bar via renderHook:
      TabbedPlugin::make()->renderHook(PanelsRenderHook::TOPBAR_LOGO_AFTER);
      
    • Extend the TabbedTab view in your theme:
      @source '../../../../vendor/jibaymcs/tabbed/resources/views/tabbed/tab.blade.php'
      
  2. Tab Metadata:

    • Attach custom data to tabs via OpenInTabAction:
      ->extraData(fn ($record) => ['priority' => $record->urgency]);
      
    • Access in JavaScript via event.detail.tab.extraData.
  3. Tab Events:

    • Listen for tabbed:tab-activated to trigger side effects (e.g., load related data):
      document.addEventListener('tabbed:tab-activated', (e) => {
          console.log('Active tab ID:', e.detail.tabId);
      });
      
  4. Dark Mode:

    • Ensure your theme supports Filament’s dark mode classes (e.g., .dark).
    • Test tab colors in both modes:
      ->tabColor(Color::Gray[500]) // Light mode
      ->tabBackground(Color::Gray[800]) // Dark mode
      

Pro Tips

  1. Tab Search:

    • Enable dropdown mode for overflow tabs:
      TabbedPlugin::make()->dropdownMode();
      
    • Users can search tabs via the dropdown menu.
  2. Pinned Tabs:

    • Use for critical pages (e.g., dashboards):
      OpenInTabAction::make()->
      
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours