1
1
<script setup lang="ts">
2
2
import hexRgb from ' hex-rgb'
3
3
4
- const { data : clusters, refresh, status } = useFetch (' /api/clusters/nuxt/nuxt' )
4
+ const { data : clusters, refresh, status } = useFetch (' /api/clusters/nuxt/nuxt' , {
5
+ server: false ,
6
+ immediate: import .meta .client && ! (' startViewTransition' in document ),
7
+ default : () => [],
8
+ })
9
+
10
+ onMounted (async () => {
11
+ if (' startViewTransition' in document ) {
12
+ document .startViewTransition (() => refresh ())
13
+ }
14
+ })
5
15
6
16
function labelColors(color : string ) {
7
17
const value = hexRgb (color )
@@ -38,7 +48,7 @@ async function updateSearch() {}
38
48
nuxt/nuxt
39
49
<button
40
50
class =" rounded-full w-7 h-7 flex place-items-center border-solid border border-gray-700 bg-transparent color-gray-400 py-2 hover:color-gray-200 active:color-white focus:color-gray-200 hover:border-gray-400 active:border-white focus:border-gray-400 transition-colors"
41
- :class =" { 'animate-spin opacity-50 pointer-events-none': status === 'pending' }"
51
+ :class =" { 'animate-spin opacity-50 pointer-events-none': status === 'pending' || status === 'idle' }"
42
52
@click =" () => refresh()"
43
53
>
44
54
<Icon
@@ -74,68 +84,97 @@ async function updateSearch() {}
74
84
name =" tabler-search"
75
85
/>
76
86
</form >
77
- <section
78
- v-for =" (cluster, c) of clusters"
79
- :key =" c"
80
- class =" flex flex-col gap-4 md:rounded-md md:border-solid border border-gray-700 md:px-4 pb-8 mt-6 columns-1 lg:columns-2 border-b-solid"
81
- >
82
- <h2 >
83
- <span class =" text-gray-500 inline-block mr-1 font-normal" >#</span >{{ c + 1 }}
84
- </h2 >
85
- <article
86
- v-for =" (issue, i) of openState[c] !== true ? cluster.slice(0, 5) : cluster"
87
+ <template v-if =" status === ' idle' " >
88
+ <section
89
+ v-for =" i in 7"
87
90
:key =" i"
91
+ :style =" { '--section-index': i }"
92
+ class =" flex flex-col gap-4 md:rounded-md md:border-solid border border-gray-700 md:px-4 pb-8 mt-6 columns-1 lg:columns-2 border-b-solid animate-pulse"
88
93
>
89
- <NuxtLink
90
- class =" flex flex-row gap-2 leading-tightest no-underline color-current"
91
- :href =" issue.html_url"
94
+ <h2 class =" flex items-center" >
95
+ <span class =" text-gray-500 inline-block mr-1 font-normal" >#</span >
96
+ <span class =" inline-block rounded-md h-5 bg-gray-500 w-5" />
97
+ </h2 >
98
+ <article >
99
+ <div
100
+ class =" flex flex-row gap-2 leading-tightest no-underline color-current"
101
+ >
102
+ <Icon
103
+ size =" large"
104
+ class =" flex-shrink-0"
105
+ :class =" 'text-gray-500'"
106
+ :name =" 'tabler-circle-dot'"
107
+ />
108
+ <div class =" rounded-full h-4 bg-gray-500 w-70" />
109
+ </div >
110
+ </article >
111
+ </section >
112
+ </template >
113
+ <template v-else >
114
+ <section
115
+ v-for =" (cluster, c) of clusters"
116
+ :key =" c"
117
+ :style =" { '--section-index': c }"
118
+ class =" flex flex-col gap-4 md:rounded-md md:border-solid border border-gray-700 md:px-4 pb-8 mt-6 columns-1 lg:columns-2 border-b-solid"
119
+ >
120
+ <h2 >
121
+ <span class =" text-gray-500 inline-block mr-1 font-normal" >#</span >{{ c + 1 }}
122
+ </h2 >
123
+ <article
124
+ v-for =" (issue, i) of openState[c] !== true ? cluster.slice(0, 5) : cluster"
125
+ :key =" i"
92
126
>
93
- <Icon
94
- size =" large"
95
- class =" flex-shrink-0"
96
- :class =" stateColors[issue.state] || 'text-gray-800'"
97
- :name =" issue.pull_request ? 'tabler-git-pull-request' : issue.state === 'closed' ? 'tabler-circle-check' : 'tabler-circle-dot'"
98
- />
99
- <div class =" flex flex-row gap-2 flex-wrap md:flex-nowrap md:pb-6 flex-grow" >
100
- <span class =" line-clamp-1 flex-grow text-sm md:text-base lg:flex-grow-0" >
101
- {{ issue.title }}
102
- </span >
103
- <span
104
- class =" text-xs relative md:absolute md:mt-6 text-gray-400 mb-1"
105
- >
106
- <span
107
- v-if =" issue.repository"
108
- >
109
- {{ issue.repository?.owner.name }}/{{ issue.repository.name }}
127
+ <NuxtLink
128
+ class =" flex flex-row gap-2 leading-tightest no-underline color-current"
129
+ :href =" issue.html_url"
130
+ >
131
+ <Icon
132
+ size =" large"
133
+ class =" flex-shrink-0"
134
+ :class =" stateColors[issue.state] || 'text-gray-800'"
135
+ :name =" issue.pull_request ? 'tabler-git-pull-request' : issue.state === 'closed' ? 'tabler-circle-check' : 'tabler-circle-dot'"
136
+ />
137
+ <div class =" flex flex-row gap-2 flex-wrap md:flex-nowrap md:pb-6 flex-grow" >
138
+ <span class =" line-clamp-1 flex-grow text-sm md:text-base lg:flex-grow-0" >
139
+ {{ issue.title }}
110
140
</span >
111
- · ;
112
- updated
113
- <NuxtTime
114
- :datetime =" issue.updated_at"
115
- relative
116
- />
117
- </span >
118
- <div class =" flex flex-row gap-1 items-baseline flex-wrap md:flex-nowrap" >
119
141
<span
120
- v-for =" (label, j) of issue.labels"
121
- :key =" j"
122
- class =" label bg-gray-200 text-gray-800 rounded-full px-2 py-0.5 whitespace-pre border-solid border-1 text-xs inline-block leading-tight"
123
- :style =" labelColors(typeof label === 'string' ? '000000' : label.color || '000000')"
142
+ class =" text-xs relative md:absolute md:mt-6 text-gray-400 mb-1"
124
143
>
125
- {{ typeof label === 'string' ? label : label.name }}
144
+ <span
145
+ v-if =" issue.repository"
146
+ >
147
+ {{ issue.repository?.owner.name }}/{{ issue.repository.name }}
148
+ </span >
149
+ · ;
150
+ updated
151
+ <NuxtTime
152
+ :datetime =" issue.updated_at"
153
+ relative
154
+ />
126
155
</span >
156
+ <div class =" flex flex-row gap-1 items-baseline flex-wrap md:flex-nowrap" >
157
+ <span
158
+ v-for =" (label, j) of issue.labels"
159
+ :key =" j"
160
+ class =" label bg-gray-200 text-gray-800 rounded-full px-2 py-0.5 whitespace-pre border-solid border-1 text-xs inline-block leading-tight"
161
+ :style =" labelColors(typeof label === 'string' ? '000000' : label.color || '000000')"
162
+ >
163
+ {{ typeof label === 'string' ? label : label.name }}
164
+ </span >
165
+ </div >
127
166
</div >
128
- </div >
129
- </NuxtLink >
130
- </ article >
131
- < button
132
- v-if = " cluster.length > 5 && openState[c] !== true "
133
- class = " rounded-md border-solid border border-gray-700 bg-transparent color-gray-400 py-2 hover:color-gray-200 active:color-white focus:color-gray-200 hover:border-gray-400 active:border-white focus:border-gray-400 transition-colors "
134
- @click = " openState[c] = !openState[c] "
135
- >
136
- show {{ cluster.length - 5 }} more
137
- </button >
138
- </section >
167
+ </NuxtLink >
168
+ </article >
169
+ < button
170
+ v-if = " cluster.length > 5 && openState[c] !== true "
171
+ class = " rounded-md border-solid border border-gray-700 bg-transparent color-gray-400 py-2 hover:color-gray-200 active:color-white focus:color-gray-200 hover:border-gray-400 active:border-white focus:border-gray-400 transition-colors "
172
+ @click = " openState[c] = !openState[c] "
173
+ >
174
+ show {{ cluster.length - 5 }} more
175
+ </ button >
176
+ </section >
177
+ </template >
139
178
</main >
140
179
<footer class =" font-sans mt-auto p-2 text-center text-sm opacity-75 hover:opacity-100" >
141
180
<!-- <a
@@ -160,6 +199,9 @@ async function updateSearch() {}
160
199
color : white ;
161
200
border-color : rgba (var (--label-r ), var (--label-g ), var (--label-b ), 0.7 );
162
201
}
202
+ section :first-of-type {
203
+ view-transition-name : var (--section-index );
204
+ }
163
205
</style >
164
206
165
207
<style >
0 commit comments