@@ -26,12 +26,17 @@ async function getUserProfile(identity: string) {
26
26
}
27
27
28
28
function App ( ) {
29
- const [ search , setSearch ] = useState < string > ( ) ;
29
+ const [ isLoading , setIsLoading ] = useState < boolean > ( true ) ;
30
+ const [ search , setSearch ] = useState < string > ( 'tsky.dev' ) ;
30
31
const [ user , setUser ] = useState < ActorProfile > ( ) ;
31
32
32
33
useEffect ( ( ) => {
33
34
if ( search ) {
34
- getUserProfile ( search ) . then ( setUser ) ;
35
+ setIsLoading ( true ) ;
36
+ getUserProfile ( search ) . then ( ( user ) => {
37
+ setUser ( user ) ;
38
+ setIsLoading ( false ) ;
39
+ } ) ;
35
40
}
36
41
} , [ search ] ) ;
37
42
@@ -72,101 +77,115 @@ function App() {
72
77
Search
73
78
</ button >
74
79
</ form >
75
- { user && (
76
- < div className = "w-full rounded-xl ring-1 ring-transparent dark:ring-white/5 overflow-hidden drop-shadow-lg dark:drop-shadow-none" >
77
- < img
78
- src = { user . banner }
79
- alt = "banner"
80
- className = "h-36 w-full object-cover"
81
- />
82
- < div className = "bg-white dark:bg-zinc-900 p-4" >
83
- < div className = "flex items-end justify-between -mt-16" >
84
- < div className = "rounded-full size-28 border-[3px] border-white dark:border-zinc-900 overflow-hidden" >
85
- < img
86
- src = { user . avatar }
87
- alt = "profile-pic"
88
- className = "size-full object-cover"
89
- />
90
- </ div >
91
- < a
92
- href = { `https://bsky.app/profile/${ user . handle } ` }
93
- target = "_blank"
94
- rel = "noreferrer"
95
- className = "rounded-full"
96
- >
97
- < button
98
- type = "button"
99
- className = "whitespace-nowrap cursor-pointer font-semibold h-max transition-all border select-none outline-none px-3 py-2 text-sm flex items-center justify-center rounded-full text-white dark:text-black focus-visible:ring-2 ring-offset-2 ring-offset-white dark:ring-offset-zinc-950 border-transparent bg-blue-500 hover:bg-blue-600 dark:bg-blue-300/90 dark:hover:bg-blue-400/80 ring-blue-300 dark:ring-blue-100"
100
- >
101
- < svg
102
- xmlns = "http://www.w3.org/2000/svg"
103
- fill = "none"
104
- viewBox = "0 0 24 24"
105
- strokeWidth = "3"
106
- stroke = "currentColor"
107
- className = "size-3.5 mr-1"
108
- >
109
- < title > Plus Icon</ title >
110
- < path
111
- strokeLinecap = "round"
112
- strokeLinejoin = "round"
113
- d = "M12 4.5v15m7.5-7.5h-15"
114
- />
115
- </ svg >
116
- Follow
117
- </ button >
118
- </ a >
119
- </ div >
120
- < h1 className = "text-lg font-semibold mt-2" > { user . displayName } </ h1 >
121
- < p className = "text-sm text-zinc-500 dark:text-zinc-400" >
122
- @{ user . handle }
123
- </ p >
124
- < div className = "mt-3 flex items-center gap-3 text-sm font-semibold" >
125
- < p >
126
- { user . followersCount }
127
- < span className = "font-normal text-zinc-500 dark:text-zinc-400" >
128
- { ' ' }
129
- Followers
130
- </ span >
131
- </ p >
132
- < p >
133
- { user . followsCount }
134
- < span className = "font-normal text-zinc-500 dark:text-zinc-400" >
135
- { ' ' }
136
- Following
137
- </ span >
138
- </ p >
139
- </ div >
140
- < p className = "mt-4" > { user . description } </ p >
141
- < div className = "flex items-end justify-between" >
142
- < p className = "text-sm text-zinc-400 dark:text-zinc-500" >
143
- Made with Tsky
144
- </ p >
145
- < a
146
- href = "https://github.com/tsky-dev/tsky"
147
- target = "_blank"
148
- rel = "noreferrer"
149
- >
150
- < svg
151
- xmlns = "http://www.w3.org/2000/svg"
152
- fill = "none"
153
- viewBox = "0 0 320 286"
154
- className = "size-8"
155
- >
156
- < title > Bluesky Icon</ title >
157
- < path
158
- fill = "rgb(10,122,255)"
159
- d = "M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z"
160
- />
161
- </ svg >
162
- </ a >
163
- </ div >
164
- </ div >
165
- </ div >
166
- ) }
80
+ { isLoading ? < LoadingSkeleton /> : user && < UserCard user = { user } /> }
167
81
</ div >
168
82
</ main >
169
83
) ;
170
84
}
171
85
172
86
export default App ;
87
+
88
+ function LoadingSkeleton ( ) {
89
+ return (
90
+ < div className = "max-w-lg mx-auto w-full h-96 animate-pulse rounded-md bg-zinc-400/20" />
91
+ ) ;
92
+ }
93
+
94
+ function UserCard ( { user } : { user : ActorProfile } ) {
95
+ return (
96
+ < div className = "w-full rounded-xl ring-1 ring-transparent dark:ring-white/5 overflow-hidden drop-shadow-lg dark:drop-shadow-none" >
97
+ { user . banner ? (
98
+ < img
99
+ src = { user . banner }
100
+ alt = "banner"
101
+ className = "h-36 w-full object-cover"
102
+ />
103
+ ) : (
104
+ < div className = "h-36 w-full bg-blue-500 dark:bg-blue-300" />
105
+ ) }
106
+ < div className = "bg-white dark:bg-zinc-900 p-4" >
107
+ < div className = "flex items-end justify-between -mt-16" >
108
+ < div className = "rounded-full size-28 border-[3px] border-white dark:border-zinc-900 overflow-hidden" >
109
+ < img
110
+ src = { user . avatar }
111
+ alt = "profile-pic"
112
+ className = "size-full object-cover"
113
+ />
114
+ </ div >
115
+ < a
116
+ href = { `https://bsky.app/profile/${ user . handle } ` }
117
+ target = "_blank"
118
+ rel = "noreferrer"
119
+ className = "rounded-full"
120
+ >
121
+ < button
122
+ type = "button"
123
+ className = "whitespace-nowrap cursor-pointer font-semibold h-max transition-all border select-none outline-none px-3 py-2 text-sm flex items-center justify-center rounded-full text-white dark:text-black focus-visible:ring-2 ring-offset-2 ring-offset-white dark:ring-offset-zinc-950 border-transparent bg-blue-500 hover:bg-blue-600 dark:bg-blue-300/90 dark:hover:bg-blue-400/80 ring-blue-300 dark:ring-blue-100"
124
+ >
125
+ < svg
126
+ xmlns = "http://www.w3.org/2000/svg"
127
+ fill = "none"
128
+ viewBox = "0 0 24 24"
129
+ strokeWidth = "3"
130
+ stroke = "currentColor"
131
+ className = "size-3.5 mr-1"
132
+ >
133
+ < title > Plus Icon</ title >
134
+ < path
135
+ strokeLinecap = "round"
136
+ strokeLinejoin = "round"
137
+ d = "M12 4.5v15m7.5-7.5h-15"
138
+ />
139
+ </ svg >
140
+ Follow
141
+ </ button >
142
+ </ a >
143
+ </ div >
144
+ < h1 className = "text-lg font-semibold mt-2" > { user . displayName } </ h1 >
145
+ < p className = "text-sm text-zinc-500 dark:text-zinc-400" >
146
+ @{ user . handle }
147
+ </ p >
148
+ < div className = "mt-3 flex items-center gap-3 text-sm font-semibold" >
149
+ < p >
150
+ { user . followersCount }
151
+ < span className = "font-normal text-zinc-500 dark:text-zinc-400" >
152
+ { ' ' }
153
+ Followers
154
+ </ span >
155
+ </ p >
156
+ < p >
157
+ { user . followsCount }
158
+ < span className = "font-normal text-zinc-500 dark:text-zinc-400" >
159
+ { ' ' }
160
+ Following
161
+ </ span >
162
+ </ p >
163
+ </ div >
164
+ < p className = "mt-4" > { user . description } </ p >
165
+ < div className = "flex items-end justify-between" >
166
+ < p className = "text-sm text-zinc-400 dark:text-zinc-500" >
167
+ Made with Tsky
168
+ </ p >
169
+ < a
170
+ href = "https://github.com/tsky-dev/tsky"
171
+ target = "_blank"
172
+ rel = "noreferrer"
173
+ >
174
+ < svg
175
+ xmlns = "http://www.w3.org/2000/svg"
176
+ fill = "none"
177
+ viewBox = "0 0 320 286"
178
+ className = "size-8"
179
+ >
180
+ < title > Bluesky Icon</ title >
181
+ < path
182
+ fill = "rgb(10,122,255)"
183
+ d = "M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z"
184
+ />
185
+ </ svg >
186
+ </ a >
187
+ </ div >
188
+ </ div >
189
+ </ div >
190
+ ) ;
191
+ }
0 commit comments