Skip to content
4 changes: 2 additions & 2 deletions apps/webapp/app/components/ImpersonationBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { UserMinusIcon } from "@heroicons/react/20/solid";
import { Form } from "@remix-run/react";
import { Paragraph } from "./primitives/Paragraph";
import { Button } from "./primitives/Buttons";
import { UserMinusIcon } from "@heroicons/react/20/solid";

export function ImpersonationBanner() {
return (
Expand All @@ -13,6 +12,7 @@ export function ImpersonationBanner() {
LeadingIcon={UserMinusIcon}
fullWidth
textAlignLeft
className="text-amber-400"
>
Stop impersonating
</Button>
Expand Down
69 changes: 42 additions & 27 deletions apps/webapp/app/components/SetupCommands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from "./primitives/ClientTabs";
import { ClipboardField } from "./primitives/ClipboardField";
import { Paragraph } from "./primitives/Paragraph";
import { Header3 } from "./primitives/Headers";

type PackageManagerContextType = {
activePackageManager: string;
Expand Down Expand Up @@ -61,7 +62,12 @@ function getApiUrlArg() {
return apiUrl ? `-a ${apiUrl}` : undefined;
}

export function InitCommandV3() {
// Add title prop to the component interfaces
type TabsProps = {
title?: string;
};

export function InitCommandV3({ title }: TabsProps) {
const project = useProject();
const projectRef = project.externalRef;
const apiUrlArg = getApiUrlArg();
Expand All @@ -77,30 +83,33 @@ export function InitCommandV3() {
value={activePackageManager}
onValueChange={setActivePackageManager}
>
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<div className="flex items-center gap-4">
{title && <span>{title}</span>}
<ClientTabsList className={title ? "ml-auto" : ""}>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
</div>
<ClientTabsContent value={"npm"}>
<ClipboardField
variant="primary/medium"
variant="secondary/medium"
iconButton
className="mb-4"
value={`npx ${initCommand}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
variant="secondary/medium"
iconButton
className="mb-4"
value={`pnpm dlx ${initCommand}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
variant="secondary/medium"
iconButton
className="mb-4"
value={`yarn dlx ${initCommand}`}
Expand All @@ -110,7 +119,7 @@ export function InitCommandV3() {
);
}

export function TriggerDevStepV3() {
export function TriggerDevStepV3({ title }: TabsProps) {
const { activePackageManager, setActivePackageManager } = usePackageManager();

return (
Expand All @@ -119,30 +128,33 @@ export function TriggerDevStepV3() {
value={activePackageManager}
onValueChange={setActivePackageManager}
>
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<div className="flex items-center gap-4">
{title && <Header3>{title}</Header3>}
<ClientTabsList className={title ? "ml-auto" : ""}>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
</div>
<ClientTabsContent value={"npm"}>
<ClipboardField
variant="primary/medium"
variant="secondary/medium"
iconButton
className="mb-4"
value={`npx trigger.dev@${v3PackageTag} dev`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
variant="secondary/medium"
iconButton
className="mb-4"
value={`pnpm dlx trigger.dev@${v3PackageTag} dev`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
variant="secondary/medium"
iconButton
className="mb-4"
value={`yarn dlx trigger.dev@${v3PackageTag} dev`}
Expand All @@ -152,7 +164,7 @@ export function TriggerDevStepV3() {
);
}

export function TriggerLoginStepV3() {
export function TriggerLoginStepV3({ title }: TabsProps) {
const { activePackageManager, setActivePackageManager } = usePackageManager();

return (
Expand All @@ -161,30 +173,33 @@ export function TriggerLoginStepV3() {
value={activePackageManager}
onValueChange={setActivePackageManager}
>
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<div className="flex items-center gap-4">
{title && <span>{title}</span>}
<ClientTabsList className={title ? "ml-auto" : ""}>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
</div>
<ClientTabsContent value={"npm"}>
<ClipboardField
variant="primary/medium"
variant="secondary/medium"
iconButton
className="mb-4"
value={`npx trigger.dev@${v3PackageTag} login`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
variant="secondary/medium"
iconButton
className="mb-4"
value={`pnpm dlx trigger.dev@${v3PackageTag} login`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
variant="secondary/medium"
iconButton
className="mb-4"
value={`yarn dlx trigger.dev@${v3PackageTag} login`}
Expand Down
7 changes: 3 additions & 4 deletions apps/webapp/app/components/navigation/EnvironmentSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useNavigation } from "@remix-run/react";
import { useEffect, useState } from "react";
import { useEnvironmentSwitcher } from "~/hooks/useEnvironmentSwitcher";
import { useFeatures } from "~/hooks/useFeatures";
import { type MatchedOrganization } from "~/hooks/useOrganizations";
import { cn } from "~/utils/cn";
import { v3BillingPath } from "~/utils/pathBuilder";
import { EnvironmentCombo } from "../environments/EnvironmentLabel";
import {
Popover,
Expand All @@ -11,10 +14,6 @@ import {
PopoverSectionHeader,
} from "../primitives/Popover";
import { type SideMenuEnvironment, type SideMenuProject } from "./SideMenu";
import { cn } from "~/utils/cn";
import { useFeatures } from "~/hooks/useFeatures";
import { v3BillingPath } from "~/utils/pathBuilder";
import { TextLink } from "../primitives/TextLink";

export function EnvironmentSelector({
organization,
Expand Down
72 changes: 34 additions & 38 deletions apps/webapp/app/components/navigation/SideMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,11 @@ import {
v3TestPath,
v3UsagePath,
} from "~/utils/pathBuilder";
import { useDevPresence } from "../DevPresence";
import { ImpersonationBanner } from "../ImpersonationBanner";
import { PackageManagerProvider, TriggerDevStepV3 } from "../SetupCommands";
import { UserProfilePhoto } from "../UserProfilePhoto";
import connectedImage from "../../assets/images/cli-connected.png";
import disconnectedImage from "../../assets/images/cli-disconnected.png";
import { FreePlanUsage } from "../billing/FreePlanUsage";
import { useDevPresence } from "../DevPresence";
import { ImpersonationBanner } from "../ImpersonationBanner";
import { Button, ButtonContent, LinkButton } from "../primitives/Buttons";
import {
Dialog,
Expand All @@ -80,18 +78,15 @@ import {
PopoverTrigger,
} from "../primitives/Popover";
import { TextLink } from "../primitives/TextLink";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../primitives/Tooltip";
import { PackageManagerProvider, TriggerDevStepV3 } from "../SetupCommands";
import { UserProfilePhoto } from "../UserProfilePhoto";
import { EnvironmentSelector } from "./EnvironmentSelector";
import { HelpAndFeedback } from "./HelpAndFeedbackPopover";
import { SideMenuHeader } from "./SideMenuHeader";
import { SideMenuItem } from "./SideMenuItem";
import { SideMenuSection } from "./SideMenuSection";
import {
SimpleTooltip,
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "../primitives/Tooltip";
import { InlineCode } from "../code/InlineCode";

type SideMenuUser = Pick<User, "email" | "admin"> & { isImpersonating: boolean };
export type SideMenuProject = Pick<
Expand Down Expand Up @@ -144,8 +139,8 @@ export function SideMenu({
>
<div
className={cn(
"flex items-center justify-between px-1 py-1 transition",
showHeaderDivider ? " border-grid-bright" : "border-transparent"
"flex items-center justify-between border-b px-1 py-1 transition duration-300",
showHeaderDivider ? "border-grid-bright" : "border-transparent"
)}
>
<ProjectSelector
Expand Down Expand Up @@ -303,7 +298,10 @@ function ProjectSelector({
<PopoverArrowTrigger
isOpen={isOrgMenuOpen}
overflowHidden
className="h-8 w-full justify-between overflow-hidden py-1 pl-1.5"
className={cn(
"h-8 w-full justify-between overflow-hidden py-1 pl-1.5",
user.isImpersonating && "border border-dashed border-amber-400"
)}
>
<span className="flex items-center gap-1.5 overflow-hidden">
<Avatar avatar={organization.avatar} className="size-5" />
Expand All @@ -320,25 +318,26 @@ function ProjectSelector({
>
<div className="flex flex-col gap-2 bg-charcoal-750 p-2">
<div className="flex items-center gap-2.5">
<div className="box-content size-10 overflow-clip rounded-sm border border-charcoal-700 bg-charcoal-850">
<div className="box-content size-10 overflow-clip rounded-sm bg-charcoal-800">
<Avatar avatar={organization.avatar} className="size-10" includePadding />
</div>
<div className="space-y-0.5">
<Paragraph variant="extra-small/bright">{organization.title}</Paragraph>
<div className="flex items-baseline">
<Paragraph variant="small/bright">{organization.title}</Paragraph>
<div className="flex items-baseline gap-2">
{plan && (
<Paragraph variant="extra-small">
<TextLink variant="secondary" to={v3BillingPath(organization)}>
{plan}
</TextLink>
</Paragraph>
)}
<Paragraph variant="extra-small">
<TextLink
variant="secondary"
to={organizationTeamPath(organization)}
>{simplur`${organization.membersCount} member[|s]`}</TextLink>
</Paragraph>
className="text-xs"
to={v3BillingPath(organization)}
>
{plan}
</TextLink>
)}
<TextLink
variant="secondary"
className="text-xs"
to={organizationTeamPath(organization)}
>{simplur`${organization.membersCount} member[|s]`}</TextLink>
</div>
</div>
</div>
Expand All @@ -348,6 +347,7 @@ function ProjectSelector({
to={organizationSettingsPath(organization)}
fullWidth
iconSpacing="gap-1.5"
className="group-hover/button:border-charcoal-500"
>
<CogIcon className="size-4 text-text-dimmed" />
<span className="text-text-bright">Settings</span>
Expand All @@ -357,6 +357,7 @@ function ProjectSelector({
to={v3UsagePath(organization)}
fullWidth
iconSpacing="gap-1.5"
className="group-hover/button:border-charcoal-500"
>
<ChartBarIcon className="size-4 text-text-dimmed" />
<span className="text-text-bright">Usage</span>
Expand Down Expand Up @@ -550,9 +551,7 @@ export function DevConnection() {
</div>
<DialogContent>
<DialogHeader>
{isConnected
? "Your dev server is connected to Trigger.dev"
: "Your dev server is not connected to Trigger.dev"}
{isConnected ? "Your dev server is connected" : "Your dev server is not connected"}
</DialogHeader>
<div className="mt-2 flex flex-col gap-3 px-2">
<div className="flex flex-col items-center justify-center gap-6 px-6 py-10">
Expand All @@ -571,20 +570,17 @@ export function DevConnection() {
{isConnected ? null : (
<div className="space-y-3">
<PackageManagerProvider>
<TriggerDevStepV3 />
<TriggerDevStepV3 title="Run this command to connect" />
</PackageManagerProvider>
<Paragraph variant="small">
Run this CLI `dev` command to connect to the Trigger.dev servers to start developing
locally. Keep it running while you develop to stay connected.
Run this CLI <InlineCode variant="extra-small">dev</InlineCode> command to connect
to the Trigger.dev servers to start developing locally. Keep it running while you
develop to stay connected. Learn more in the{" "}
<TextLink to={docsPath("cli-dev")}>CLI docs</TextLink>.
</Paragraph>
</div>
)}
</div>
<DialogFooter>
<LinkButton variant="tertiary/medium" LeadingIcon={BookOpenIcon} to={docsPath("cli-dev")}>
CLI docs
</LinkButton>
</DialogFooter>
</DialogContent>
</Dialog>
);
Expand Down
8 changes: 4 additions & 4 deletions apps/webapp/app/components/navigation/SideMenuSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ export function SideMenuSection({
expanded: {
height: "auto",
transition: {
height: { duration: 0.3, ease: "easeOut" },
height: { duration: 0.3, ease: "easeInOut" },
},
},
collapsed: {
height: 0,
transition: {
height: { duration: 0.2, ease: "easeIn" },
height: { duration: 0.2, ease: "easeInOut" },
},
},
}}
Expand All @@ -67,12 +67,12 @@ export function SideMenuSection({
expanded: {
translateY: 0,
opacity: 1,
transition: { duration: 0.3, ease: "easeOut" },
transition: { duration: 0.3, ease: "easeInOut" },
},
collapsed: {
translateY: "-100%",
opacity: 0,
transition: { duration: 0.2, ease: "easeIn" },
transition: { duration: 0.2, ease: "easeInOut" },
},
}}
>
Expand Down
Loading