Advertisement

AI Analysis

Livewire 4 Migration: File-by-File Guide

This document provides specific migration instructions for each file that needs updating.


✅ Implementation Status (Updated)

Phase 1: Core Migration - COMPLETED ✅

  • composer.json: Updated to require livewire/livewire ^4.0, flux ^2.3, flux-pro ^2.7
  • $listeners → #[On()]: All 14 files migrated
  • Livewire.on() JS callbacks: Fixed array destructuring (2 files)

Phase 2: Wire Transitions - COMPLETED ✅

  • draft/draft-lobby.blade.php: Modal overlays with wire:transition.opacity and content with wire:transition.scale
  • notification-manager.blade.php: Unsaved changes bar with wire:transition.slide.up
  • scrims/import-flex-clash-games.blade.php: Processing indicator modal
  • scrims/conflict-warning.blade.php: Expandable details with wire:transition.slide.down
  • scrims/opponent.blade.php: Expandable form with wire:transition.slide.down
  • surge/improvement-trajectory.blade.php: Expandable charts section

Phase 3: Loading States - COMPLETED ✅

  • comps/create.blade.php: wire:loading.delay.shortest for smooth UX
  • scrims/create.blade.php: Targeted loading with spinner icons
  • matches/create.blade.php: Both create buttons with delay modifiers
  • dashboard/insights.blade.php: View analysis button improved

Phase 4: JavaScript Breaking Changes - COMPLETED ✅

  • draft/create-draft-lobby.blade.php: Fixed Livewire.on('copy-to-clipboard', ([event]) => ...)
  • components/banner-helper.blade.php: Fixed all Livewire.on() callbacks to use array destructuring

Phase 5: URL Attributes - COMPLETED ✅

  • Scrims/Find.php: Migrated 5 URL params to #[Url] attributes, removed redundant mount() initialization
  • Teams/Index.php: Migrated 3 URL params to #[Url] attributes
  • Scrims/Index.php: Migrated 4 URL params to #[Url] attributes, removed redundant mount() initialization
  • Playbook/Index.php: Migrated 7 URL params to #[Url] attributes
  • Comps/Index.php: Migrated 6 URL params to #[Url] attributes

Phase 6: Lazy Loading - COMPLETED ✅

  • Surge Hub (9 components): improvement-trajectory, team-health-dashboard, strategic-intel, player-spotlight, weekly-podcast, performance-pulse, daily-missions, role-transition-context, playstyle-mismatch-alerts
  • Dashboard (4 components): upcoming-scrims, daily-message, comps, recent-activity

Phase 7: Islands Analysis - NOT APPLICABLE ⏸️

After analysis, Islands were determined to be not a good fit for this codebase:

  • Most components have significant user interactions requiring immediate hydration
  • Lazy loading already provides similar performance benefits
  • Heavy Alpine.js state usage (@entangle, x-data) conflicts with deferred hydration

Remaining Tasks

  • [ ] Run composer update livewire/livewire livewire/flux livewire/flux-pro (requires local environment)
  • [ ] Test all updated components
  • [ ] Optional: Migrate $rules/$messages to methods (4 files)

Part 0: CSS Transitions → wire:transition

Overview

The codebase has 1,023 CSS transition usages across 152 files. Many of these are used with Livewire state changes and can benefit from wire:transition for smoother morphing.

Types of Transitions to Migrate

Type A: Livewire State-Controlled Visibility (HIGH PRIORITY)

These transitions on elements that appear/disappear based on Livewire state should use wire:transition:

{{-- Before: CSS transition with @if --}}

@if($showForm)

Form content...

@endif

{{-- After: wire:transition handles the animation --}}

@if($showForm)

Form content...

@endif

Type B: Loading State Transitions (MEDIUM PRIORITY)

Elements with transitions triggered by wire:loading:

{{-- Before: CSS transition with wire:loading --}}

Save

{{-- After: wire:transition.out for smooth removal --}}

Save

Type C: Alpine-Controlled (KEEP AS-IS)

Transitions controlled by Alpine.js x-show should remain with x-transition or CSS:

{{-- Keep CSS/Alpine for Alpine-controlled visibility --}}

Content

High-Priority Files for CSS Transition Migration

1. resources/views/livewire/games/fetch-game.blade.php (23 transitions)

Current Pattern:

x-bind:class="{ 'opacity-50 scale-95': loading }">

Issue: This uses Alpine for state but CSS for animation. The CSS transition is redundant since Alpine handles it.

Migration Strategy:

  • Keep Alpine-controlled opacity/scale
  • Remove redundant transition-all duration-500 ease-out from static elements
  • Use wire:transition only where Livewire controls visibility directly

Simplified version:

{{-- Remove redundant transitions on static wrapper --}}

{{-- Keep Alpine-controlled transitions --}}

    ...

{{-- For wire:loading controlled elements, use wire:transition --}}

Submit Game ID


2. resources/views/livewire/scrims/confirm.blade.php (19 transitions)

Current Pattern:

Migration:

{{-- Option 1: If x-show controls it, use x-transition --}}
x-transition:enter="transition ease-out duration-300"

x-transition:enter-start="opacity-0 translate-y-4"

x-transition:enter-end="opacity-100 translate-y-0">

{{-- Option 2: If @if/$confirmed controls it, use wire:transition --}}

@if($confirmed)

@endif


3. resources/views/livewire/roster/show.blade.php (22 transitions)

Focus areas:

  • Button hover states (keep CSS - user interaction, not Livewire state)
  • Modal show/hide (use wire:transition if controlled by Livewire)
  • Loading states (use wire:transition)

4. resources/views/livewire/scrims/find.blade.php (32 transitions)

Pattern Found:

Keep: These are hover interactions, not Livewire state changes.

Migrate: Any transitions on elements that appear/disappear via Livewire.


CSS Transition Categories

Category

Action

Example

Hover effects

KEEP CSS

hover:scale-105 transition-transform

Focus states

KEEP CSS

focus:ring-2 transition-all

User interactions

KEEP CSS

active:scale-95 transition-transform

Livewire @if visibility

USE wire:transition

@if($show) <div wire:transition>

wire:loading visibility

USE wire:transition

wire:loading wire:transition

Alpine x-show

USE x-transition

x-show="open" x-transition

Permanent decorative

KEEP CSS

Background gradients, shimmer effects

Files by Priority

HIGH PRIORITY (State-controlled visibility):

1. livewire/games/fetch-game.blade.php - Loading states

2. livewire/scrims/confirm.blade.php - Form state changes

3. livewire/roster/show.blade.php - Modal visibility

4. livewire/dashboard/podcast-widget.blade.php - Generation states

5. livewire/floating-onboarding.blade.php - Step transitions

MEDIUM PRIORITY (Mixed usage):

1. livewire/draft/draft-lobby.blade.php - Pick/ban animations

2. livewire/dashboard/daily-message.blade.php - Content changes

3. livewire/scrims/find.blade.php - Result filtering

4. livewire/comps/show.blade.php - Tab content

LOW PRIORITY (Mostly hover/decorative):

1. Component buttons (primary-button.blade.php, etc.)

2. Navigation components

3. Static marketing pages


Part 1: Listener Migration ($listeners → #[On()])

1. app/Livewire/Dashboard.php

Current:

protected $listeners = [

'go-to-profile' => 'goToProfile',

'go-to-opgg' => 'goToOpgg',

];

Change to:

use Livewire\Attributes\On;

#[On('go-to-profile')]

public function goToProfile()

{

$this->dispatch('open-url', route('teams.public', $this->user->currentTeam));

}

#[On('go-to-opgg')]

public function goToOpgg()

{

$this->dispatch('open-url', $this->user->currentTeam->op_gg_link);

}


2. app/Livewire/Roster/Show.php

Current:

protected $listeners = [

'reset-changes' => 'cancelAddPlayer',

'removePlayer' => 'removePlayer',

'executeNotificationAction' => 'executeNotificationAction',

'close-modal' => 'dismissRemovePlayer',

];

Change to:

use Livewire\Attributes\On;

#[On('reset-changes')]

public function cancelAddPlayer()

{

$this->closeAddPlayerModal();

}

#[On('removePlayer')]

public function removePlayer() { / existing code / }

#[On('executeNotificationAction')]

public function executeNotificationAction($action) { / existing code / }

#[On('close-modal')]

public function dismissRemovePlayer() { / existing code / }


3. app/Livewire/Team/Show.php

Find and migrate:

// Add import at top

use Livewire\Attributes\On;

// Replace $listeners with #[On()] attributes on each method


4. app/Livewire/Stats/Show.php

Find and migrate similarly.


5. app/Livewire/NotificationManager.php

Current listeners need migration.


6. app/Livewire/Scrims/CreatePosting.php

Current listeners need migration.


7. app/Livewire/Scrims/Find.php

Current listeners need migration.


8. app/Livewire/DraftInterface.php

Current listeners need migration.


9. app/Livewire/Games/Show.php

Current listeners need migration.


10. app/Livewire/Comps/BansKanban.php

Current listeners need migration.


11. app/Livewire/Comps/ChampionsKanban.php

Current listeners need migration.


12. app/Livewire/Comps/Bans.php

Current listeners need migration.


13. app/Livewire/Comps/Create.php

Current listeners need migration.


Part 2: Loading States Enhancements

High Priority Files

resources/views/livewire/games/fetch-game.blade.php

Enhancements:

1. Add delay to prevent flash on fast responses:

{{-- Before --}}

{{-- After --}}

2. Use wire:loading.flex for flex containers:

{{-- Before --}}

{{-- After --}}


resources/views/livewire/roster/show.blade.php

51 loading state instances to review.

Key improvements:

1. Add delays to button loading states

2. Consolidate duplicate loading patterns

3. Use skeleton loaders for content areas

Example:

{{-- Current pattern --}}

{{-- Enhanced pattern --}}


resources/views/livewire/dashboard/podcast-widget.blade.php

11 loading states to enhance.

Add transitions for smoother state changes:

{{-- Enhanced with transitions --}}

Generate

Starting...


Part 3: Transition Migration (x-transition → wire:transition)

resources/views/livewire/persistent-podcast-player.blade.php

12 x-transition usages to review.

For Livewire-controlled visibility:

{{-- If controlled by @if/$showPlayer --}}

@if($showPlayer)

@endif

For Alpine-controlled visibility (keep x-transition):

{{-- If controlled by x-show/Alpine state --}}


resources/views/components/trial-expiration-banner.blade.php

6 x-transition usages.

Review and migrate where appropriate.


resources/views/components/subscription-expired-banner.blade.php

6 x-transition usages.

Review and migrate where appropriate.


Part 4: Islands Implementation

Dashboard Page

File: resources/views/livewire/dashboard.blade.php (or parent layout)

{{-- Main Content --}}

@island

@endisland

@island

@endisland

@island

@endisland

@island

@endisland

{{-- Sidebar --}}

@island

@endisland

@island

@endisland

@island

@endisland

@island

@endisland


Surge Hub Page

File: resources/views/livewire/surge/hub.blade.php

{{-- AI Briefing --}}

@island

@endisland

{{-- Performance Section --}}

@island

@endisland

@island

@endisland

{{-- Strategic Intel --}}

@island

@endisland

{{-- Weekly Podcast --}}

@island

@endisland

{{-- Player Highlights --}}

@island

@endisland


Part 5: Lazy Loading Implementation

Heavy Components to Lazy Load

{{-- Dashboard - Performance Insights (AI-heavy) --}}

{{-- Surge - AI Briefing --}}

{{-- Game Timeline (complex) --}}

Loading timeline...


Part 6: Form Objects (New Feature)

Create Form Classes

app/Livewire/Forms/RiotIdForm.php

namespace App\Livewire\Forms;

use Livewire\Form;

class RiotIdForm extends Form

{

public string $riot_id = '';

public string $role = '';

public function rules(): array

{

return [

'riot_id' => ['required', 'string', 'regex:/^.+#.+$/'],

'role' => ['required', 'in:top,jungle,mid,adc,support'],

];

}

public function messages(): array

{

return [

'riot_id.regex' => 'Please enter a valid Riot ID (e.g., Faker#KR1)',

'role.required' => 'Please select a role',

];

}

public function parseRiotId(): array

{

$parts = explode('#', $this->riot_id);

$tag = array_pop($parts);

$name = implode('#', $parts);

return [

'summoner_name' => trim($name),

'tag_line' => trim($tag),

];

}

}

Usage in Roster/Show.php

use App\Livewire\Forms\RiotIdForm;

class Show extends Component

{

public RiotIdForm $playerForm;

public function addNewPlayer()

{

$this->playerForm->validate();

$parsed = $this->playerForm->parseRiotId();

// Use $parsed['summoner_name'] and $parsed['tag_line']

}

}


Part 7: Wire Navigate Enhancements

{{-- Prefetch on hover for instant navigation --}}

View Profile

{{-- Main navigation with prefetch --}}


Migration Commands

Step 1: Update dependency

composer require livewire/livewire:^4.0

Step 2: Clear caches

php artisan view:clear

php artisan cache:clear

Step 3: Run tests

php artisan test

Step 4: Run Pint

vendor/bin/pint --dirty

Step 5: Check for deprecation warnings in logs

tail -f storage/logs/laravel.log

grep -i "livewire\

deprecated"


Testing Checklist

After migration, test these critical flows:

  • [ ] Dashboard loads all widgets
  • [ ] Roster add/edit/remove player
  • [ ] Scrim creation flow
  • [ ] Draft lobby real-time updates
  • [ ] Podcast generation
  • [ ] Game fetching
  • [ ] Notification system
  • [ ] Team management
  • [ ] Player profiles
  • [ ] Comps CRUD operations

This document should be used in conjunction with livewire-4-upgrade-plan.md

Advertisement