Skip to content

Commit b2ccbe3

Browse files
committed
chore: add loading spinner with Alpine.js state management for improved post render experience
1 parent 97b2f2c commit b2ccbe3

1 file changed

Lines changed: 129 additions & 112 deletions

File tree

resources/views/pages/posts/⚡show.blade.php

Lines changed: 129 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,15 @@ public function render()
7979
@script
8080
<script>
8181
Alpine.data('postsShowPage', () => ({
82+
isReady: false,
8283
async init() {
8384
setupPostOutline(this.$refs.postOutline, this.$refs.postBody);
8485
await highlightAllInElement(this.$refs.postBody);
8586
codeBlockHelper(this.$refs.postBody);
8687
imageBlockHelper(this.$refs.postBody);
8788
processYoutubeOembeds();
8889
processTwitterOembeds(this.$refs.postBody);
90+
this.isReady = true;
8991
setupProgressBar(this.$refs.postCard, this.$refs.progressBar);
9092
setupScrollToTopButton(this.$refs.scrollToTopBtn);
9193
setupSharer();
@@ -115,130 +117,145 @@ class="flex sticky top-1/2 flex-col -translate-y-1/2"
115117
</div>
116118

117119
<div class="flex flex-col justify-start items-center px-2 w-full max-w-3xl xl:px-0">
118-
{{-- mobile menu --}}
119-
@if (auth()->id() === $post->user_id)
120-
<livewire:posts.mobile-menu :post-id="$post->id" />
121-
@endif
120+
{{-- loading spinner --}}
121+
<div
122+
class="flex justify-center items-center py-20"
123+
x-show="!isReady"
124+
x-cloak
125+
>
126+
<x-icons.animate-spin class="text-emerald-500 size-8 dark:text-lividus-500" />
127+
</div>
122128

123-
<x-card
129+
<div
124130
class="w-full"
125-
x-ref="postCard"
131+
x-show="isReady"
132+
x-cloak
126133
>
127-
<article>
128-
{{-- post title --}}
129-
<h1
130-
class="py-6 px-4 -mx-4 -mt-4 text-2xl font-semibold leading-relaxed text-emerald-600 to-transparent rounded-t-xl md:text-4xl bg-linear-to-r from-emerald-100/60 dark:text-lividus-500 dark:from-lividus-800/60"
131-
>
132-
{{ $post->title }}
133-
</h1>
134-
135-
{{-- post thumbnail --}}
136-
@if (!empty($post->preview_url))
137-
<div
138-
class="-mx-4"
139-
id="post-thumbnail"
134+
{{-- mobile menu --}}
135+
@if (auth()->id() === $post->user_id)
136+
<livewire:posts.mobile-menu :post-id="$post->id" />
137+
@endif
138+
139+
<x-card
140+
class="w-full"
141+
x-ref="postCard"
142+
>
143+
<article>
144+
{{-- post title --}}
145+
<h1
146+
class="py-6 px-4 -mx-4 -mt-4 text-2xl font-semibold leading-relaxed text-emerald-600 to-transparent rounded-t-xl md:text-4xl bg-linear-to-r from-emerald-100/60 dark:text-lividus-500 dark:from-lividus-800/60"
140147
>
141-
<img
142-
class="w-full"
143-
src="{{ $post->preview_url }}"
144-
alt="{{ $post->title }}"
148+
{{ $post->title }}
149+
</h1>
150+
151+
{{-- post thumbnail --}}
152+
@if (!empty($post->preview_url))
153+
<div
154+
class="-mx-4"
155+
id="post-thumbnail"
145156
>
157+
<img
158+
class="w-full"
159+
src="{{ $post->preview_url }}"
160+
alt="{{ $post->title }}"
161+
>
162+
</div>
163+
@endif
164+
165+
{{-- post information --}}
166+
<div class="flex items-center mt-4 space-x-2 text-base text-neutral-400">
167+
{{-- classfication --}}
168+
<div class="flex items-center">
169+
<div class="size-4">{!! $post->category->icon !!}</div>
170+
171+
<span class="ml-2">{{ $post->category->name }}</span>
172+
</div>
173+
174+
<div class="hidden md:block">&bull;</div>
175+
176+
{{-- post created time --}}
177+
<div class="hidden items-center md:flex">
178+
<x-icons.calendar-week-fill class="w-4" />
179+
<time
180+
class="ml-2"
181+
datetime="{{ $post->created_at->toDateString() }}"
182+
>{{ $post->created_at->toDateString() }}</time>
183+
184+
@if ($post->created_at->toDateString() !== $post->updated_at->toDateString())
185+
<time datetime="{{ $post->updated_at->toDateString() }}">
186+
{{ '(最後更新於 ' . $post->updated_at->toDateString() . ')' }}
187+
</time>
188+
@endif
189+
</div>
190+
191+
<div class="hidden md:block">&bull;</div>
192+
193+
<div class="hidden items-center md:flex">
194+
<x-icons.book-half class="w-4" />
195+
196+
<span class="ml-2">{{ $this->readTime }} 分鐘</span>
197+
</div>
198+
199+
<div class="hidden md:block">&bull;</div>
200+
201+
{{-- comments count --}}
202+
<div class="hidden md:flex md:items-center">
203+
<x-icons.chat-square-text class="w-4" />
204+
<span class="ml-2">{{ $post->comments_count }}</span>
205+
</div>
146206
</div>
147-
@endif
148-
149-
{{-- post information --}}
150-
<div class="flex items-center mt-4 space-x-2 text-base text-neutral-400">
151-
{{-- classfication --}}
152-
<div class="flex items-center">
153-
<div class="size-4">{!! $post->category->icon !!}</div>
154207

155-
<span class="ml-2">{{ $post->category->name }}</span>
156-
</div>
208+
{{-- post tags --}}
209+
@if ($post->tags()->exists())
210+
<div class="flex flex-wrap items-center mt-4 text-base">
211+
<x-icons.tags class="mr-1 w-4 text-emerald-200 dark:text-lividus-700" />
157212

158-
<div class="hidden md:block">&bull;</div>
159-
160-
{{-- post created time --}}
161-
<div class="hidden items-center md:flex">
162-
<x-icons.calendar-week-fill class="w-4" />
163-
<time
164-
class="ml-2"
165-
datetime="{{ $post->created_at->toDateString() }}"
166-
>{{ $post->created_at->toDateString() }}</time>
167-
168-
@if ($post->created_at->toDateString() !== $post->updated_at->toDateString())
169-
<time datetime="{{ $post->updated_at->toDateString() }}">
170-
{{ '(最後更新於 ' . $post->updated_at->toDateString() . ')' }}
171-
</time>
172-
@endif
173-
</div>
174-
175-
<div class="hidden md:block">&bull;</div>
176-
177-
<div class="hidden items-center md:flex">
178-
<x-icons.book-half class="w-4" />
179-
180-
<span class="ml-2">{{ $this->readTime }} 分鐘</span>
181-
</div>
213+
@foreach ($post->tags as $tag)
214+
<x-tag :href="route('tags.show', ['id' => $tag->id])">
215+
{{ $tag->name }}
216+
</x-tag>
217+
@endforeach
218+
</div>
219+
@endif
182220

183-
<div class="hidden md:block">&bull;</div>
184-
185-
{{-- comments count --}}
186-
<div class="hidden md:flex md:items-center">
187-
<x-icons.chat-square-text class="w-4" />
188-
<span class="ml-2">{{ $post->comments_count }}</span>
221+
{{-- post body --}}
222+
<div
223+
class="mt-4 rich-text"
224+
x-ref="postBody"
225+
>
226+
{!! $post->body !!}
189227
</div>
228+
</article>
229+
</x-card>
230+
231+
{{-- about author --}}
232+
<x-card class="grid grid-cols-12 gap-4 mt-6 w-full">
233+
<div class="flex col-span-12 justify-start items-center md:col-span-2 md:justify-center">
234+
<img
235+
class="w-20 h-20 rounded-full"
236+
src="{{ $post->user->gravatar_url }}"
237+
alt="{{ $post->user->name }}"
238+
>
190239
</div>
191-
192-
{{-- post tags --}}
193-
@if ($post->tags()->exists())
194-
<div class="flex flex-wrap items-center mt-4 text-base">
195-
<x-icons.tags class="mr-1 w-4 text-emerald-200 dark:text-lividus-700" />
196-
197-
@foreach ($post->tags as $tag)
198-
<x-tag :href="route('tags.show', ['id' => $tag->id])">
199-
{{ $tag->name }}
200-
</x-tag>
201-
@endforeach
202-
</div>
203-
@endif
204-
205-
{{-- post body --}}
206-
<div
207-
class="mt-4 rich-text"
208-
x-ref="postBody"
209-
>
210-
{!! $post->body !!}
240+
<div class="col-span-12 space-y-2 md:col-span-10">
241+
<div class="uppercase text-zinc-400">written by</div>
242+
<a
243+
class="inline-block text-2xl gradient-underline-grow dark:text-zinc-50"
244+
href="{{ route('users.show', ['id' => $post->user->id]) }}"
245+
wire:navigate
246+
>
247+
{{ $post->user->name }}
248+
</a>
249+
<p class="whitespace-pre-wrap dark:text-zinc-50">{{ $post->user->introduction }}</p>
211250
</div>
212-
</article>
213-
</x-card>
214-
215-
{{-- about author --}}
216-
<x-card class="grid grid-cols-12 gap-4 mt-6 w-full">
217-
<div class="flex col-span-12 justify-start items-center md:col-span-2 md:justify-center">
218-
<img
219-
class="w-20 h-20 rounded-full"
220-
src="{{ $post->user->gravatar_url }}"
221-
alt="{{ $post->user->name }}"
222-
>
223-
</div>
224-
<div class="col-span-12 space-y-2 md:col-span-10">
225-
<div class="uppercase text-zinc-400">written by</div>
226-
<a
227-
class="inline-block text-2xl gradient-underline-grow dark:text-zinc-50"
228-
href="{{ route('users.show', ['id' => $post->user->id]) }}"
229-
wire:navigate
230-
>
231-
{{ $post->user->name }}
232-
</a>
233-
<p class="whitespace-pre-wrap dark:text-zinc-50">{{ $post->user->introduction }}</p>
234-
</div>
235-
</x-card>
236-
237-
<livewire:comments.board
238-
:post-id="$post->id"
239-
:post-user-id="$post->user_id"
240-
:comment-counts="$post->comments_count"
241-
/>
251+
</x-card>
252+
253+
<livewire:comments.board
254+
:post-id="$post->id"
255+
:post-user-id="$post->user_id"
256+
:comment-counts="$post->comments_count"
257+
/>
258+
</div>
242259
</div>
243260

244261
<div class="hidden xl:block xl:w-1/5">

0 commit comments

Comments
 (0)