Attic is a cozy space with lofty ambitions. attic.social
11
fork

Configure Feed

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

bookmark url paste button

+52 -21
+2 -1
src/css/components/button.css
··· 11 11 font-weight: 400; 12 12 inline-size: fit-content; 13 13 line-height: 1; 14 - min-inline-size: var(--block-size); 14 + min-inline-size: var(--min-inline-size, var(--block-size)); 15 15 padding: 0 5px; 16 16 /*text-box: trim-both ex alphabetic;*/ 17 + text-align: center; 17 18 text-decoration: none; 18 19 text-transform: uppercase; 19 20 text-shadow: 2px 2px rgb(var(--color-brown) / 0.3);
+11 -1
src/css/components/form.css
··· 40 40 inline-size: 100%; 41 41 } 42 42 43 - & div:has(input[name="title"]) { 43 + & div:has(input + button) { 44 44 display: grid; 45 45 inline-size: 100%; 46 46 gap: 10px; 47 + 48 + & button { 49 + --min-inline-size: 7ch; 50 + } 51 + 52 + & [type="url"] + button { 53 + &:disabled { 54 + text-decoration: line-through; 55 + } 56 + } 47 57 48 58 @media (width >= 600px) { 49 59 grid-template-columns: 1fr auto;
+39 -19
src/routes/bookmarks/[did=did]/+page.svelte
··· 56 56 let dialogFormRef: HTMLFormElement | null = $state(null); 57 57 let dialogUrlInput: HTMLInputElement | null = $state(null); 58 58 let dialogTitleInput: HTMLInputElement | null = $state(null); 59 + let dialogUrlPaste = $state(true); 59 60 let dialogUrlValid = $state(false); 60 61 let dialogTags: string[] = $state([]); 61 62 let dialogTagInput: HTMLInputElement | null = $state(null); ··· 131 132 } 132 133 }; 133 134 134 - const dateFormat = $derived( 135 - new Intl.DateTimeFormat(data.locale, { 136 - dateStyle: "medium", 137 - timeStyle: "short", 138 - }), 139 - ); 135 + const onPasteURL = async (_ev: MouseEvent) => { 136 + if (dialogUrlInput === null) return; 137 + try { 138 + const text = await navigator.clipboard.readText(); 139 + dialogUrlInput.value = text; 140 + } catch (err) { 141 + dialogUrlPaste = false; 142 + } 143 + }; 140 144 141 145 const onFetchTitle = async (ev: MouseEvent) => { 142 146 if (dialogTitleInput === null) return; ··· 221 225 if (form.error) alert(form.error); 222 226 } 223 227 }); 228 + 229 + const dateFormat = $derived( 230 + new Intl.DateTimeFormat(data.locale, { 231 + dateStyle: "medium", 232 + timeStyle: "short", 233 + }), 234 + ); 224 235 </script> 225 236 226 237 <svelte:head> ··· 340 351 {#if form?.error} 341 352 <p class="error">{form.error}</p> 342 353 {/if} 343 - <label for="url">URL</label> 344 - <input 345 - type="url" 346 - id="url" 347 - name="url" 348 - maxlength="1024" 349 - placeholder="https://..." 350 - bind:this={dialogUrlInput} 351 - oninput={() => 352 - (dialogUrlValid = dialogUrlInput?.checkValidity() ?? false)} 353 - value={dialogEntity?.url} 354 - required 355 - /> 354 + <div> 355 + <label for="url">URL</label> 356 + <input 357 + type="url" 358 + id="url" 359 + name="url" 360 + maxlength="1024" 361 + placeholder="https://..." 362 + bind:this={dialogUrlInput} 363 + oninput={() => 364 + (dialogUrlValid = dialogUrlInput?.checkValidity() ?? false)} 365 + value={dialogEntity?.url} 366 + required 367 + /> 368 + <button 369 + type="button" 370 + onclick={onPasteURL} 371 + disabled={dialogUrlPaste === false} 372 + > 373 + Paste 374 + </button> 375 + </div> 356 376 <div> 357 377 <label for="title">Title</label> 358 378 <input