mirror of
https://github.com/lukevella/rallly.git
synced 2025-08-02 16:09:08 +02:00
⚡️ Faster tab switches (#1701)
This commit is contained in:
parent
486bd50139
commit
590e19ae16
6 changed files with 59 additions and 29 deletions
9
.vscode/settings.json
vendored
9
.vscode/settings.json
vendored
|
@ -1,10 +1,14 @@
|
|||
{
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": "explicit"
|
||||
"source.fixAll.biome": "explicit",
|
||||
"source.organizeImports.biome": "explicit"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.preferences.importModuleSpecifier": "shortest",
|
||||
"cSpell.words": ["Rallly", "Vella"],
|
||||
|
@ -14,5 +18,6 @@
|
|||
"typescript.preferences.preferTypeOnlyAutoImports": true,
|
||||
"typescript.tsserver.log": "verbose",
|
||||
"typescript.tsserver.trace": "messages",
|
||||
"references.preferredLocation": "view"
|
||||
"references.preferredLocation": "view",
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"use client";
|
||||
import { cn } from "@rallly/ui";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@rallly/ui/page-tabs";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import React from "react";
|
||||
|
@ -9,6 +10,8 @@ export function EventsTabbedView({ children }: { children: React.ReactNode }) {
|
|||
const searchParams = useSearchParams();
|
||||
const name = "status";
|
||||
const router = useRouter();
|
||||
const [isPending, startTransition] = React.useTransition();
|
||||
const [tab, setTab] = React.useState(searchParams.get(name) ?? "upcoming");
|
||||
const handleTabChange = React.useCallback(
|
||||
(value: string) => {
|
||||
const params = new URLSearchParams(searchParams);
|
||||
|
@ -17,15 +20,16 @@ export function EventsTabbedView({ children }: { children: React.ReactNode }) {
|
|||
params.delete("page");
|
||||
|
||||
const newUrl = `?${params.toString()}`;
|
||||
router.replace(newUrl, { scroll: false });
|
||||
startTransition(() => {
|
||||
setTab(value);
|
||||
router.replace(newUrl, { scroll: false });
|
||||
});
|
||||
},
|
||||
[router, searchParams],
|
||||
);
|
||||
|
||||
const value = searchParams.get(name) ?? "upcoming";
|
||||
|
||||
return (
|
||||
<Tabs value={value} onValueChange={handleTabChange}>
|
||||
<Tabs value={tab} onValueChange={handleTabChange}>
|
||||
<TabsList>
|
||||
<TabsTrigger value="upcoming">
|
||||
<Trans i18nKey="upcoming" defaults="Upcoming" />
|
||||
|
@ -34,7 +38,15 @@ export function EventsTabbedView({ children }: { children: React.ReactNode }) {
|
|||
<Trans i18nKey="past" defaults="Past" />
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent tabIndex={-1} value={value} key={value}>
|
||||
<TabsContent
|
||||
tabIndex={-1}
|
||||
value={tab}
|
||||
key={tab}
|
||||
className={cn(
|
||||
"transition-opacity",
|
||||
isPending ? "opacity-50 delay-200 pointer-events-none" : "",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
|
|
@ -138,13 +138,13 @@ export default async function Page({
|
|||
</PageDescription>
|
||||
</PageHeader>
|
||||
<PageContent>
|
||||
<EventsTabbedView>
|
||||
<div className="space-y-4">
|
||||
<SearchInput
|
||||
placeholder={t("searchEventsPlaceholder", {
|
||||
defaultValue: "Search events by title...",
|
||||
})}
|
||||
/>
|
||||
<div className="space-y-4">
|
||||
<SearchInput
|
||||
placeholder={t("searchEventsPlaceholder", {
|
||||
defaultValue: "Search events by title...",
|
||||
})}
|
||||
/>
|
||||
<EventsTabbedView>
|
||||
<div className="space-y-6">
|
||||
{paginatedEvents.length === 0 && (
|
||||
<ScheduledEventEmptyState status={status} />
|
||||
|
@ -177,8 +177,8 @@ export default async function Page({
|
|||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</EventsTabbedView>
|
||||
</EventsTabbedView>
|
||||
</div>
|
||||
</PageContent>
|
||||
</PageContainer>
|
||||
);
|
||||
|
|
|
@ -168,13 +168,13 @@ export default async function Page({
|
|||
</div>
|
||||
</div>
|
||||
<PageContent className="space-y-4">
|
||||
<SearchInput
|
||||
placeholder={t("searchPollsPlaceholder", {
|
||||
defaultValue: "Search polls by title...",
|
||||
})}
|
||||
/>
|
||||
<PollsTabbedView>
|
||||
<div className="space-y-4">
|
||||
<SearchInput
|
||||
placeholder={t("searchPollsPlaceholder", {
|
||||
defaultValue: "Search polls by title...",
|
||||
})}
|
||||
/>
|
||||
{polls.length === 0 ? (
|
||||
<PollsEmptyState />
|
||||
) : (
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
"use client";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@rallly/ui/page-tabs";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import React from "react";
|
||||
|
||||
import { Trans } from "@/components/trans";
|
||||
|
||||
import { cn } from "@rallly/ui";
|
||||
import React from "react";
|
||||
|
||||
export function PollsTabbedView({ children }: { children: React.ReactNode }) {
|
||||
const searchParams = useSearchParams();
|
||||
const name = "status";
|
||||
const router = useRouter();
|
||||
const [isPending, startTransition] = React.useTransition();
|
||||
const [tab, setTab] = React.useState(searchParams.get(name) ?? "live");
|
||||
const handleTabChange = React.useCallback(
|
||||
(value: string) => {
|
||||
const params = new URLSearchParams(searchParams);
|
||||
|
@ -16,16 +20,17 @@ export function PollsTabbedView({ children }: { children: React.ReactNode }) {
|
|||
|
||||
params.delete("page");
|
||||
|
||||
const newUrl = `?${params.toString()}`;
|
||||
router.replace(newUrl, { scroll: false });
|
||||
startTransition(() => {
|
||||
setTab(value);
|
||||
const newUrl = `?${params.toString()}`;
|
||||
router.replace(newUrl, { scroll: false });
|
||||
});
|
||||
},
|
||||
[router, searchParams],
|
||||
);
|
||||
|
||||
const value = searchParams.get(name) ?? "live";
|
||||
|
||||
return (
|
||||
<Tabs value={value} onValueChange={handleTabChange}>
|
||||
<Tabs value={tab} onValueChange={handleTabChange}>
|
||||
<TabsList>
|
||||
<TabsTrigger value="live">
|
||||
<Trans i18nKey="pollStatusOpen" defaults="Live" />
|
||||
|
@ -37,7 +42,15 @@ export function PollsTabbedView({ children }: { children: React.ReactNode }) {
|
|||
<Trans i18nKey="pollStatusFinalized" defaults="Finalized" />
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent tabIndex={-1} value={value} key={value}>
|
||||
<TabsContent
|
||||
tabIndex={-1}
|
||||
value={tab}
|
||||
key={tab}
|
||||
className={cn(
|
||||
"transition-opacity",
|
||||
isPending ? "opacity-50 delay-200 pointer-events-none" : "",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
|
|
@ -18,7 +18,7 @@ const Progress = React.forwardRef<
|
|||
{...props}
|
||||
>
|
||||
<ProgressPrimitive.Indicator
|
||||
className="bg-primary h-full w-full flex-1 transition-all"
|
||||
className="bg-gradient-to-r from-purple-500 to-indigo-500 h-full w-full flex-1 transition-all"
|
||||
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
||||
/>
|
||||
</ProgressPrimitive.Root>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue