ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto

add actor typeahead <3

+7
package-lock.json
··· 17 17 "@icons-pack/react-simple-icons": "^13.8.0", 18 18 "@neondatabase/serverless": "^1.0.2", 19 19 "@netlify/functions": "^4.2.7", 20 + "actor-typeahead": "^0.1.2", 20 21 "cookie": "^1.0.2", 21 22 "jose": "^6.1.0", 22 23 "jszip": "^3.10.1", ··· 3095 3096 "peerDependencies": { 3096 3097 "acorn": "^8" 3097 3098 } 3099 + }, 3100 + "node_modules/actor-typeahead": { 3101 + "version": "0.1.2", 3102 + "resolved": "https://registry.npmjs.org/actor-typeahead/-/actor-typeahead-0.1.2.tgz", 3103 + "integrity": "sha512-I97YqqNl7Kar0J/bIJvgY/KmHpssHcDElhfwVTLP7wRFlkxso2ZLBqiS2zol5A8UVUJbQK2JXYaqNpZXz8Uk2A==", 3104 + "license": "MPL-2.0" 3098 3105 }, 3099 3106 "node_modules/agent-base": { 3100 3107 "version": "7.1.4",
+1
package.json
··· 21 21 "@icons-pack/react-simple-icons": "^13.8.0", 22 22 "@neondatabase/serverless": "^1.0.2", 23 23 "@netlify/functions": "^4.2.7", 24 + "actor-typeahead": "^0.1.2", 24 25 "cookie": "^1.0.2", 25 26 "jose": "^6.1.0", 26 27 "jszip": "^3.10.1",
+19
src/index.css
··· 144 144 ); 145 145 animation: svg-glow-right 3s ease-in-out infinite 0.5s; /* offset timing */ 146 146 } 147 + 148 + /* Actor typeahead */ 149 + actor-typeahead { 150 + --color-background: rgb(249 250 251 / 1); 151 + --color-border: rgb(6 182 212 / 0.5); 152 + --color-shadow: rgb(88 28 135); 153 + --color-hover: rgb(6 182 212 / 0.1); 154 + --color-avatar-fallback: rgb(6 182 212 / 0.2); 155 + --radius: 0.75rem; 156 + --padding-menu: 0.5rem; 157 + } 158 + 159 + .dark actor-typeahead { 160 + --color-background: rgb(15 23 42 / 1); 161 + --color-border: rgb(126 34 206 / 0.3); 162 + --color-shadow: rgb(0 0 0); 163 + --color-hover: rgb(126 34 206 / 0.2); 164 + --color-avatar-fallback: rgb(126 34 206 / 0.2); 165 + }
+23 -20
src/pages/Login.tsx
··· 1 - import { useState } from "react"; 1 + import { useState, useRef } from "react"; 2 + import "actor-typeahead"; 2 3 import { Heart, Upload, Search, ArrowRight } from "lucide-react"; 3 4 import FireflyLogo from "../assets/at-firefly-logo.svg?react"; 4 5 ··· 16 17 reducedMotion = false, 17 18 }: LoginPageProps) { 18 19 const [handle, setHandle] = useState(""); 20 + const inputRef = useRef<HTMLInputElement>(null); 19 21 20 22 const handleSubmit = (e: React.FormEvent) => { 21 23 e.preventDefault(); 22 - onSubmit(handle); 24 + // Get the value directly from the input instead of state 25 + const currentHandle = inputRef.current?.value || handle; 26 + onSubmit(currentHandle); 23 27 }; 24 28 25 29 return ( ··· 108 112 > 109 113 Your ATmosphere Handle 110 114 </label> 111 - <input 112 - id="atproto-handle" 113 - type="text" 114 - value={handle} 115 - onChange={(e) => setHandle(e.target.value)} 116 - placeholder="yourname.bsky.social" 117 - className="w-full px-4 py-3 bg-purple-50/50 dark:bg-slate-900/50 border-2 border-cyan-500/50 dark:border-purple-500/30 rounded-xl text-purple-900 dark:text-cyan-100 placeholder-purple-750/80 dark:placeholder-cyan-250/80 focus:outline-none focus:ring-2 focus:ring-orange-500 dark:focus:ring-amber-400 focus:border-transparent transition-all" 118 - aria-required="true" 119 - aria-describedby="handle-description" 120 - /> 121 - {/*<p 122 - id="handle-description" 123 - className="text-xs text-slate-600 dark:text-slate-400 mt-2" 124 - > 125 - Enter your full ATmosphere handle (e.g., 126 - username.bsky.social or yourname.com) 127 - </p>*/} 115 + <actor-typeahead rows={5}> 116 + <input 117 + ref={inputRef} 118 + id="atproto-handle" 119 + type="text" 120 + defaultValue={handle} 121 + onInput={(e) => 122 + setHandle((e.target as HTMLInputElement).value) 123 + } 124 + placeholder="yourname.bsky.social" 125 + className="w-full px-4 py-3 bg-purple-50/50 dark:bg-slate-900/50 border-2 border-cyan-500/50 dark:border-purple-500/30 rounded-xl text-purple-900 dark:text-cyan-100 placeholder-purple-750/80 dark:placeholder-cyan-250/80 focus:outline-none focus:ring-2 focus:ring-orange-500 dark:focus:ring-amber-400 focus:border-transparent transition-all" 126 + aria-required="true" 127 + aria-describedby="handle-description" 128 + /> 129 + </actor-typeahead> 128 130 </div> 129 131 130 132 <button ··· 155 157 Secure OAuth Connection 156 158 </p> 157 159 <p className="text-xs mt-1"> 158 - We use official AT Protocol OAuth. We never see your 160 + We use official AT Protocol OAuth. You will be directed 161 + to your account to authorize access. We never see your 159 162 password and you can revoke access anytime. 160 163 </p> 161 164 </div>
+19
src/types/actor-typeahead.d.ts
··· 1 + import "react"; 2 + 3 + // uses npm install actor-typeahead 4 + // from https://tangled.org/jakelazaroff.com/actor-typeahead <3 5 + 6 + declare module "react" { 7 + namespace JSX { 8 + interface IntrinsicElements { 9 + "actor-typeahead": React.DetailedHTMLProps< 10 + { 11 + host?: string; 12 + rows?: number; 13 + children?: React.ReactNode; 14 + }, 15 + HTMLElement 16 + >; 17 + } 18 + } 19 + }