Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/CardSkeleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface CardSkeletonProps {
export const CardSkeleton: React.FC<CardSkeletonProps> = ({ className = '' }) => {
return (
<div
className={`p-4 rounded-2xl bg-white dark:bg-[#1A1A1E] border-[1.5px] border-neutral-300/90 dark:border-neutral-700 shadow-xs dark:shadow-md dark:shadow-black/40 space-y-3.5 transition-colors ${className}`}
className={`px-4 sm:px-6 py-4 space-y-3.5 transition-colors ${className}`}
role="status"
aria-busy="true"
aria-label="Loading card"
Expand Down
10 changes: 5 additions & 5 deletions src/components/LanguageSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,14 @@ export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
</button>

{isOpen && (
<div className="w-56 mt-2 rounded-2xl bg-neutral-200/95 dark:bg-neutral-900/95 border border-neutral-300 dark:border-neutral-700 shadow-[0_4px_16px_rgba(0,0,0,0.10)] dark:shadow-[0_4px_16px_rgba(0,0,0,0.50)] py-1.5 z-50 max-h-80 overflow-y-auto custom-scrollbar">
<div className="w-56 mt-2 rounded-2xl bg-neutral-200/95 dark:bg-neutral-900/95 border border-neutral-300 dark:border-neutral-700 shadow-[0_4px_16px_rgba(0,0,0,0.10)] dark:shadow-[0_4px_16px_rgba(0,0,0,0.50)] p-1.5 flex flex-col gap-0.5 z-50">
{languages.map((lang) => {
const isActive = i18n.language.startsWith(lang.code);
return (
<button
key={lang.code}
onClick={() => handleSelect(lang.code)}
className={`w-full flex items-center justify-between px-4 py-2 text-xs transition-colors ${
className={`w-full flex items-center justify-between px-3 py-2 rounded-xl text-xs transition-colors cursor-pointer ${
isActive
? 'bg-[#CEFF00]/15 text-foreground font-bold'
: 'text-neutral-700 dark:text-neutral-300 hover:bg-neutral-300/60 dark:hover:bg-neutral-800/80'
Expand Down Expand Up @@ -151,16 +151,16 @@ export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
)}

{isOpen && (
<div className="absolute left-1/2 -translate-x-1/2 top-[calc(100%+21px)] w-40 rounded-xl bg-white dark:bg-neutral-900 border border-[#C7C7C7] dark:border-neutral-700 shadow-[0_4px_16px_rgba(0,0,0,0.10)] dark:shadow-[0_4px_16px_rgba(0,0,0,0.50)] z-[70] py-1 animate-in fade-in slide-in-from-top-2 duration-150 max-h-80 overflow-y-auto custom-scrollbar isolate">
<div className="absolute left-1/2 -translate-x-1/2 top-[calc(100%+21px)] w-44 rounded-2xl bg-white dark:bg-neutral-900 border border-[#C7C7C7] dark:border-neutral-700 shadow-[0_4px_16px_rgba(0,0,0,0.10)] dark:shadow-[0_4px_16px_rgba(0,0,0,0.50)] z-[70] p-1.5 flex flex-col gap-0.5 animate-in fade-in slide-in-from-top-2 duration-150 max-h-80 overflow-y-auto custom-scrollbar isolate">
{languages.map((lang) => {
const isActive = i18n.language.startsWith(lang.code);
return (
<button
key={lang.code}
onClick={() => handleSelect(lang.code)}
className={`w-full flex items-center justify-between px-3 py-1.5 text-xs transition-colors ${
className={`w-full flex items-center justify-between px-2.5 py-1.5 rounded-xl text-xs transition-colors cursor-pointer ${
isActive
? 'bg-[#CEFF00]/10 text-foreground font-bold'
? 'bg-[#CEFF00]/15 dark:bg-[#CEFF00]/15 text-foreground font-bold'
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800/80 hover:text-foreground'
}`}
>
Expand Down
20 changes: 10 additions & 10 deletions src/components/ProximitySidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const ProximitySidebar: React.FC<ProximitySidebarProps> = ({
return (
<div
aria-label="Proximity Navigation Minimap"
className="fixed left-3 sm:left-4 lg:left-5 xl:left-6 top-1/2 -translate-y-1/2 z-40 hidden lg:flex flex-col items-start p-0 select-none pointer-events-auto"
className="fixed left-2 xl:left-3 2xl:left-6 top-1/2 -translate-y-1/2 z-40 hidden lg:flex flex-col items-start p-0 select-none pointer-events-auto"
>
<div className="flex flex-col items-start gap-1 py-1">
{Array.from({ length: totalDashes }).map((_, index) => {
Expand All @@ -92,24 +92,24 @@ export const ProximitySidebar: React.FC<ProximitySidebarProps> = ({
const distance = Math.abs(index - activeDashCenter);
const isHovered = hoveredIndex === index;

let widthClass = 'w-6 bg-neutral-300/80 dark:bg-neutral-700/80';
let widthClass = 'w-3 xl:w-4 2xl:w-6 bg-neutral-300/80 dark:bg-neutral-700/80';
let glowClass = '';

if (isHovered) {
widthClass = 'w-16 bg-neutral-900 dark:bg-white';
widthClass = 'w-8 xl:w-10 2xl:w-16 bg-neutral-900 dark:bg-white';
glowClass = 'shadow-sm dark:shadow-[0_0_5px_rgba(255,255,255,0.3)]';
} else if (distance === 0) {
widthClass = 'w-16 bg-[#3f6e00] dark:bg-[#CEFF00]';
widthClass = 'w-7 xl:w-9 2xl:w-16 bg-[#3f6e00] dark:bg-[#CEFF00]';
glowClass = 'shadow-[0_0_4px_rgba(63,110,0,0.25)] dark:shadow-[0_0_4px_rgba(206,255,0,0.35)]';
} else if (distance === 1) {
widthClass = 'w-12 bg-[#3f6e00]/85 dark:bg-[#CEFF00]/80';
widthClass = 'w-5 xl:w-7 2xl:w-12 bg-[#3f6e00]/85 dark:bg-[#CEFF00]/80';
glowClass = 'dark:shadow-[0_0_2px_rgba(206,255,0,0.2)]';
} else if (distance === 2) {
widthClass = 'w-10 bg-[#3f6e00]/55 dark:bg-[#CEFF00]/50';
widthClass = 'w-4 xl:w-5 2xl:w-10 bg-[#3f6e00]/55 dark:bg-[#CEFF00]/50';
} else if (distance === 3) {
widthClass = 'w-8 bg-[#3f6e00]/30 dark:bg-[#CEFF00]/25';
widthClass = 'w-3.5 xl:w-4 2xl:w-8 bg-[#3f6e00]/30 dark:bg-[#CEFF00]/25';
} else if (isTitle) {
widthClass = 'w-9 bg-neutral-400 dark:bg-neutral-500';
widthClass = 'w-4 xl:w-5 2xl:w-9 bg-neutral-400 dark:bg-neutral-500';
}

return (
Expand All @@ -118,7 +118,7 @@ export const ProximitySidebar: React.FC<ProximitySidebarProps> = ({
onClick={() => scrollToDash(index, section.id, isTitle)}
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(null)}
className="group relative flex items-center justify-start w-20 py-0.5 sm:py-1 cursor-pointer focus:outline-none"
className="group relative flex items-center justify-start w-9 xl:w-11 2xl:w-20 py-0.5 sm:py-1 cursor-pointer focus:outline-none"
aria-label={isTitle ? section.label : undefined}
>
<div
Expand All @@ -127,7 +127,7 @@ export const ProximitySidebar: React.FC<ProximitySidebarProps> = ({

{/* Tooltip for Section Title Bars or Hovered Dash */}
{isHovered && isTitle && (
<span className="absolute left-20 px-2.5 py-1 rounded-md bg-neutral-900 text-[#CEFF00] dark:text-[#CEFF00] text-[11px] font-mono whitespace-nowrap shadow-xl border border-neutral-700 animate-in fade-in slide-in-from-left-1 pointer-events-none z-50">
<span className="absolute left-10 xl:left-12 2xl:left-20 px-2.5 py-1 rounded-md bg-neutral-900 text-[#CEFF00] dark:text-[#CEFF00] text-[11px] font-mono whitespace-nowrap shadow-xl border border-neutral-700 animate-in fade-in slide-in-from-left-1 pointer-events-none z-50">
{section.label}
</span>
)}
Expand Down
3 changes: 2 additions & 1 deletion src/components/TechBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ export const TechBar: React.FC<TechBarProps> = ({ entry, maxStars }) => {
const cleanVersion = entry.creator && entry.creator.latestVersion ? sanitizeText(entry.creator.latestVersion) : '';
const liveVersion = useGitHubRelease(entry.githubUrl, cleanVersion);

const rawRatio = Math.max(0, entry.popularity.totalStars) / (maxStars || 1);
const starPercentage = Math.min(
100,
Math.max(8, (entry.popularity.totalStars / (maxStars || 1)) * 100)
Math.max(8, Math.round(Math.sqrt(rawRatio) * 1000) / 10)
);

const formattedStars = formatNumber(entry.popularity.totalStars, i18n.language);
Expand Down
38 changes: 20 additions & 18 deletions src/components/TechTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const CustomDropdown: React.FC<{
</button>

{isOpen && (
<div className="absolute right-0 top-[calc(100%+8px)] w-48 rounded-xl bg-white dark:bg-neutral-900 border border-[#C7C7C7] dark:border-neutral-700 shadow-2xl z-50 overflow-hidden py-1 animate-in fade-in slide-in-from-top-2 duration-150">
<div className="absolute right-0 top-[calc(100%+8px)] w-48 rounded-2xl bg-white dark:bg-neutral-900 border border-[#C7C7C7] dark:border-neutral-700 shadow-2xl z-50 p-1.5 flex flex-col gap-0.5 animate-in fade-in slide-in-from-top-2 duration-150">
{options.map((opt) => {
const isSelected = opt.value === value;
return (
Expand All @@ -92,9 +92,9 @@ const CustomDropdown: React.FC<{
onChange(opt.value);
setIsOpen(false);
}}
className={`w-full flex items-center justify-between px-3.5 py-2 text-xs transition-colors cursor-pointer ${
className={`w-full flex items-center justify-between px-3 py-2 rounded-xl text-xs transition-colors cursor-pointer ${
isSelected
? 'bg-[#CEFF00]/10 text-foreground font-bold'
? 'bg-[#CEFF00]/15 dark:bg-[#CEFF00]/15 text-foreground font-bold'
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800/80 hover:text-foreground'
}`}
>
Expand Down Expand Up @@ -297,7 +297,7 @@ export const TechTable: React.FC<TechTableProps> = ({
))}
</div>
) : (
<div className="p-3 sm:p-4 space-y-3.5">
<div className="w-full divide-y divide-neutral-300 dark:divide-neutral-700">
{[1, 2].map((idx) => (
<CardSkeleton key={idx} />
))}
Expand All @@ -307,16 +307,16 @@ export const TechTable: React.FC<TechTableProps> = ({
<div className="w-full overflow-x-auto custom-scrollbar rounded-b-[24px]">
<table className="w-full text-left border-collapse table-auto">
<thead>
<tr className="border-b border-neutral-200/80 dark:border-neutral-800/80 text-[10px] lg:text-[11px] font-semibold uppercase tracking-tight lg:tracking-wider text-neutral-500 dark:text-neutral-400 bg-neutral-50/80 dark:bg-neutral-900/70">
<th className="py-2.5 lg:py-3 pl-2.5 pr-1 lg:pl-4 lg:pr-2 text-left">{t('table.technology')}</th>
<th className="py-2.5 lg:py-3 px-1 text-left">{t('table.creator')}</th>
<th className="py-2.5 lg:py-3 px-1 text-center">{t('table.type')}</th>
<th className="py-2.5 lg:py-3 px-1 lg:px-2 text-left">{t('table.popularity')}</th>
<th className="py-2.5 lg:py-3 px-1 text-center">{t('table.momentum')}</th>
<th className="py-2.5 lg:py-3 px-1 text-center">{t('table.ecosystem')}</th>
<th className="py-2.5 lg:py-3 px-1 text-center">{t('table.community')}</th>
<th className="py-2.5 lg:py-3 px-1 text-center">{t('table.latestVersion')}</th>
<th className="py-2.5 lg:py-3 px-1.5 lg:px-3 text-center">{t('table.github')}</th>
<tr className="border-b border-neutral-200/80 dark:border-neutral-800/80 text-[10px] lg:text-[11px] font-semibold uppercase tracking-tight lg:tracking-wider text-neutral-500 dark:text-neutral-400 bg-neutral-50/80 dark:bg-neutral-900/70 whitespace-nowrap">
<th className="py-2.5 lg:py-3 pl-2.5 pr-1 lg:pl-4 lg:pr-2 text-left whitespace-nowrap">{t('table.technology')}</th>
<th className="py-2.5 lg:py-3 px-1 text-left whitespace-nowrap">{t('table.creator')}</th>
<th className="py-2.5 lg:py-3 px-1 text-center whitespace-nowrap">{t('table.type')}</th>
<th className="py-2.5 lg:py-3 px-1 lg:px-2 text-left whitespace-nowrap">{t('table.popularity')}</th>
<th className="py-2.5 lg:py-3 px-1 text-center whitespace-nowrap">{t('table.momentum')}</th>
<th className="py-2.5 lg:py-3 px-1 text-center whitespace-nowrap">{t('table.ecosystem')}</th>
<th className="py-2.5 lg:py-3 px-1 text-center whitespace-nowrap">{t('table.community')}</th>
<th className="py-2.5 lg:py-3 px-1 text-center whitespace-nowrap">{t('table.latestVersion')}</th>
<th className="py-2.5 lg:py-3 px-1.5 lg:px-3 text-center whitespace-nowrap">{t('table.github')}</th>
</tr>
</thead>
<tbody className="divide-y divide-neutral-200/60 dark:divide-neutral-800/60 text-xs">
Expand All @@ -327,7 +327,7 @@ export const TechTable: React.FC<TechTableProps> = ({
</table>
</div>
) : (
<div className="p-3 sm:p-4 space-y-3.5">
<div className="w-full divide-y divide-neutral-300 dark:divide-neutral-700">
{processedEntries.map((entry, index) => (
<LazyMobileCard key={entry.id} entry={entry} maxStars={maxStars} index={index} priority={priority} />
))}
Expand Down Expand Up @@ -368,9 +368,10 @@ const TableRow: React.FC<TableRowProps> = ({ entry, maxStars }) => {

const isHostedOnGitHub = isGitHubRepo(entry.githubUrl);

const rawRatio = Math.max(0, entry.popularity.totalStars) / (maxStars || 1);
const percentage = Math.min(
100,
Math.max(5, (entry.popularity.totalStars / (maxStars || 1)) * 100)
Math.max(5, Math.round(Math.sqrt(rawRatio) * 1000) / 10)
);
const formattedStars = formatNumber(entry.popularity.totalStars, i18n.language);
const formattedNewRepos = formatNumber(entry.momentum.newReposLast30Days, i18n.language);
Expand Down Expand Up @@ -712,9 +713,10 @@ const MobileCard: React.FC<TableRowProps> = ({ entry, maxStars }) => {

const isHostedOnGitHub = isGitHubRepo(entry.githubUrl);

const rawRatio = Math.max(0, entry.popularity.totalStars) / (maxStars || 1);
const percentage = Math.min(
100,
Math.max(5, (entry.popularity.totalStars / (maxStars || 1)) * 100)
Math.max(5, Math.round(Math.sqrt(rawRatio) * 1000) / 10)
);
const formattedStars = formatNumber(entry.popularity.totalStars, i18n.language);
const formattedNewRepos = formatNumber(entry.momentum.newReposLast30Days, i18n.language);
Expand All @@ -723,7 +725,7 @@ const MobileCard: React.FC<TableRowProps> = ({ entry, maxStars }) => {
return (
<div
data-tech-id={entry.id}
className="p-4 rounded-2xl bg-white dark:bg-[#1A1A1E] border-[1.5px] border-neutral-300/90 dark:border-neutral-700 shadow-xs dark:shadow-md dark:shadow-black/40 space-y-3.5 transition-colors cv-card"
className="px-4 sm:px-6 py-4 space-y-3.5 hover:bg-neutral-50/60 dark:hover:bg-white/[0.02] transition-colors cv-card"
>
{/* Top: Blurred Icon Container + Name */}
<div className="flex items-center justify-between gap-2">
Expand Down
6 changes: 3 additions & 3 deletions src/components/ThemeToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ export const ThemeToggle: React.FC<ThemeToggleProps> = ({
</button>

{isOpen && (
<div className="w-56 mt-2 rounded-2xl bg-neutral-200/95 dark:bg-neutral-900/95 border border-neutral-300 dark:border-neutral-700 shadow-xl overflow-hidden py-1.5 z-50">
<div className="w-56 mt-2 rounded-2xl bg-neutral-200/95 dark:bg-neutral-900/95 border border-neutral-300 dark:border-neutral-700 shadow-xl p-1.5 flex flex-col gap-0.5 z-50">
<button
onClick={() => handleSelectTheme('dark')}
className={`w-full flex items-center justify-between px-4 py-2.5 text-xs transition-colors ${
className={`w-full flex items-center justify-between px-3 py-2 rounded-xl text-xs transition-colors cursor-pointer ${
theme === 'dark'
? 'bg-[#CEFF00]/15 text-foreground font-bold'
: 'text-neutral-700 dark:text-neutral-300 hover:bg-neutral-300/60 dark:hover:bg-neutral-800/80'
Expand All @@ -75,7 +75,7 @@ export const ThemeToggle: React.FC<ThemeToggleProps> = ({

<button
onClick={() => handleSelectTheme('light')}
className={`w-full flex items-center justify-between px-4 py-2.5 text-xs transition-colors ${
className={`w-full flex items-center justify-between px-3 py-2 rounded-xl text-xs transition-colors cursor-pointer ${
theme === 'light'
? 'bg-[#CEFF00]/15 text-foreground font-bold'
: 'text-neutral-700 dark:text-neutral-300 hover:bg-neutral-300/60 dark:hover:bg-neutral-800/80'
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"latestVersion": "AKTUELLE VERSION",
"community": "COMMUNITY",
"ecosystem": "ÖKOSYSTEM-VOLUMEN",
"github": "GITHUB",
"github": "REPO",
"sortAria": "Sortierkriterium",
"sortName": "Name (A-Z)",
"sortStars": "Meiste Sterne",
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"latestVersion": "LATEST VERSION",
"community": "COMMUNITY",
"ecosystem": "ECOSYSTEM VOLUME",
"github": "GITHUB",
"github": "REPO",
"sortAria": "Sort Criteria",
"sortName": "Name (A-Z)",
"sortStars": "Most Stars",
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"latestVersion": "ÚLTIMA VERSIÓN",
"community": "COMUNIDAD",
"ecosystem": "VOLUMEN DEL ECOSISTEMA",
"github": "GITHUB",
"github": "REPO",
"sortAria": "Criterios de ordenación",
"sortName": "Nombre (A-Z)",
"sortStars": "Más estrellas",
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"latestVersion": "DERNIÈRE VERSION",
"community": "COMMUNAUTÉ",
"ecosystem": "VOLUME DE L'ÉCOSYSTÈME",
"github": "GITHUB",
"github": "REPO",
"sortAria": "Critères de tri",
"sortName": "Nom (A-Z)",
"sortStars": "Plus d'étoiles",
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"latestVersion": "ULTIMA VERSIONE",
"community": "COMMUNITY",
"ecosystem": "VOLUME ECOSISTEMA",
"github": "GITHUB",
"github": "REPO",
"sortAria": "Criteri di ordinamento",
"sortName": "Nome (A-Z)",
"sortStars": "Più stelle",
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"latestVersion": "ÚLTIMA VERSÃO",
"community": "COMUNIDADE",
"ecosystem": "VOLUME DO ECOSSISTEMA",
"github": "GITHUB",
"github": "REPO",
"sortAria": "Critérios de Ordenação",
"sortName": "Nome (A-Z)",
"sortStars": "Mais Estrelas",
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"latestVersion": "ПОСЛЕДНЯЯ ВЕРСИЯ",
"community": "СООБЩЕСТВО",
"ecosystem": "ОБЪЕМ ЭКОСИСТЕМЫ",
"github": "GITHUB",
"github": "REPO",
"sortAria": "Критерии сортировки",
"sortName": "Имя (А-Я / A-Z)",
"sortStars": "Больше звезд",
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"latestVersion": "GÜNCEL SÜRÜM",
"community": "TOPLULUK",
"ecosystem": "EKOSİSTEM HACMİ",
"github": "GİTHUB",
"github": "REPO",
"sortAria": "Sıralama Ölçütü",
"sortName": "İsim (A-Z)",
"sortStars": "En Çok Yıldız",
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"latestVersion": "最新版本",
"community": "社区",
"ecosystem": "生态总量",
"github": "GITHUB",
"github": "REPO",
"sortAria": "排序标准",
"sortName": "名称 (A-Z)",
"sortStars": "星标最多",
Expand Down
Loading