This repository has no description
0

Configure Feed

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

add definitions page and updated nav

+810 -664
+2
src/App.jsx
··· 8 8 import Home from './components/Home/Home'; 9 9 import Leaderboard from './components/Leaderboard/Leaderboard'; 10 10 import Supporter from './components/Supporter/Supporter'; 11 + import Definitions from './components/Definitions/Definitions'; 11 12 import Shortcut from './components/Shortcut/Shortcut'; 12 13 import Resources from './components/Resources/Resources'; 13 14 import ScoringMethodology from './components/ScoringMethodology/ScoringMethodology'; ··· 37 38 <Route path="/terms" element={<Terms />} /> 38 39 <Route path="/newsletter" element={<Newsletter />} /> 39 40 <Route path="/supporter" element={<Supporter />} /> 41 + <Route path="/definitions" element={<Definitions />} /> 40 42 <Route path="/leaderboard" element={<Leaderboard />} /> 41 43 <Route path="/resources" element={<Resources />} /> 42 44 <Route path="/shortcut" element={<Shortcut />} />
+219
src/components/Definitions/Definitions.css
··· 1 + .definitions-page { 2 + margin: 20px auto 20px; 3 + max-width: 450px; 4 + padding: 20px; 5 + } 6 + 7 + .definitions-page .alt-card { 8 + text-align: left; 9 + } 10 + 11 + .definitions-page ul { 12 + list-style: none; 13 + text-align: center; 14 + margin: 0px auto; 15 + padding: 0px; 16 + width: 100%; 17 + opacity: 0.5; 18 + } 19 + 20 + .definitions-page { 21 + margin: 20px auto 40px; 22 + max-width: 450px; 23 + padding: 20px; 24 + } 25 + 26 + .definitions-page .alt-card { 27 + text-align: left; 28 + } 29 + 30 + .definitions-page h1 { 31 + margin-bottom: 20px; 32 + } 33 + 34 + .definitions-page h2 { 35 + margin-top: 30px; 36 + margin-bottom: 20px; 37 + } 38 + 39 + .definitions-page p { 40 + margin: 15px 0; 41 + line-height: 1.5; 42 + } 43 + 44 + .intro-text { 45 + margin-bottom: 30px; 46 + font-size: 1.1em; 47 + } 48 + 49 + .back-to-methodology { 50 + margin: 20px 0; 51 + } 52 + 53 + .back-to-methodology a { 54 + color: var(--button-bg); 55 + text-decoration: none; 56 + display: inline-block; 57 + transition: all 0.2s ease; 58 + padding: 6px 12px; 59 + border-radius: 4px; 60 + background-color: rgba(59, 154, 248, 0.1); 61 + } 62 + 63 + .back-to-methodology a:hover { 64 + background-color: rgba(59, 154, 248, 0.2); 65 + text-decoration: underline; 66 + } 67 + 68 + .definitions-section { 69 + margin-bottom: 40px; 70 + } 71 + 72 + /* Definition accordion styles */ 73 + .definitions-container { 74 + margin-top: 20px; 75 + overflow: hidden; 76 + } 77 + 78 + .definition-item { 79 + margin-bottom: 10px; 80 + border-radius: 6px; 81 + background-color: var(--navbar-bg); 82 + overflow: hidden; 83 + transition: all 0.3s ease; 84 + border: 1px solid var(--card-border); 85 + } 86 + 87 + .definition-term { 88 + padding: 12px 15px; 89 + display: flex; 90 + justify-content: space-between; 91 + align-items: center; 92 + font-weight: 600; 93 + cursor: pointer; 94 + background-color: var(--navbar-bg); 95 + color: var(--text); 96 + transition: background-color 0.3s ease, color 0.3s ease; 97 + } 98 + 99 + .toggle-icon { 100 + font-size: 16px; 101 + font-weight: bold; 102 + color: var(--button-bg); 103 + transition: color 0.3s ease; 104 + } 105 + 106 + .definition-description { 107 + max-height: 0; 108 + margin-left: 0; 109 + overflow: hidden; 110 + padding: 0 15px; 111 + transition: all 0.3s ease; 112 + color: var(--text); 113 + } 114 + 115 + .definition-description.expanded { 116 + max-height: 500px; 117 + padding: 15px; 118 + border-top: 1px solid var(--card-border); 119 + margin-left: 0px; 120 + } 121 + 122 + .definition-item:hover { 123 + border-color: var(--button-bg); 124 + } 125 + 126 + .definition-term:hover { 127 + background-color: var(--background); 128 + } 129 + 130 + /* Social status styles */ 131 + .social-statuses-container { 132 + margin-top: 15px; 133 + margin-bottom: 30px; 134 + } 135 + 136 + .social-statuses-container .definition-term { 137 + font-weight: 700; 138 + } 139 + 140 + /* Social status color indicators */ 141 + .social-statuses-container .definition-item:nth-child(1) .definition-term { 142 + border-left: 4px solid #e2e8f0; /* Lightest - Newcomer */ 143 + } 144 + 145 + .social-statuses-container .definition-item:nth-child(2) .definition-term { 146 + border-left: 4px solid #004F84; /* Explorer */ 147 + } 148 + 149 + .social-statuses-container .definition-item:nth-child(3) .definition-term { 150 + border-left: 4px solid #3B9AF8; /* Pathfinder */ 151 + } 152 + 153 + .social-statuses-container .definition-item:nth-child(4) .definition-term { 154 + border-left: 4px solid #FFA500; /* Guide */ 155 + } 156 + 157 + .social-statuses-container .definition-item:nth-child(5) .definition-term { 158 + border-left: 4px solid #FFD700; /* Darkest - Leader */ 159 + } 160 + 161 + /* Learn more link styles */ 162 + .learn-more-link { 163 + margin-top: 12px; 164 + font-size: 0.9em; 165 + text-align: right; 166 + } 167 + 168 + .learn-more-link a { 169 + color: var(--button-bg); 170 + text-decoration: none; 171 + display: inline-block; 172 + transition: all 0.2s ease; 173 + padding: 4px 8px; 174 + border-radius: 4px; 175 + } 176 + 177 + .learn-more-link a:hover { 178 + background-color: rgba(59, 154, 248, 0.1); 179 + text-decoration: underline; 180 + } 181 + 182 + /* Dark mode specific overrides */ 183 + .dark-mode .definition-item { 184 + background-color: var(--navbar-bg); 185 + border-color: var(--card-border); 186 + } 187 + 188 + .dark-mode .definition-term { 189 + background-color: var(--navbar-bg); 190 + } 191 + 192 + .dark-mode .definition-term:hover { 193 + background-color: #2d2d2d; 194 + } 195 + 196 + .dark-mode .toggle-icon { 197 + color: var(--button-bg); 198 + } 199 + 200 + .dark-mode .definition-description.expanded { 201 + border-top-color: var(--card-border); 202 + } 203 + 204 + .dark-mode .learn-more-link a { 205 + color: var(--button-bg); 206 + } 207 + 208 + .dark-mode .learn-more-link a:hover { 209 + background-color: rgba(59, 154, 248, 0.15); 210 + } 211 + 212 + .dark-mode .back-to-methodology a { 213 + color: var(--button-bg); 214 + background-color: rgba(59, 154, 248, 0.15); 215 + } 216 + 217 + .dark-mode .back-to-methodology a:hover { 218 + background-color: rgba(59, 154, 248, 0.25); 219 + }
+234
src/components/Definitions/Definitions.js
··· 1 + import React, { useState } from 'react'; 2 + import './Definitions.css'; 3 + import { Link } from 'react-router-dom'; 4 + 5 + const Definitions = () => { 6 + // State to track which definition is expanded 7 + const [expandedTerm, setExpandedTerm] = useState(null); 8 + // State to track which social status is expanded 9 + const [expandedStatus, setExpandedStatus] = useState(null); 10 + 11 + // Toggle function for definitions accordion 12 + const toggleTerm = (term) => { 13 + if (expandedTerm === term) { 14 + setExpandedTerm(null); 15 + } else { 16 + setExpandedTerm(term); 17 + } 18 + }; 19 + 20 + // Toggle function for social status accordion 21 + const toggleStatus = (status) => { 22 + if (expandedStatus === status) { 23 + setExpandedStatus(null); 24 + } else { 25 + setExpandedStatus(status); 26 + } 27 + }; 28 + 29 + // Helper function to add UTM parameters to links 30 + const addUtmParams = (url, source = "term_definition") => { 31 + // Check if URL already has parameters 32 + const hasParams = url.includes('?'); 33 + const connector = hasParams ? '&' : '?'; 34 + 35 + // Add UTM parameters 36 + return `${url}${connector}utm_source=cred.blue&utm_medium=definitions&utm_campaign=${source}`; 37 + }; 38 + 39 + // Definitions data with added links 40 + const definitions = [ 41 + { 42 + id: "pds", 43 + term: "Personal Data Server (PDS)", 44 + definition: "A server that hosts your AT Protocol data and content. You can use Bluesky's PDS hosting or choose a third-party PDS host for more control over your data. By default, new Bluesky accounts use Bluesky's PDS hosting, so the vast majority of accounts right now do not use a third-party PDS. Having a third-party PDS host contributes to the further decentralization of the network, but it is currently difficult to do.", 45 + learnMoreLink: "https://atproto.com/guides/self-hosting" 46 + }, 47 + { 48 + id: "bsky-mushroom", 49 + term: "Bluesky Mushroom", 50 + definition: "All of Bluesky's PDS hosting servers are named after various types of mushrooms. If your account is on a Bluesky Mushroom, that means you are entrusting Bluesky with holding your data for you. To see a full list of the Bluesky Mushrooms, use the learn more link below.", 51 + learnMoreLink: "https://bsky-debug.app/" 52 + }, 53 + { 54 + id: "did", 55 + term: "DID", 56 + definition: "The AT Protocol uses Decentralized Identifiers (DIDs) as persistent, long-term account identifiers. DID is a W3C standard, with many standardized and proposed DID method implementations. There are currently two methods supported by the protocol: did:plc and did:web. New Bluesky accounts use the did:plc method.", 57 + learnMoreLink: "https://atproto.com/specs/did" 58 + }, 59 + { 60 + id: "lexicon", 61 + term: "Lexicon/Collection", 62 + definition: "The schema system used by the AT Protocol to define data structures. Lexicons are kind of like a file formats, and different AT Protocol apps can choose which of these file formats to support. Apps can have their own unique file formats as well. Third-party lexicons allow for custom features and extensions to the protocol. Lexicons are written in JSON and are sometimes referred to as collections.", 63 + learnMoreLink: "https://atproto.com/guides/lexicon" 64 + }, 65 + { 66 + id: "rotation-key", 67 + term: "Rotation Key", 68 + definition: "A security key that allows you to recover your account if your primary credentials are compromised.", 69 + learnMoreLink: "https://atproto.com/guides/account-migration#updating-identity" 70 + }, 71 + { 72 + id: "bluesky-eras", 73 + term: "Bluesky Eras", 74 + definition: "Ever since Bluesky was first incubated from within Twitter in 2019, it has been through numerous different defining eras. Each of these eras has had distinct qualities and even cultures. The main eras are as follows: 1. pre-history (staff, advisors, friends), 2. invite-only (the introduction of the invite system), 3. public release (anyone could create an account)", 75 + learnMoreLink: "https://atproto.com/guides/account-migration#updating-identity" 76 + }, 77 + { 78 + id: "alt-text", 79 + term: "Alt Text", 80 + definition: "Text descriptions added to images that make content accessible to users with visual impairments or when images fail to load.", 81 + learnMoreLink: "https://accessibility.huit.harvard.edu/describe-content-images" 82 + }, 83 + { 84 + id: "social-graph", 85 + term: "Social Graph", 86 + definition: "The network of connections between accounts, including followers, following, and engagement patterns.", 87 + learnMoreLink: "https://en.wikipedia.org/wiki/Social_graph" 88 + }, 89 + { 90 + id: "labelers", 91 + term: "Labelers", 92 + definition: "Entities that can apply labels to content on Bluesky for moderation purposes. Users can choose which labelers they trust.", 93 + learnMoreLink: "https://docs.bsky.app/docs/advanced-guides/moderation" 94 + }, 95 + { 96 + id: "engagement-rate", 97 + term: "Engagement Rate", 98 + definition: "A metric that measures how much interaction your content receives relative to your audience size.", 99 + } 100 + ]; 101 + 102 + // Social status data with added links 103 + const socialStatuses = [ 104 + { 105 + id: "newcomer", 106 + name: "Newcomer", 107 + description: "Accounts that are new to Bluesky or have minimal activity. These users are just getting started on the platform and beginning to build their presence. After 30 days, Newcomers become Explorers.", 108 + }, 109 + { 110 + id: "explorer", 111 + name: "Explorer", 112 + description: "Users who are actively engaging with the platform, discovering features, and building their initial network. They have established a basic presence but are still growing their connections and potentially finding their community.", 113 + }, 114 + { 115 + id: "pathfinder", 116 + name: "Pathfinder", 117 + description: "Established users who have developed a consistent presence and are actively contributing to conversations. These accounts have a growing influence (1,000+ followers) and solid engagement within their communities.", 118 + }, 119 + { 120 + id: "guide", 121 + name: "Guide", 122 + description: "Well-established users who have significant influence within specific communities (10,000+ followers). They often create valuable content and maintain strong engagement with their followers.", 123 + }, 124 + { 125 + id: "leader", 126 + name: "Leader", 127 + description: "Highly influential accounts with substantial followings (100,000+) and engagement. These users have a broad impact across multiple communities and consistently contribute high-value content to the platform.", 128 + } 129 + ]; 130 + 131 + return ( 132 + <> 133 + <main className="definitions-page"> 134 + <div className="alt-card"> 135 + <h1>Definitions | cred.blue</h1> 136 + 137 + <p className="intro-text"> 138 + This page provides explanations for key terms related to Bluesky, the AT Protocol, and how the cred.blue scoring system works. 139 + </p> 140 + 141 + <div className="back-to-methodology"> 142 + <Link to="/methodology">← Back to Scoring Methodology</Link> 143 + </div> 144 + 145 + <section className="definitions-section"> 146 + <h2>Social Status Definitions</h2> 147 + <p> 148 + Rather than displaying follower counts on profiles, the cred.blue analysis categorizes each identity into one of five social statuses based on its follower count, social graph ratio, engagement rate, and age. There are additional labels placed before the social status to indicate how engaging the account actually is. 149 + </p> 150 + <div className="social-statuses-container definitions-container"> 151 + {socialStatuses.map((status) => ( 152 + <div key={status.id} className="definition-item"> 153 + <dt 154 + className="definition-term" 155 + onClick={() => toggleStatus(status.id)} 156 + role="button" 157 + aria-expanded={expandedStatus === status.id} 158 + > 159 + {status.name} 160 + {expandedStatus === status.id ? 161 + <span className="toggle-icon" aria-hidden="true">−</span> : 162 + <span className="toggle-icon" aria-hidden="true">+</span> 163 + } 164 + </dt> 165 + <dd 166 + className={`definition-description ${expandedStatus === status.id ? 'expanded' : ''}`} 167 + aria-hidden={expandedStatus !== status.id} 168 + > 169 + {status.description} 170 + {status.learnMoreLink && ( 171 + <div className="learn-more-link"> 172 + <a 173 + href={addUtmParams(status.learnMoreLink, `social_status_${status.id}`)} 174 + target="_blank" 175 + rel="noopener noreferrer" 176 + > 177 + Learn more about {status.name} status → 178 + </a> 179 + </div> 180 + )} 181 + </dd> 182 + </div> 183 + ))} 184 + </div> 185 + </section> 186 + 187 + <section className="definitions-section"> 188 + <h2>AT Protocol & Bluesky Terms</h2> 189 + <p> 190 + Understanding these terms will help you better navigate the Bluesky ecosystem and interpret your cred.blue score. 191 + </p> 192 + <div className="definitions-container"> 193 + {definitions.map((item) => ( 194 + <div key={item.id} className="definition-item"> 195 + <dt 196 + className="definition-term" 197 + onClick={() => toggleTerm(item.id)} 198 + role="button" 199 + aria-expanded={expandedTerm === item.id} 200 + > 201 + {item.term} 202 + {expandedTerm === item.id ? 203 + <span className="toggle-icon" aria-hidden="true">−</span> : 204 + <span className="toggle-icon" aria-hidden="true">+</span> 205 + } 206 + </dt> 207 + <dd 208 + className={`definition-description ${expandedTerm === item.id ? 'expanded' : ''}`} 209 + aria-hidden={expandedTerm !== item.id} 210 + > 211 + {item.definition} 212 + {item.learnMoreLink && ( 213 + <div className="learn-more-link"> 214 + <a 215 + href={addUtmParams(item.learnMoreLink, `term_${item.id}`)} 216 + target="_blank" 217 + rel="noopener noreferrer" 218 + > 219 + Learn more about {item.term} → 220 + </a> 221 + </div> 222 + )} 223 + </dd> 224 + </div> 225 + ))} 226 + </div> 227 + </section> 228 + </div> 229 + </main> 230 + </> 231 + ); 232 + }; 233 + 234 + export default Definitions;
+271 -291
src/components/Navbar/Navbar.css
··· 2 2 3 3 /* Common Navbar Styles */ 4 4 .navbar { 5 - width: 100%; 6 - background-color: var(--navbar-bg); 7 - transition: background-color 0.3s ease, border-color 0.3s ease; 8 - border-bottom: 5px solid var(--card-border); 5 + width: 100%; 6 + background-color: var(--navbar-bg); 7 + transition: background-color 0.3s ease, border-color 0.3s ease; 8 + border-bottom: 5px solid var(--card-border); 9 9 } 10 10 11 - .cred { 12 - color: #3B9AF8; 13 - } 11 + .cred { 12 + color: #3B9AF8; 13 + } 14 + 15 + .period { 16 + color: black; 17 + } 18 + 19 + .blue { 20 + color: #004F84; 21 + } 22 + 23 + .dark-mode .cred { 24 + color: #c7c7c7; 25 + } 26 + 27 + .dark-mode .period { 28 + color: #fff; 29 + } 30 + 31 + .dark-mode .blue { 32 + color: #3B9AF8; 33 + } 34 + 35 + .navbar-container { 36 + max-width: 1000px; 37 + margin: 0 auto; /* Center the content */ 38 + padding: 0 20px; /* Horizontal padding */ 39 + display: flex; 40 + align-items: center; 41 + justify-content: space-between; /* Distribute space between left and right sections */ 42 + height: 84px; 43 + box-sizing: border-box; 44 + } 14 45 15 - .period { 16 - color: black; 17 - } 46 + /* Left Section: Logo and Links */ 47 + .navbar-left { 48 + display: flex; 49 + align-items: center; 50 + } 18 51 19 - .blue { 20 - color: #004F84; 21 - } 52 + .navbar-logo a { 53 + font-size: 1.5rem; 54 + font-weight: bold; 55 + color: #3B9AF8; /* Blue color for the logo */ 56 + text-decoration: none; 57 + transition: color 0.3s ease; 58 + } 22 59 23 - .dark-mode .cred { 24 - color: #c7c7c7; 25 - } 60 + .navbar-links { 61 + font-weight: bold; 62 + margin-top: 2px; 63 + } 26 64 27 - .dark-mode .period { 28 - color: #fff; 29 - } 65 + .navbar-links ul { 66 + list-style: none; 67 + display: flex; 68 + margin: 0; 69 + padding: 0; 70 + margin-left: 20px; /* Spacing between logo and links */ 71 + } 30 72 31 - .dark-mode .blue { 32 - color: #3B9AF8; 33 - } 73 + .navbar-links ul li { 74 + margin-left: 20px; /* Spacing between links */ 75 + } 34 76 35 - .theme-toggle-button:hover { 36 - background: none; 37 - } 38 - 39 - .navbar-container { 40 - max-width: 1000px; 41 - margin: 0 auto; /* Center the content */ 42 - padding: 0 20px; /* Horizontal padding */ 43 - display: flex; 44 - align-items: center; 45 - justify-content: space-between; /* Distribute space between left and right sections */ 46 - height: 84px; 47 - box-sizing: border-box; 48 - } 49 - 50 - /* Left Section: Logo and Links */ 51 - .navbar-left { 52 - display: flex; 53 - align-items: center; 54 - } 55 - 56 - .navbar-logo a { 57 - font-size: 1.5rem; 58 - font-weight: bold; 59 - color: #3B9AF8; /* Blue color for the logo */ 60 - text-decoration: none; 61 - transition: color 0.3s ease; 62 - } 77 + .navbar-links ul li a { 78 + text-decoration: none; 79 + color: #004f84; /* Dark blue color for links */ 80 + font-size: 1rem; 81 + transition: color 0.3s ease; 82 + } 63 83 64 - .navbar-links { 65 - font-weight: bold; 66 - margin-top: 2px; 67 - } 68 - 69 - .navbar-links ul { 70 - list-style: none; 71 - display: flex; 72 - margin: 0; 73 - padding: 0; 74 - margin-left: 20px; /* Spacing between logo and links */ 75 - } 76 - 77 - .navbar-links ul li { 78 - margin-left: 20px; /* Spacing between links */ 79 - } 80 - 81 - .navbar-links ul li a { 82 - text-decoration: none; 83 - color: #004f84; /* Dark gray color for links */ 84 - font-size: 1rem; 85 - transition: color 0.3s ease; 86 - } 87 - 88 - .navbar-links ul li a:hover { 89 - color: #3B9AF8; /* Change color on hover */ 90 - } 91 - 92 - /* Right Section: Actions */ 93 - .navbar-actions { 94 - display: flex; 95 - align-items: center; 96 - gap: 20px; /* Space between the toggle and auth buttons */ 97 - } 98 - 99 - /* Logout Button */ 100 - .logout-button { 101 - background-color: #dc3545; /* Red background */ 102 - color: #ffffff; /* White text */ 103 - } 104 - 105 - .logout-button:hover { 106 - background-color: #c82333; /* Darker red on hover */ 107 - } 108 - 109 - /* Disabled Button Styling */ 110 - .disabled-button { 111 - background-color: gray; 112 - color: white; 113 - cursor: not-allowed; 114 - } 115 - 116 - .dark-mode .navbar-logo a { 117 - color: #f5f5f5; /* Light color for logo */ 118 - } 119 - 120 - .dark-mode .navbar-links ul li a { 121 - color: #f5f5f5; /* Light gray for links */ 122 - } 123 - 124 - .dark-mode .navbar-links ul li a:hover { 125 - color: #66b2ff; /* Lighter blue on hover */ 126 - } 127 - 128 - .dark-mode .auth-button { 129 - transition: background-color 0.3s ease, color 0.3s ease; 130 - } 131 - 132 - /* Adjust Login Button for Dark Mode */ 133 - .dark-mode .login-button { 134 - background-color: #3B9AF8; /* Dark gray background */ 135 - color: #f5f5f5; /* Light text */ 136 - } 137 - 138 - .dark-mode .login-button:hover { 139 - background-color: #004F84; /* Even darker on hover */ 140 - } 141 - 142 - /* Adjust Logout Button for Dark Mode */ 143 - .dark-mode .logout-button { 144 - background-color: #ff6b6b; /* Light red background */ 145 - color: #f5f5f5; /* Light text */ 146 - } 147 - 148 - .dark-mode .logout-button:hover { 149 - background-color: #ff4c4c; /* Darker red on hover */ 150 - } 151 - 152 - /* Dark Mode Toggle Button Styling */ 153 - .theme-toggle-button { 154 - background: none; 155 - border: none; 156 - cursor: pointer; 157 - font-size: 1rem; 158 - color: var(--text);; /* Default text color */ 159 - transition: color 0.3s ease; 160 - display: flex; 161 - align-items: center; 162 - } 163 - 164 - .theme-toggle-button svg { 165 - margin-right: 5px; /* Space between icon and text */ 166 - } 84 + .navbar-links ul li a:hover { 85 + color: #3B9AF8; /* Change color on hover */ 86 + } 167 87 88 + /* Right Section: Actions */ 89 + .navbar-actions { 90 + display: flex; 91 + align-items: center; 92 + gap: 0.3em; 93 + } 168 94 169 - /* Theme toggle button icon only */ 95 + /* Theme toggle and icon styles */ 170 96 .theme-toggle-button { 171 97 background: none; 172 98 border: none; 173 99 cursor: pointer; 174 - font-size: 1.6em; 175 - display: flex; 100 + display: inline-flex; 101 + scale: 1.3; 176 102 align-items: center; 177 103 justify-content: center; 104 + padding: 0.5rem; 178 105 color: #004f84; 179 - padding: 0px; 106 + transition: color 0.2s ease; 107 + font-size: 1.6em; 180 108 } 181 109 182 - /* Theme toggle button icon only */ 110 + .theme-toggle-button:hover { 111 + color: var(--primary-color); 112 + background: none; 113 + } 114 + 183 115 .dark-mode .theme-toggle-button { 184 116 color: #ffffff; 185 117 } 186 118 119 + .theme-toggle-button svg { 120 + margin-right: 5px; /* Space between icon and text */ 121 + } 122 + 187 123 /* Icon styles */ 188 124 .nav-icon { 189 125 display: inline-flex; 190 126 align-items: center; 191 127 justify-content: center; 192 128 padding: 0.5rem; 193 - color: #004f84;; 129 + color: #004f84; 194 130 transition: color 0.2s ease; 195 131 scale: 1.3; 196 132 } 197 133 198 - /* Icon styles */ 199 134 .dark-mode .nav-icon { 200 - color: #ffffff;; 135 + color: #ffffff; 201 136 } 202 137 203 138 .nav-icon:hover { ··· 209 144 height: 1.25rem; 210 145 } 211 146 212 - /* Theme toggle button styles */ 213 - .theme-toggle-button { 214 - display: inline-flex; 215 - scale: 1.3; 216 - align-items: center; 217 - justify-content: center; 218 - padding: 0.5rem; 219 - background: none; 220 - border: none; 221 - cursor: pointer; 222 - color: #004f84;; 223 - transition: color 0.2s ease; 147 + /* Button styles */ 148 + .auth-button.login-button { 149 + padding: 7px 14px; 224 150 } 225 151 226 - .theme-toggle-button:hover { 227 - color: var(--primary-color); 152 + .logout-button { 153 + background-color: #dc3545; /* Red background */ 154 + color: #ffffff; /* White text */ 228 155 } 229 156 230 - /* Navbar actions container */ 231 - .navbar-actions { 232 - display: flex; 233 - align-items: center; 234 - gap: 0.3em; 157 + .logout-button:hover { 158 + background-color: #c82333; /* Darker red on hover */ 159 + } 160 + 161 + .disabled-button { 162 + background-color: gray; 163 + color: white; 164 + cursor: not-allowed; 165 + } 166 + 167 + .dark-mode .navbar-logo a { 168 + color: #f5f5f5; /* Light color for logo */ 169 + } 170 + 171 + .dark-mode .navbar-links ul li a { 172 + color: #f5f5f5; /* Light gray for links */ 173 + } 174 + 175 + .dark-mode .navbar-links ul li a:hover { 176 + color: #66b2ff; /* Lighter blue on hover */ 177 + } 178 + 179 + .dark-mode .auth-button { 180 + transition: background-color 0.3s ease, color 0.3s ease; 181 + } 182 + 183 + .dark-mode .login-button { 184 + background-color: #3B9AF8; /* Blue background */ 185 + color: #f5f5f5; /* Light text */ 186 + } 187 + 188 + .dark-mode .login-button:hover { 189 + background-color: #004F84; /* Darker blue on hover */ 190 + } 191 + 192 + .dark-mode .logout-button { 193 + background-color: #ff6b6b; /* Light red background */ 194 + color: #f5f5f5; /* Light text */ 235 195 } 236 196 237 - .auth-button.login-button { 238 - padding: 7px 14px; 197 + .dark-mode .logout-button:hover { 198 + background-color: #ff4c4c; /* Darker red on hover */ 239 199 } 240 200 241 201 .navbar-logo { ··· 268 228 margin-left: 10.2px; 269 229 } 270 230 271 - /* Dropdown Menu Styles */ 231 + /* ---------------------------------- */ 232 + /* Dropdown Menu Styles - NEW VERSION */ 233 + /* ---------------------------------- */ 272 234 .dropdown-container { 273 235 position: relative; 274 236 } ··· 320 282 .dropdown-menu li { 321 283 margin: 0 !important; 322 284 padding: 0; 285 + display: block; /* Force items to be blocks in a column */ 286 + width: 100%; 323 287 } 324 288 325 289 .dropdown-menu li a { ··· 329 293 text-decoration: none; 330 294 transition: background-color 0.2s ease; 331 295 white-space: nowrap; 296 + width: 100%; 297 + box-sizing: border-box; 332 298 } 333 299 334 300 .dropdown-menu li a:hover { ··· 348 314 color: #66b2ff; 349 315 } 350 316 351 - /* Responsive Adjustments for Dropdown */ 317 + /* ---------------------------------- */ 318 + /* Responsive Design Styles */ 319 + /* ---------------------------------- */ 352 320 @media (max-width: 940px) { 321 + /* Navbar container adjustments */ 322 + .navbar-container { 323 + flex-direction: column; 324 + align-items: center; 325 + height: auto; 326 + justify-content: center; 327 + row-gap: 23px; 328 + margin-top: 27px; 329 + margin-bottom: 27px; 330 + box-sizing: border-box; 331 + max-width: 1200px; 332 + padding: 0 20px; 333 + } 334 + 335 + /* Logo adjustments */ 336 + .navbar-logo { 337 + text-align: center; 338 + } 339 + 340 + .navbar-logo a { 341 + font-size: 2.5em; 342 + } 343 + 344 + .beta-badge { 345 + font-size: 0.75em; 346 + font-weight: 600; 347 + margin: 11px; 348 + padding: 4px 7px; 349 + margin-right: 0px; 350 + } 351 + 352 + /* Left section adjustments */ 353 + .navbar-left { 354 + align-items: center; 355 + display: block; 356 + } 357 + 358 + /* Links adjustments */ 359 + .navbar-links { 360 + font-weight: 700; 361 + margin-top: 15px; 362 + text-align: center; 363 + } 364 + 365 + .navbar-links ul { 366 + display: flex; 367 + justify-content: center; 368 + flex-wrap: wrap; 369 + padding: 0; 370 + list-style: none; 371 + margin: 0px; 372 + } 373 + 374 + .navbar-links ul li { 375 + margin: 0 10px; 376 + } 377 + 378 + /* Actions adjustments */ 379 + .navbar-actions { 380 + align-items: center; 381 + display: flex; 382 + gap: 5px; 383 + justify-content: center; 384 + } 385 + 386 + .navbar-support-button-container { 387 + margin-left: 0px; 388 + } 389 + 390 + /* Dropdown adjustments for mobile */ 353 391 .dropdown-menu { 354 392 position: static; 355 393 display: none; 356 394 box-shadow: none; 357 - border: none; 358 395 min-width: auto; 359 396 width: 100%; 360 - margin-top: 5px; 361 - padding: 5px 0; 362 - background-color: transparent; 397 + margin-top: 8px; 398 + margin-bottom: 8px; 399 + padding: 8px 0; 400 + background-color: rgba(59, 154, 248, 0.05); 401 + border: 1px solid var(--card-border); 402 + border-radius: 4px; 363 403 transform: none; 364 404 } 365 405 366 - .dropdown-container:hover .dropdown-menu { 406 + .dropdown-container:hover .dropdown-menu, 407 + .dropdown-container.active .dropdown-menu { 367 408 display: block; 368 409 opacity: 1; 369 410 visibility: visible; 370 411 transform: none; 371 412 } 372 413 414 + /* Force menu items to be in a column */ 415 + .dropdown-menu li { 416 + display: block; 417 + width: 100%; 418 + text-align: center; 419 + } 420 + 373 421 .dropdown-menu li a { 374 - padding: 5px 10px; 422 + padding: 8px 16px; 375 423 text-align: center; 424 + display: block; 376 425 } 377 426 378 427 .dropdown-trigger::after { 379 - position: static; 428 + display: inline-block; 380 429 margin-left: 5px; 430 + position: static; 381 431 transform: none; 432 + vertical-align: middle; 382 433 } 383 434 384 - .dropdown-container:hover .dropdown-trigger::after { 435 + .dropdown-container:hover .dropdown-trigger::after, 436 + .dropdown-container.active .dropdown-trigger::after { 385 437 transform: rotate(180deg); 386 438 } 387 - } 388 - 389 - /* Responsive Design: Links display in a row under the logo */ 390 - @media (max-width: 940px) { 391 - .navbar-container { 392 - flex-direction: column; 393 - align-items: center; 394 - } 395 - 396 - .navbar-support-button-container { 397 - margin-left: 0px; 398 - } 399 - 400 - .navbar-links ul { 401 - display: flex; 402 - justify-content: center; 403 - flex-wrap: wrap; 404 - padding: 0; 405 - list-style: none; 406 - margin: 0px; 407 - } 408 439 409 - .navbar-links ul li { 410 - margin: 0 10px; 411 - } 412 - 413 - .navbar-actions { 414 - align-items: center; 415 - display: flex; 416 - gap: 5px; 417 - justify-content: center; 418 - } 419 - 420 - .navbar-links { 421 - font-weight: 700; 422 - margin-top: 15px; 423 - text-align: center; 424 - } 425 - 426 - .navbar-logo a { 427 - font-size: 2.5em; 428 - } 429 - 430 - .navbar-container { 431 - align-items: center; 432 - flex-direction: column; 433 - justify-content: center; 434 - row-gap: 23px; 435 - margin-top: 27px; 436 - margin-bottom: 27px; 437 - display: flex; 438 - } 439 - 440 - .navbar-container { 441 - box-sizing: border-box; 442 - height: 100%; 443 - justify-content: space-between; 444 - max-width: 1200px; 445 - padding: 0 20px; 446 - } 447 - 448 - .navbar-left { 449 - align-items: center; 450 - display: block; 451 - } 452 - 453 - .navbar-logo { 454 - text-align: center; 455 - } 456 - 457 - .beta-badge { 458 - font-size: 0.75em; 459 - font-weight: 600; 460 - margin: 11px; 461 - padding: 4px 7px; 462 - margin-right: 0px; 463 - } 440 + /* Prevent layout shifting */ 441 + .dropdown-container { 442 + margin-bottom: 4px; 443 + min-height: 32px; 464 444 } 445 + } 465 446 466 - /* Responsive Design: Links display in a row under the logo */ 467 - @media (max-width: 450px) { 468 - .navbar-links { 469 - max-width: 300px; 470 - line-height: 1.8em; 471 - } 447 + /* Smaller screen refinements */ 448 + @media (max-width: 450px) { 449 + .navbar-links { 450 + max-width: 300px; 451 + line-height: 1.8em; 472 452 } 453 + } 473 454 474 - /* Responsive Design: Links display in a row under the logo */ 475 - @media (max-width: 370px) { 476 - .navbar-support-button { 477 - max-width: 135.5px; 478 - font-size: 0.8em; 479 - margin-left: 0px; 480 - } 481 - .navbar-links { 482 - font-weight: 700; 483 - text-align: center; 484 - max-width: 205.5px; 485 - margin: auto; 486 - margin-top: auto; 487 - margin-top: 15px; 488 - line-height: 1.5em; 489 - } 490 - } 455 + @media (max-width: 370px) { 456 + .navbar-support-button { 457 + max-width: 135.5px; 458 + font-size: 0.8em; 459 + margin-left: 0px; 460 + } 461 + 462 + .navbar-links { 463 + font-weight: 700; 464 + text-align: center; 465 + max-width: 205.5px; 466 + margin: auto; 467 + margin-top: 15px; 468 + line-height: 1.5em; 469 + } 470 + }
+47 -8
src/components/Navbar/Navbar.js
··· 1 - import React, { useContext, useState } from 'react'; 1 + import React, { useContext, useState, useRef, useEffect } from 'react'; 2 2 import { Link, useNavigate } from 'react-router-dom'; 3 3 import { ThemeContext } from '../../contexts/ThemeContext'; 4 4 import './Navbar.css'; 5 5 6 6 // Dropdown Menu Component 7 7 const DropdownMenu = ({ title, path, items }) => { 8 - const [isHovered, setIsHovered] = useState(false); 8 + const [isOpen, setIsOpen] = useState(false); 9 + const dropdownRef = useRef(null); 10 + 11 + // Handle click outside to close the dropdown 12 + useEffect(() => { 13 + const handleClickOutside = (event) => { 14 + if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { 15 + setIsOpen(false); 16 + } 17 + }; 18 + 19 + // Add event listener only when dropdown is open 20 + if (isOpen) { 21 + document.addEventListener('mousedown', handleClickOutside); 22 + } 23 + 24 + return () => { 25 + document.removeEventListener('mousedown', handleClickOutside); 26 + }; 27 + }, [isOpen]); 28 + 29 + // Detect if we're on mobile based on window width 30 + const isMobile = () => window.innerWidth <= 940; 9 31 10 32 return ( 11 33 <li 12 - className="dropdown-container" 13 - onMouseEnter={() => setIsHovered(true)} 14 - onMouseLeave={() => setIsHovered(false)} 34 + className={`dropdown-container ${isOpen ? 'active' : ''}`} 35 + ref={dropdownRef} 36 + onMouseEnter={() => !isMobile() && setIsOpen(true)} 37 + onMouseLeave={() => !isMobile() && setIsOpen(false)} 15 38 > 16 - <Link to={path} className="dropdown-trigger">{title}</Link> 17 - {isHovered && ( 39 + <Link 40 + to={path} 41 + className="dropdown-trigger" 42 + onClick={(e) => { 43 + if (isMobile()) { 44 + e.preventDefault(); 45 + setIsOpen(!isOpen); 46 + } 47 + }} 48 + > 49 + {title} 50 + </Link> 51 + {(isOpen || (!isMobile() && isOpen)) && ( 18 52 <ul className="dropdown-menu"> 19 53 {items.map((item, index) => ( 20 54 <li key={index}> 21 - <Link to={item.path}>{item.title}</Link> 55 + <Link 56 + to={item.path} 57 + onClick={() => setIsOpen(false)} 58 + > 59 + {item.title} 60 + </Link> 22 61 </li> 23 62 ))} 24 63 </ul>
+27 -164
src/components/ScoringMethodology/ScoringMethodology.css
··· 35 35 margin: 15px 0; 36 36 line-height: 1.5; 37 37 } 38 - 38 + 39 39 .increase-score-list li { 40 40 margin-bottom: 5px; 41 41 } 42 - 43 - .social-status-list li { 44 - margin-bottom: 5px; 45 - } 46 - 42 + 47 43 .methodology-page-chart .score-gauge { 48 44 margin: auto !important; 49 45 padding-right: 11px; 50 46 padding-bottom: 10.5px; 51 - } 52 - 53 - /* Add these styles to your ScoringMethodology.css file */ 54 - 55 - .definitions-container { 56 - margin-top: 20px; 57 - overflow: hidden; 58 - } 59 - 60 - .definition-item { 61 - margin-bottom: 10px; 62 - border-radius: 6px; 63 - background-color: var(--navbar-bg); 64 - overflow: hidden; 65 - transition: all 0.3s ease; 66 - border: 1px solid var(--card-border); 67 47 } 68 48 69 - .definition-term { 70 - padding: 12px 15px; 71 - display: flex; 72 - justify-content: space-between; 73 - align-items: center; 74 - font-weight: 600; 75 - cursor: pointer; 76 - background-color: var(--navbar-bg); 77 - color: var(--text); 78 - transition: background-color 0.3s ease, color 0.3s ease; 79 - } 80 - 81 - .toggle-icon { 82 - font-size: 16px; 83 - font-weight: bold; 84 - color: var(--button-bg); 85 - transition: color 0.3s ease; 86 - } 87 - 88 - .definition-description { 89 - max-height: 0; 90 - margin-left: 0; 91 - overflow: hidden; 92 - padding: 0 15px; 93 - transition: all 0.3s ease; 94 - color: var(--text); 95 - } 96 - 97 - .definition-description.expanded { 98 - max-height: 500px; 49 + /* Link to Definitions page */ 50 + .definitions-link-container { 51 + margin-top: 40px; 99 52 padding: 15px; 100 - border-top: 1px solid var(--card-border); 101 - margin-left: 0px; 102 - } 103 - 104 - .definition-item:hover { 105 - border-color: var(--button-bg); 106 - } 107 - 108 - .definition-term:hover { 109 - background-color: var(--background); 53 + background-color: rgba(59, 154, 248, 0.1); 54 + border-radius: 8px; 55 + border-left: 4px solid var(--button-bg); 110 56 } 111 57 112 - /* Alternative simple style (if you prefer a non-accordion approach) */ 113 - .definitions-simple .definition-item { 114 - margin-bottom: 20px; 115 - background-color: transparent; 116 - border: none; 58 + .definitions-link { 59 + display: inline-block; 60 + margin-top: 10px; 61 + color: var(--button-bg); 62 + text-decoration: none; 63 + padding: 8px 16px; 64 + border-radius: 4px; 65 + background-color: rgba(59, 154, 248, 0.15); 66 + transition: all 0.2s ease; 67 + font-weight: 500; 117 68 } 118 69 119 - .definitions-simple .definition-term { 120 - font-weight: 700; 121 - margin-bottom: 8px; 122 - cursor: default; 123 - background-color: transparent; 124 - padding: 0; 125 - color: var(--text); 126 - } 127 - 128 - .definitions-simple .definition-description { 129 - max-height: none; 130 - padding: 0 0 0 15px; 131 - border-left: 3px solid var(--button-bg); 132 - color: var(--text); 70 + .definitions-link:hover { 71 + background-color: rgba(59, 154, 248, 0.25); 72 + text-decoration: underline; 133 73 } 134 74 135 75 /* Dark mode specific overrides */ 136 - .dark-mode .definition-item { 137 - background-color: var(--navbar-bg); 138 - border-color: var(--card-border); 139 - } 140 - 141 - .dark-mode .definition-term { 142 - background-color: var(--navbar-bg); 143 - } 144 - 145 - .dark-mode .definition-term:hover { 146 - background-color: #2d2d2d; 147 - } 148 - 149 - .dark-mode .toggle-icon { 150 - color: var(--button-bg); 151 - } 152 - 153 - .dark-mode .definition-description.expanded { 154 - border-top-color: var(--card-border); 155 - } 156 - 157 - .dark-mode .definitions-simple .definition-description { 76 + .dark-mode .definitions-link-container { 77 + background-color: rgba(59, 154, 248, 0.1); 158 78 border-left-color: var(--button-bg); 159 79 } 160 - 161 - 162 - /* Add these styles to your ScoringMethodology.css file */ 163 - 164 - /* Make the social statuses container use the same styling as definitions */ 165 - .social-statuses-container { 166 - margin-top: 15px; 167 - margin-bottom: 30px; 168 - } 169 80 170 - /* Additional style for the social status names to make them stand out */ 171 - .social-statuses-container .definition-term { 172 - font-weight: 700; 173 - } 174 - 175 - /* Add a subtle indicator for the different status levels */ 176 - .social-statuses-container .definition-item:nth-child(1) .definition-term { 177 - border-left: 4px solid #e2e8f0; /* Lightest - Newcomer */ 178 - } 179 - 180 - .social-statuses-container .definition-item:nth-child(2) .definition-term { 181 - border-left: 4px solid #004F84; /* Explorer */ 182 - } 183 - 184 - .social-statuses-container .definition-item:nth-child(3) .definition-term { 185 - border-left: 4px solid #3B9AF8; /* Pathfinder */ 186 - } 187 - 188 - .social-statuses-container .definition-item:nth-child(4) .definition-term { 189 - border-left: 4px solid #FFA500; /* Guide */ 190 - } 191 - 192 - .social-statuses-container .definition-item:nth-child(5) .definition-term { 193 - border-left: 4px solid #FFD700; /* Darkest - Leader */ 194 - } 195 - 196 - /* Add these styles to your ScoringMethodology.css file */ 197 - 198 - .learn-more-link { 199 - margin-top: 12px; 200 - font-size: 0.9em; 201 - text-align: right; 202 - } 203 - 204 - .learn-more-link a { 81 + .dark-mode .definitions-link { 205 82 color: var(--button-bg); 206 - text-decoration: none; 207 - display: inline-block; 208 - transition: all 0.2s ease; 209 - padding: 4px 8px; 210 - border-radius: 4px; 83 + background-color: rgba(59, 154, 248, 0.2); 211 84 } 212 85 213 - .learn-more-link a:hover { 214 - background-color: rgba(59, 154, 248, 0.1); 215 - text-decoration: underline; 216 - } 217 - 218 - /* Make sure links work properly in dark mode */ 219 - .dark-mode .learn-more-link a { 220 - color: var(--button-bg); 221 - } 222 - 223 - .dark-mode .learn-more-link a:hover { 224 - background-color: rgba(59, 154, 248, 0.15); 86 + .dark-mode .definitions-link:hover { 87 + background-color: rgba(59, 154, 248, 0.3); 225 88 }
+10 -201
src/components/ScoringMethodology/ScoringMethodology.js
··· 1 - import React, { useState } from 'react'; 1 + import React from 'react'; 2 2 import './ScoringMethodology.css'; 3 3 import ScoreGauge from '../UserProfile/ScoreGauge'; 4 + import { Link } from 'react-router-dom'; 4 5 5 6 const ScoringMethodology = () => { 6 - // State to track which definition is expanded 7 - const [expandedTerm, setExpandedTerm] = useState(null); 8 - // State to track which social status is expanded 9 - const [expandedStatus, setExpandedStatus] = useState(null); 10 - 11 - // Toggle function for definitions accordion 12 - const toggleTerm = (term) => { 13 - if (expandedTerm === term) { 14 - setExpandedTerm(null); 15 - } else { 16 - setExpandedTerm(term); 17 - } 18 - }; 19 - 20 - // Toggle function for social status accordion 21 - const toggleStatus = (status) => { 22 - if (expandedStatus === status) { 23 - setExpandedStatus(null); 24 - } else { 25 - setExpandedStatus(status); 26 - } 27 - }; 28 - 29 - // Helper function to add UTM parameters to links 30 - const addUtmParams = (url, source = "term_definition") => { 31 - // Check if URL already has parameters 32 - const hasParams = url.includes('?'); 33 - const connector = hasParams ? '&' : '?'; 34 - 35 - // Add UTM parameters 36 - return `${url}${connector}utm_source=cred.blue&utm_medium=methodology&utm_campaign=${source}`; 37 - }; 38 - 39 - // Definitions data with added links 40 - const definitions = [ 41 - { 42 - id: "pds", 43 - term: "Personal Data Server (PDS)", 44 - definition: "A server that hosts your AT Protocol data and content. You can use Bluesky's PDS hosting or choose a third-party PDS host for more control over your data. By default, new Bluesky accounts use Bluesky's PDS hosting, so the vast majority of accounts right now do not use a third-party PDS. Having a third-party PDS host contributes to the further decentralization of the network, but it is currently difficult to do.", 45 - learnMoreLink: "https://atproto.com/guides/self-hosting" 46 - }, 47 - { 48 - id: "bsky-mushroom", 49 - term: "Bluesky Mushroom", 50 - definition: "All of Bluesky's PDS hosting servers are named after various types of mushrooms. If your account is on a Bluesky Mushroom, that means you are entrusting Bluesky with holding your data for you. To see a full list of the Bluesky Mushrooms, use the learn more link below.", 51 - learnMoreLink: "https://bsky-debug.app/" 52 - }, 53 - { 54 - id: "did", 55 - term: "DID", 56 - definition: "The AT Protocol uses Decentralized Identifiers (DIDs) as persistent, long-term account identifiers. DID is a W3C standard, with many standardized and proposed DID method implementations. There are currently two methods supported by the protocol: did:plc and did:web. New Bluesky accounts use the did:plc method.", 57 - learnMoreLink: "https://atproto.com/specs/did" 58 - }, 59 - { 60 - id: "lexicon", 61 - term: "Lexicon/Collection", 62 - definition: "The schema system used by the AT Protocol to define data structures. Lexicons are kind of like a file formats, and different AT Protocol apps can choose which of these file formats to support. Apps can have their own unique file formats as well. Third-party lexicons allow for custom features and extensions to the protocol. Lexicons are written in JSON and are sometimes referred to as collections.", 63 - learnMoreLink: "https://atproto.com/guides/lexicon" 64 - }, 65 - { 66 - id: "rotation-key", 67 - term: "Rotation Key", 68 - definition: "A security key that allows you to recover your account if your primary credentials are compromised.", 69 - learnMoreLink: "https://atproto.com/guides/account-migration#updating-identity" 70 - }, 71 - { 72 - id: "bluesky-eras", 73 - term: "Bluesky Eras", 74 - definition: "Ever since Bluesky was first incubated from within Twitter in 2019, it has been through numerous different defining eras. Each of these eras has had distinct qualities and even cultures. The main eras are as follows: 1. pre-history (staff, advisors, friends), 2. invite-only (the introduction of the invite system), 3. public release (anyone could create an account)", 75 - learnMoreLink: "https://atproto.com/guides/account-migration#updating-identity" 76 - }, 77 - { 78 - id: "alt-text", 79 - term: "Alt Text", 80 - definition: "Text descriptions added to images that make content accessible to users with visual impairments or when images fail to load.", 81 - learnMoreLink: "https://accessibility.huit.harvard.edu/describe-content-images" 82 - }, 83 - { 84 - id: "social-graph", 85 - term: "Social Graph", 86 - definition: "The network of connections between accounts, including followers, following, and engagement patterns.", 87 - learnMoreLink: "https://en.wikipedia.org/wiki/Social_graph" 88 - }, 89 - { 90 - id: "labelers", 91 - term: "Labelers", 92 - definition: "Entities that can apply labels to content on Bluesky for moderation purposes. Users can choose which labelers they trust.", 93 - learnMoreLink: "https://docs.bsky.app/docs/advanced-guides/moderation" 94 - }, 95 - { 96 - id: "engagement-rate", 97 - term: "Engagement Rate", 98 - definition: "A metric that measures how much interaction your content receives relative to your audience size.", 99 - } 100 - ]; 101 - 102 - // Social status data with added links 103 - const socialStatuses = [ 104 - { 105 - id: "newcomer", 106 - name: "Newcomer", 107 - description: "Accounts that are new to Bluesky or have minimal activity. These users are just getting started on the platform and beginning to build their presence. After 30 days, Newcomers become Explorers.", 108 - }, 109 - { 110 - id: "explorer", 111 - name: "Explorer", 112 - description: "Users who are actively engaging with the platform, discovering features, and building their initial network. They have established a basic presence but are still growing their connections and potentially finding their community.", 113 - }, 114 - { 115 - id: "pathfinder", 116 - name: "Pathfinder", 117 - description: "Established users who have developed a consistent presence and are actively contributing to conversations. These accounts have a growing influence (1,000+ followers) and solid engagement within their communities.", 118 - }, 119 - { 120 - id: "guide", 121 - name: "Guide", 122 - description: "Well-established users who have significant influence within specific communities (10,000+ followers). They often create valuable content and maintain strong engagement with their followers.", 123 - }, 124 - { 125 - id: "leader", 126 - name: "Leader", 127 - description: "Highly influential accounts with substantial followings (100,000+) and engagement. These users have a broad impact across multiple communities and consistently contribute high-value content to the platform.", 128 - } 129 - ]; 130 - 131 7 return ( 132 8 <main className="methodology-page"> 133 9 <div className="alt-card"> ··· 186 62 entire community. 187 63 </p> 188 64 189 - <h2>What are the different social statuses?</h2> 190 - <p> 191 - Rather than displaying follower counts on profiles, the cred.blue analysis categorizes each identity into one of five social statuses based on its follower count, social graph ratio, engagement rate, and age. There are additional labels placed before the social status to indicate how engaging the account actually is. 192 - </p> 193 - <div className="social-statuses-container definitions-container"> 194 - {socialStatuses.map((status) => ( 195 - <div key={status.id} className="definition-item"> 196 - <dt 197 - className="definition-term" 198 - onClick={() => toggleStatus(status.id)} 199 - role="button" 200 - aria-expanded={expandedStatus === status.id} 201 - > 202 - {status.name} 203 - {expandedStatus === status.id ? 204 - <span className="toggle-icon" aria-hidden="true">−</span> : 205 - <span className="toggle-icon" aria-hidden="true">+</span> 206 - } 207 - </dt> 208 - <dd 209 - className={`definition-description ${expandedStatus === status.id ? 'expanded' : ''}`} 210 - aria-hidden={expandedStatus !== status.id} 211 - > 212 - {status.description} 213 - {status.learnMoreLink && ( 214 - <div className="learn-more-link"> 215 - <a 216 - href={addUtmParams(status.learnMoreLink, `social_status_${status.id}`)} 217 - target="_blank" 218 - rel="noopener noreferrer" 219 - > 220 - Learn more about {status.name} status → 221 - </a> 222 - </div> 223 - )} 224 - </dd> 225 - </div> 226 - ))} 65 + <div className="definitions-link-container"> 66 + <p> 67 + Looking for explanations of terms used in cred.blue or details about social statuses? 68 + </p> 69 + <Link to="/definitions" className="definitions-link"> 70 + View Definitions & Social Status Details → 71 + </Link> 227 72 </div> 228 - 229 - <h2>Key Terms and Definitions</h2> 230 - <div className="definitions-container"> 231 - {definitions.map((item) => ( 232 - <div key={item.id} className="definition-item"> 233 - <dt 234 - className="definition-term" 235 - onClick={() => toggleTerm(item.id)} 236 - role="button" 237 - aria-expanded={expandedTerm === item.id} 238 - > 239 - {item.term} 240 - {expandedTerm === item.id ? 241 - <span className="toggle-icon" aria-hidden="true">−</span> : 242 - <span className="toggle-icon" aria-hidden="true">+</span> 243 - } 244 - </dt> 245 - <dd 246 - className={`definition-description ${expandedTerm === item.id ? 'expanded' : ''}`} 247 - aria-hidden={expandedTerm !== item.id} 248 - > 249 - {item.definition} 250 - {item.learnMoreLink && ( 251 - <div className="learn-more-link"> 252 - <a 253 - href={addUtmParams(item.learnMoreLink, `term_${item.id}`)} 254 - target="_blank" 255 - rel="noopener noreferrer" 256 - > 257 - Learn more about {item.term} → 258 - </a> 259 - </div> 260 - )} 261 - </dd> 262 - </div> 263 - ))} 264 - </div> 73 + 265 74 </div> 266 75 </main> 267 76 );