Files
eranos/src/components/FeedEmptyState.tsx
T
mkfain c74dbb6a3b i18n: translate Feed, FeedModeSwitcher, FeedEmptyState, ReplyContext, PostActionBar, ReactionButton
Extends the feed.* namespace with five new sub-namespaces:
compose.placeholder, tabs (Follows / Following / Global), empty (the
six per-tab + per-mode empty-state messages plus the three CTA labels
that show under them), modeSwitcher (the home feed's mode-picker dropdown
with Agora / All Nostr / Following options, the dropdown trigger's aria
label, and the disabled-Following tooltip), replyContext (Replying to,
the and-joiner, plus a pluralized andOthers_one/andOthers_other), and
actions (Reply / Repost / Undo repost / React / Zap / Share / More + the
Link-copied toast).

PostActionBar's replyLabel prop default went from 'Reply' to undefined;
the component falls back to t('feed.actions.reply') at render time so
existing call sites that pass an already-translated string keep working
unchanged. FeedModeSwitcher's OPTIONS array swapped its hard-coded
label string for an i18nKey suffix, materialized through t() inside the
component.

ar / es / zh / fa / ps / km / sn translations drafted inline; km, sn,
ps, fa still pending native-speaker review.
2026-05-23 19:05:18 -05:00

69 lines
2.3 KiB
TypeScript

import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Users } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useAppContext } from '@/hooks/useAppContext';
import { getStorageKey } from '@/lib/storageKey';
import { cn } from '@/lib/utils';
interface FeedEmptyStateProps {
/** Primary empty-state message. */
message: string;
/** Called when the user clicks "Switch to Global". Omit to hide the button. */
onSwitchToGlobal?: () => void;
/** Show a "Discover people" link to /packs. */
showDiscover?: boolean;
className?: string;
}
/**
* Consistent empty state for Follows/Global feed tabs across all feed pages.
*
* - Follows tab: pass `onSwitchToGlobal` and `showDiscover` to render CTAs.
* - Global tab: omit both; the message should guide the user
* to check their relay connections.
*/
export function FeedEmptyState({
message,
onSwitchToGlobal,
showDiscover,
className,
}: FeedEmptyStateProps) {
const { t } = useTranslation();
const { config } = useAppContext();
// The /packs page defaults to the Follows tab, which is also empty when the
// user doesn't follow anyone. Pre-seed its saved tab to Global so the link
// lands on a populated view.
const handleDiscoverClick = () => {
try {
sessionStorage.setItem(getStorageKey(config.appId, 'feed-tab:packs'), 'global');
} catch { /* sessionStorage unavailable */ }
};
return (
<div className={cn('py-20 px-8 flex flex-col items-center text-center', className)}>
<div className="size-12 rounded-full bg-muted flex items-center justify-center mb-4">
<Users className="size-6 text-muted-foreground" />
</div>
<p className="text-muted-foreground max-w-xs">{message}</p>
{(showDiscover || onSwitchToGlobal) && (
<div className="flex flex-col gap-2 mt-5 w-full max-w-xs">
{showDiscover && (
<Button asChild className="rounded-full">
<Link to="/packs" onClick={handleDiscoverClick}>{t('feed.empty.discoverPeople')}</Link>
</Button>
)}
{onSwitchToGlobal && (
<Button variant="ghost" className="rounded-full" onClick={onSwitchToGlobal}>
{t('feed.empty.browseGlobal')}
</Button>
)}
</div>
)}
</div>
);
}