Fork of Chiri for Astro for my blog
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 93856307e5f4eeb75dad33c7e3281050e4e8d7b9 455 lines 12 kB view raw
1<div class="tag-card"> 2 <div class="tag-container"> 3 <div id="tag-component" class="tag-component"> 4 <button id="add-button" class="add-button"> 5 <svg class="add-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> 6 <path 7 d="M7.75 2a.75.75 0 0 1 .75.75V7h4.25a.75.75 0 0 1 0 1.5H8.5v4.25a.75.75 0 0 1-1.5 0V8.5H2.75a.75.75 0 0 1 0-1.5H7V2.75A.75.75 0 0 1 7.75 2Z" 8 ></path> 9 </svg> 10 </button> 11 12 <div id="input-state" class="input-state"> 13 <input id="tag-input" type="text" placeholder="Tag Name" class="tag-input" /> 14 <button id="confirm-button" class="confirm-button disabled"> 15 <svg class="confirm-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> 16 <path 17 d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z" 18 ></path> 19 </svg> 20 </button> 21 <button id="cancel-button" class="cancel-button"> 22 <svg class="cancel-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> 23 <path 24 d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z" 25 ></path> 26 </svg> 27 </button> 28 </div> 29 30 <div id="tag-display" class="tag-display"> 31 <span id="tag-text" class="tag-text"></span> 32 <button id="delete-button" class="delete-button"> 33 <svg class="delete-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> 34 <path 35 d="M11 1.75V3h2.25a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1 0-1.5H5V1.75C5 .784 5.784 0 6.75 0h2.5C10.216 0 11 .784 11 1.75ZM4.496 6.675l.66 6.6a.25.25 0 0 0 .249.225h5.19a.25.25 0 0 0 .249-.225l.66-6.6a.75.75 0 0 1 1.492.149l-.66 6.6A1.748 1.748 0 0 1 10.595 15h-5.19a1.75 1.75 0 0 1-1.741-1.575l-.66-6.6a.75.75 0 1 1 1.492-.15ZM6.5 1.75V3h3V1.75a.25.25 0 0 0-.25-.25h-2.5a.25.25 0 0 0-.25.25Z" 36 ></path> 37 </svg> 38 </button> 39 </div> 40 </div> 41 </div> 42</div> 43 44<script is:inline> 45 function setupTag() { 46 let currentState = 'add' // 'add', 'input', 'display' 47 let tagValue = localStorage.getItem('tagValue') || '' 48 49 const addButton = document.getElementById('add-button') 50 const inputState = document.getElementById('input-state') 51 const tagDisplay = document.getElementById('tag-display') 52 const tagInput = document.getElementById('tag-input') 53 const confirmButton = document.getElementById('confirm-button') 54 const cancelButton = document.getElementById('cancel-button') 55 const deleteButton = document.getElementById('delete-button') 56 const tagText = document.getElementById('tag-text') 57 58 if (tagValue) { 59 addButton.classList.add('hidden') 60 inputState.classList.remove('active') 61 tagDisplay.classList.add('active') 62 tagText.textContent = truncateText(tagValue) 63 currentState = 'display' 64 } else { 65 addButton.classList.remove('hidden') 66 inputState.classList.remove('active') 67 tagDisplay.classList.remove('active') 68 tagInput.value = '' 69 currentState = 'add' 70 } 71 72 // Switch to input state 73 function switchToInput() { 74 currentState = 'input' 75 addButton.classList.add('hidden') 76 setTimeout(() => { 77 inputState.classList.add('active') 78 tagInput.focus() 79 }, 100) 80 } 81 82 // Switch to display state 83 function switchToDisplay() { 84 currentState = 'display' 85 inputState.classList.remove('active') 86 setTimeout(() => { 87 tagDisplay.classList.add('active') 88 tagText.textContent = truncateText(tagValue) 89 // Store to localStorage 90 localStorage.setItem('tagValue', tagValue) 91 }, 300) 92 } 93 94 // Return to add state 95 function switchToAdd() { 96 if (currentState === 'display') { 97 tagDisplay.classList.remove('active') 98 } else if (currentState === 'input') { 99 inputState.classList.remove('active') 100 } 101 currentState = 'add' 102 setTimeout(() => { 103 addButton.classList.remove('hidden') 104 tagValue = '' 105 tagInput.value = '' 106 localStorage.removeItem('tagValue') 107 updateConfirmButton() 108 }, 250) 109 } 110 111 // Update confirm button state 112 function updateConfirmButton() { 113 if (tagInput.value.trim()) { 114 confirmButton.classList.remove('disabled') 115 } else { 116 confirmButton.classList.add('disabled') 117 } 118 } 119 120 // Truncate text to max 24 characters 121 function truncateText(text, maxLength = 24) { 122 if (text.length <= maxLength) { 123 return text 124 } 125 return text.substring(0, maxLength) + '...' 126 } 127 128 // Bind events 129 addButton.onclick = switchToInput 130 131 tagInput.oninput = function (e) { 132 const inputValue = e.target.value 133 if (inputValue.length > 24) { 134 e.target.value = inputValue.substring(0, 24) 135 tagValue = inputValue 136 } else { 137 tagValue = inputValue 138 } 139 updateConfirmButton() 140 } 141 142 tagInput.onkeydown = function (e) { 143 if (e.key === 'Enter' && tagValue.trim()) { 144 switchToDisplay() 145 } else if (e.key === 'Escape') { 146 switchToAdd() 147 } 148 } 149 150 confirmButton.onclick = function () { 151 if (tagValue.trim()) { 152 switchToDisplay() 153 } 154 } 155 156 cancelButton.onclick = switchToAdd 157 deleteButton.onclick = switchToAdd 158 } 159 160 setupTag() 161 162 document.addEventListener('astro:page-load', setupTag) 163</script> 164 165<style> 166 .tag-card { 167 border: 1px solid var(--border); 168 width: 100%; 169 height: 12rem; 170 display: flex; 171 align-items: center; 172 justify-content: center; 173 border-radius: 10px; 174 } 175 176 .tag-container { 177 display: flex; 178 justify-content: center; 179 align-items: center; 180 width: 100%; 181 padding: 0 2rem; 182 overflow: hidden; 183 } 184 185 .tag-component { 186 display: flex; 187 align-items: center; 188 justify-content: center; 189 gap: 0.5rem; 190 position: relative; 191 width: 100%; 192 min-height: 40px; 193 } 194 195 .add-button { 196 background-color: var(--text-primary); 197 color: var(--bg); 198 border: none; 199 border-radius: 50%; 200 width: 36px; 201 height: 36px; 202 cursor: pointer; 203 display: flex; 204 align-items: center; 205 justify-content: center; 206 transition: 207 all 0.3s ease, 208 visibility 0s; 209 position: absolute; 210 top: 50%; 211 left: 50%; 212 transform: translate(-50%, -50%) scale(1); 213 z-index: 1; 214 opacity: 1; 215 visibility: visible; 216 overflow: visible; 217 will-change: transform; 218 -webkit-transform: translate(-50%, -50%) scale(1); 219 box-sizing: border-box; 220 padding: 0; 221 margin: 0; 222 } 223 224 .add-button.hidden { 225 opacity: 0; 226 transform: translate(-50%, -50%) scale(0.8); 227 pointer-events: none; 228 visibility: hidden; 229 transition: 230 all 0.3s ease, 231 visibility 0s 0.2s; 232 } 233 234 .add-icon, 235 .confirm-icon, 236 .cancel-icon, 237 .delete-icon { 238 fill: currentColor; 239 width: 1rem; 240 height: 1rem; 241 position: relative; 242 display: block; 243 transform: translateZ(0); 244 } 245 246 .add-button:hover { 247 opacity: 0.8; 248 transform: translate(-50%, -50%) scale(1); 249 -webkit-transform: translate(-50%, -50%) scale(1); 250 } 251 252 .input-state { 253 display: flex; 254 align-items: center; 255 gap: 0.125rem; 256 background-color: var(--astro-code-background); 257 border: 1px solid var(--code-bg); 258 border-radius: 18px; 259 padding: 0.28125rem 0.375rem; 260 width: 40px; 261 max-width: 40px; 262 opacity: 0; 263 overflow: hidden; 264 transition: all 0.3s ease; 265 position: relative; 266 z-index: 2; 267 pointer-events: none; 268 } 269 270 .input-state.active { 271 width: 10rem; 272 max-width: 10rem; 273 opacity: 1; 274 pointer-events: all; 275 } 276 277 .tag-input { 278 background: transparent; 279 border: none; 280 outline: none; 281 color: var(--text-primary); 282 font-size: 0.9rem; 283 font-family: var(--mono); 284 min-width: 4rem; 285 padding: 0.25rem 0.5rem; 286 opacity: 0; 287 transform: translateX(-8px); 288 transition: 289 opacity 0.2s ease 0.15s, 290 transform 0.2s ease 0.15s; 291 } 292 293 .input-state.active .tag-input { 294 opacity: 1; 295 transform: translateX(0); 296 } 297 298 .tag-input::placeholder { 299 color: var(--text-tertiary); 300 } 301 302 .confirm-button, 303 .cancel-button { 304 background: none; 305 border: none; 306 border-radius: 50%; 307 width: 24px; 308 height: 24px; 309 cursor: pointer; 310 display: flex; 311 align-items: center; 312 justify-content: center; 313 font-size: 0.8rem; 314 opacity: 0; 315 transform: scale(0.8); 316 transition: all 0.2s ease; 317 position: relative; 318 min-width: 24px; 319 min-height: 24px; 320 } 321 322 .confirm-button::before, 323 .cancel-button::before { 324 content: ''; 325 position: absolute; 326 top: 50%; 327 left: 50%; 328 transform: translate(-50%, -50%); 329 border-radius: 50%; 330 background-color: var(--code-bg); 331 opacity: 0; 332 transition: opacity 0.2s ease; 333 z-index: -1; 334 width: 28px; 335 height: 28px; 336 } 337 338 .confirm-button:hover::before, 339 .cancel-button:hover::before { 340 opacity: 1; 341 } 342 343 .input-state.active .confirm-button, 344 .input-state.active .cancel-button { 345 transform: scale(1); 346 } 347 348 .confirm-button { 349 color: var(--text-primary); 350 opacity: 0.6; 351 } 352 353 .confirm-button.disabled { 354 opacity: 0.3; 355 cursor: not-allowed; 356 } 357 358 .confirm-button:not(.disabled):hover { 359 opacity: 1; 360 } 361 362 .confirm-button.disabled:hover::before { 363 opacity: 0; 364 } 365 366 .cancel-button { 367 color: var(--text-primary); 368 opacity: 0.6; 369 } 370 371 .cancel-button:hover { 372 opacity: 1; 373 } 374 375 .tag-display { 376 display: flex; 377 align-items: center; 378 gap: 0.25rem; 379 background-color: var(--astro-code-background); 380 border: 1px solid var(--code-bg); 381 border-radius: 18px; 382 padding: 0.28125rem 0.325rem 0.28125rem 0.75rem; 383 position: absolute; 384 top: 50%; 385 left: 50%; 386 transform: translate(-50%, -50%); 387 z-index: 3; 388 opacity: 0; 389 pointer-events: none; 390 transition: all 0.25s ease-out; 391 will-change: transform, opacity; 392 } 393 394 .tag-display > * { 395 margin-right: 0.125rem; 396 } 397 398 .tag-display > *:last-child { 399 margin-right: 0; 400 } 401 402 .tag-display.active { 403 opacity: 1; 404 transform: translate(-50%, -50%); 405 pointer-events: all; 406 } 407 408 .tag-text { 409 color: var(--text-primary); 410 font-size: 0.9rem; 411 font-family: var(--mono); 412 } 413 414 .delete-button { 415 background: none; 416 border: none; 417 border-radius: 50%; 418 width: 24px; 419 height: 24px; 420 cursor: pointer; 421 display: flex; 422 align-items: center; 423 justify-content: center; 424 font-size: 0.8rem; 425 color: var(--text-primary); 426 opacity: 0.6; 427 transition: all 0.2s ease; 428 position: relative; 429 min-width: 24px; 430 min-height: 24px; 431 } 432 433 .delete-button::before { 434 content: ''; 435 position: absolute; 436 top: 50%; 437 left: 50%; 438 transform: translate(-50%, -50%); 439 border-radius: 50%; 440 background-color: var(--code-bg); 441 opacity: 0; 442 transition: opacity 0.2s ease; 443 z-index: -1; 444 width: 28px; 445 height: 28px; 446 } 447 448 .delete-button:hover { 449 opacity: 1; 450 } 451 452 .delete-button:hover::before { 453 opacity: 1; 454 } 455</style>