this repo has no description
10
fork

Configure Feed

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

fix(explore): move main-link arrow from listing card to detail-page hero

Listing card click goes back to /explore/<handle> with no arrow —
visitors land on the detail page first, where they can read the
description, see the Atmosphere services and landing page, then
choose to open the project. The diagonal-arrow button-affordance
now lives on the detail-page hero card itself: when a profile has
mainLink the whole hero becomes <a target="_blank"> and the corner
disc lights up brand-blue on hover. Records without mainLink keep
the hero as a static panel so the layout doesn't visibly downgrade.

Also: replace the homepage explore CTA copy with the shorter
"Browse apps and services in the Atmosphere." line.

Made-with: Cursor

+111 -75
+61 -39
assets/styles.css
··· 1906 1906 transform: translateY(-2px); 1907 1907 box-shadow: 0 12px 32px rgba(48, 70, 128, 0.12); 1908 1908 } 1909 - /** 1910 - * Card-as-button affordance: anchor the arrow in the top-right corner 1911 - * (relative to the card) so it sits clear of the avatar/title row but 1912 - * doesn't obstruct content. The arrow inherits text colour and fades 1913 - * up to full opacity on hover/focus. Padding-right reserves space so 1914 - * long names don't slide under the arrow. 1915 - */ 1916 - .profile-card-button { 1917 - position: relative; 1918 - padding-right: 2.4rem; 1919 - cursor: pointer; 1920 - } 1921 - .profile-card-arrow { 1922 - position: absolute; 1923 - top: 0.85rem; 1924 - right: 0.85rem; 1925 - display: inline-flex; 1926 - align-items: center; 1927 - justify-content: center; 1928 - width: 1.4rem; 1929 - height: 1.4rem; 1930 - color: rgba(18, 26, 47, 0.45); 1931 - opacity: 0.85; 1932 - transition: transform 0.15s ease, opacity 0.15s ease, color 0.15s ease; 1933 - pointer-events: none; 1934 - } 1935 - .profile-card-button:hover .profile-card-arrow, 1936 - .profile-card-button:focus-visible .profile-card-arrow { 1937 - transform: translate(2px, -2px); 1938 - opacity: 1; 1939 - color: #254a9e; 1940 - } 1941 - .dark-phase .profile-card-arrow { 1942 - color: rgba(255, 255, 255, 0.55); 1943 - } 1944 - .dark-phase .profile-card-button:hover .profile-card-arrow, 1945 - .dark-phase .profile-card-button:focus-visible .profile-card-arrow { 1946 - color: #c8d3ff; 1947 - } 1948 1909 .profile-card-avatar { 1949 1910 flex: 0 0 56px; 1950 1911 width: 56px; ··· 2061 2022 flex-wrap: wrap; 2062 2023 padding: 1.5rem; 2063 2024 border-radius: 24px; 2025 + } 2026 + /** 2027 + * When the project has a `mainLink`, the hero is rendered as an 2028 + * anchor — visitors can tap anywhere on the panel to jump straight 2029 + * to the project. The diagonal arrow in the top-right corner sits 2030 + * in a soft glass disc so it reads as a real button affordance, and 2031 + * the whole hero lifts a touch on hover the same way the listing 2032 + * cards do. Padding-right reserves space so long names don't slide 2033 + * under the disc. 2034 + */ 2035 + a.profile-hero { 2036 + text-decoration: none; 2037 + color: inherit; 2038 + } 2039 + .profile-hero-button { 2040 + position: relative; 2041 + padding-right: 3.4rem; 2042 + cursor: pointer; 2043 + transition: transform 0.18s ease, box-shadow 0.18s ease; 2044 + } 2045 + .profile-hero-button:hover, 2046 + .profile-hero-button:focus-visible { 2047 + transform: translateY(-2px); 2048 + box-shadow: 0 14px 36px rgba(48, 70, 128, 0.14); 2049 + } 2050 + .profile-hero-arrow { 2051 + position: absolute; 2052 + top: 1rem; 2053 + right: 1rem; 2054 + display: inline-flex; 2055 + align-items: center; 2056 + justify-content: center; 2057 + width: 2.1rem; 2058 + height: 2.1rem; 2059 + border-radius: 999px; 2060 + background: rgba(255, 255, 255, 0.6); 2061 + border: 1px solid rgba(37, 74, 158, 0.2); 2062 + color: #254a9e; 2063 + box-shadow: 0 2px 6px rgba(48, 70, 128, 0.1); 2064 + transition: transform 0.18s ease, background 0.18s ease, 2065 + box-shadow 0.18s ease, color 0.18s ease, border-color 0.18s ease; 2066 + pointer-events: none; 2067 + } 2068 + .profile-hero-button:hover .profile-hero-arrow, 2069 + .profile-hero-button:focus-visible .profile-hero-arrow { 2070 + transform: translate(3px, -3px); 2071 + background: #254a9e; 2072 + border-color: #254a9e; 2073 + color: #ffffff; 2074 + box-shadow: 0 6px 16px rgba(37, 74, 158, 0.32); 2075 + } 2076 + .dark-phase .profile-hero-arrow { 2077 + background: rgba(255, 255, 255, 0.12); 2078 + border-color: rgba(200, 211, 255, 0.32); 2079 + color: #c8d3ff; 2080 + } 2081 + .dark-phase .profile-hero-button:hover .profile-hero-arrow, 2082 + .dark-phase .profile-hero-button:focus-visible .profile-hero-arrow { 2083 + background: #c8d3ff; 2084 + border-color: #c8d3ff; 2085 + color: #0e1428; 2064 2086 } 2065 2087 .profile-hero-avatar { 2066 2088 width: 120px;
+6 -31
components/explore/ProfileCard.tsx
··· 6 6 } 7 7 8 8 /** 9 - * The profile card is the primary surface of /explore. The whole card 10 - * is clickable and lands the visitor on the project's `mainLink` (the 11 - * actual app/service/page) — a small top-right arrow signals the 12 - * external destination. Legacy records that pre-date `mainLink` fall 13 - * back to the local /explore/<handle> detail page so the card never 14 - * 404s, just degrades gracefully. 9 + * Listing-grid card. Clicking the card opens the project's profile 10 + * detail page (/explore/<handle>) — visitors get the description, 11 + * Atmosphere services, landing page, etc. on the detail page, where 12 + * the hero card is what actually links out to mainLink. 15 13 */ 16 14 export default function ProfileCard({ profile }: Props) { 17 15 const t = useT(); ··· 19 17 const cats = profile.categories.slice(0, 3); 20 18 const featured = profile.featured; 21 19 22 - const isExternal = !!profile.mainLink; 23 - const href = profile.mainLink ?? 24 - `/explore/${encodeURIComponent(profile.handle)}`; 25 - 26 20 return ( 27 21 <a 28 - href={href} 29 - class="glass profile-card profile-card-button" 30 - {...(isExternal 31 - ? { target: "_blank", rel: "noopener noreferrer external" } 32 - : {})} 22 + href={`/explore/${encodeURIComponent(profile.handle)}`} 23 + class="glass profile-card" 33 24 > 34 - <span class="profile-card-arrow" aria-hidden="true"> 35 - <svg 36 - width="18" 37 - height="18" 38 - viewBox="0 0 24 24" 39 - fill="none" 40 - stroke="currentColor" 41 - stroke-width="2" 42 - stroke-linecap="round" 43 - stroke-linejoin="round" 44 - > 45 - <line x1="7" y1="17" x2="17" y2="7"></line> 46 - <polyline points="9 7 17 7 17 15"></polyline> 47 - </svg> 48 - </span> 49 - 50 25 <div class="profile-card-avatar"> 51 26 {profile.avatarCid 52 27 ? (
+43 -3
components/explore/ProfileHero.tsx
··· 5 5 profile: ProfileRow; 6 6 } 7 7 8 + /** 9 + * Profile detail hero. When the project has a `mainLink` (the actual 10 + * app/service URL), the whole hero becomes a button that opens that 11 + * destination in a new tab — the diagonal arrow in the top-right 12 + * corner is the affordance. Records without a mainLink (legacy or 13 + * deliberately empty) render the same content as a static panel so 14 + * the page still reads correctly. 15 + */ 8 16 export default function ProfileHero({ profile }: Props) { 9 17 const t = useT(); 10 18 const tCat = t.categories as Record<string, string>; ··· 12 20 const tBadges = t.badges; 13 21 const featured = profile.featured; 14 22 const cats = profile.categories; 23 + const hasMainLink = !!profile.mainLink; 15 24 16 - return ( 17 - <div class="profile-hero glass"> 25 + const inner = ( 26 + <> 27 + {hasMainLink && ( 28 + <span class="profile-hero-arrow" aria-hidden="true"> 29 + <svg 30 + width="18" 31 + height="18" 32 + viewBox="0 0 24 24" 33 + fill="none" 34 + stroke="currentColor" 35 + stroke-width="2.4" 36 + stroke-linecap="round" 37 + stroke-linejoin="round" 38 + > 39 + <line x1="7" y1="17" x2="17" y2="7"></line> 40 + <polyline points="9 7 17 7 17 15"></polyline> 41 + </svg> 42 + </span> 43 + )} 18 44 <div class="profile-hero-avatar"> 19 45 {profile.avatarCid 20 46 ? ( ··· 59 85 </div> 60 86 <p class="profile-hero-description">{profile.description}</p> 61 87 </div> 62 - </div> 88 + </> 63 89 ); 90 + 91 + if (hasMainLink) { 92 + return ( 93 + <a 94 + href={profile.mainLink!} 95 + target="_blank" 96 + rel="noopener noreferrer external" 97 + class="profile-hero glass profile-hero-button" 98 + > 99 + {inner} 100 + </a> 101 + ); 102 + } 103 + return <div class="profile-hero glass">{inner}</div>; 64 104 }
+1 -2
i18n/messages/en.tsx
··· 230 230 231 231 homeCta: { 232 232 headline: "See what's been built.", 233 - body: 234 - "Browse apps, account providers, moderators, and infrastructure — all built on the same open foundation.", 233 + body: "Browse apps and services in the Atmosphere.", 235 234 button: "Explore Apps", 236 235 }, 237 236