Skip to content

Commit 583d299

Browse files
authored
chore(webapp): Concurrency page UI improvements (#2825)
### UI Improvements to the Concurrency page: - Truncates long branch names and includes a tooltip - The Tables have a new variant if you don't want the rows to highlight on hover - Small fix to pluralize some words in the purchase modal - Fix to prevent tooltip buttons being `type=submit` - Updates the /limits docs page to include purchasing more concurrency - Adds a clear banner when you have a positive balance of unallocated concurrency https://github.com/user-attachments/assets/54d927c3-84e3-4d55-8f42-726098f4daf0
1 parent 1733805 commit 583d299

File tree

6 files changed

+64
-15
lines changed

6 files changed

+64
-15
lines changed

apps/webapp/app/components/environments/EnvironmentLabel.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,28 +51,40 @@ export function EnvironmentCombo({
5151
environment,
5252
className,
5353
iconClassName,
54+
tooltipSideOffset,
55+
tooltipSide,
5456
}: {
5557
environment: Environment;
5658
className?: string;
5759
iconClassName?: string;
60+
tooltipSideOffset?: number;
61+
tooltipSide?: "top" | "right" | "bottom" | "left";
5862
}) {
5963
return (
6064
<span className={cn("flex items-center gap-1.5 text-sm text-text-bright", className)}>
6165
<EnvironmentIcon
6266
environment={environment}
6367
className={cn("size-4.5 shrink-0", iconClassName)}
6468
/>
65-
<EnvironmentLabel environment={environment} />
69+
<EnvironmentLabel
70+
environment={environment}
71+
tooltipSideOffset={tooltipSideOffset}
72+
tooltipSide={tooltipSide}
73+
/>
6674
</span>
6775
);
6876
}
6977

7078
export function EnvironmentLabel({
7179
environment,
7280
className,
81+
tooltipSideOffset = 34,
82+
tooltipSide = "right",
7383
}: {
7484
environment: Environment;
7585
className?: string;
86+
tooltipSideOffset?: number;
87+
tooltipSide?: "top" | "right" | "bottom" | "left";
7688
}) {
7789
const spanRef = useRef<HTMLSpanElement>(null);
7890
const [isTruncated, setIsTruncated] = useState(false);
@@ -115,9 +127,10 @@ export function EnvironmentLabel({
115127
{text}
116128
</span>
117129
}
118-
side="right"
130+
side={tooltipSide}
119131
variant="dark"
120-
sideOffset={34}
132+
sideOffset={tooltipSideOffset}
133+
disableHoverableContent
121134
/>
122135
);
123136
}

apps/webapp/app/components/primitives/Buttons.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ export const LinkButton = ({
389389
to={to}
390390
ref={innerRef}
391391
replace={replace}
392-
className={cn("group/button block focus-custom", props.fullWidth ? "w-full" : "")}
392+
className={cn("group/button block focus-custom", props.fullWidth ? "w-full" : "w-fit")}
393393
onClick={onClick}
394394
onMouseDown={onMouseDown}
395395
onMouseEnter={onMouseEnter}

apps/webapp/app/components/primitives/Table.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ const variants = {
1515
menuButtonDivider: "group-hover/table-row:border-charcoal-600/70",
1616
rowSelected: "bg-charcoal-750 group-hover/table-row:bg-charcoal-750",
1717
},
18+
"bright/no-hover": {
19+
header: "bg-transparent",
20+
cell: "group-hover/table-row:bg-transparent",
21+
stickyCell: "bg-background-bright",
22+
menuButton: "bg-background-bright",
23+
menuButtonDivider: "",
24+
rowSelected: "bg-charcoal-750",
25+
},
1826
dimmed: {
1927
header: "bg-background-dimmed",
2028
cell: "group-hover/table-row:bg-charcoal-800 group-has-[[tabindex='0']:focus]/table-row:bg-background-bright",

apps/webapp/app/components/primitives/Tooltip.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ function SimpleTooltip({
8585
<TooltipProvider disableHoverableContent={disableHoverableContent}>
8686
<Tooltip open={open} onOpenChange={onOpenChange}>
8787
<TooltipTrigger
88+
type="button"
8889
tabIndex={-1}
8990
className={cn("h-fit", buttonClassName)}
9091
style={buttonStyle}

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.concurrency/route.tsx

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { conform, useFieldList, useForm } from "@conform-to/react";
22
import { parse } from "@conform-to/zod";
33
import {
4+
ArrowDownIcon,
45
EnvelopeIcon,
56
ExclamationTriangleIcon,
67
InformationCircleIcon,
@@ -18,6 +19,7 @@ import {
1819
import { json, type ActionFunctionArgs, type LoaderFunctionArgs } from "@remix-run/server-runtime";
1920
import { tryCatch } from "@trigger.dev/core";
2021
import { useEffect, useState } from "react";
22+
import simplur from "simplur";
2123
import { typedjson, useTypedLoaderData } from "remix-typedjson";
2224
import { z } from "zod";
2325
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
@@ -331,7 +333,7 @@ function Upgradable({
331333
disabled={unallocated < 0 ? false : allocationModified}
332334
/>
333335
</div>
334-
<Table>
336+
<Table variant="bright/no-hover">
335337
<TableBody>
336338
<TableRow>
337339
<TableCell className="pl-0 text-text-bright">Extra concurrency purchased</TableCell>
@@ -379,8 +381,15 @@ function Upgradable({
379381
)}
380382
</TableCell>
381383
</TableRow>
382-
<TableRow className={allocationModified ? undefined : "after:bg-transparent"}>
383-
<TableCell colSpan={2} className="py-0">
384+
<TableRow
385+
className={
386+
allocationModified || unallocated > 0 ? undefined : "after:bg-transparent"
387+
}
388+
>
389+
<TableCell
390+
colSpan={2}
391+
className={cn("py-0", (unallocated > 0 || allocationModified) && "pr-0")}
392+
>
384393
<div className="flex h-10 items-center">
385394
{allocationModified ? (
386395
unallocated < 0 ? (
@@ -419,6 +428,16 @@ function Upgradable({
419428
</Button>
420429
</div>
421430
)
431+
) : unallocated > 0 ? (
432+
<div className="flex h-full w-full items-center justify-between bg-success/10 px-2.5">
433+
<div className="flex items-center justify-start gap-1">
434+
<InformationCircleIcon className="size-4 text-success" />
435+
<span className="text-success">
436+
You have {unallocated} extra concurrency available to allocate below.
437+
</span>
438+
</div>
439+
<ArrowDownIcon className="size-4 animate-bounce text-success" />
440+
</div>
422441
) : (
423442
<></>
424443
)}
@@ -434,7 +453,7 @@ function Upgradable({
434453
<div className="flex items-center pb-1">
435454
<Header3 className="grow">Concurrency allocation</Header3>
436455
</div>
437-
<Table>
456+
<Table variant="bright/no-hover">
438457
<TableHeader>
439458
<TableRow>
440459
<TableHeaderCell className="pl-0">Environment</TableHeaderCell>
@@ -452,7 +471,12 @@ function Upgradable({
452471
{environments.map((environment, index) => (
453472
<TableRow key={environment.id}>
454473
<TableCell>
455-
<EnvironmentCombo environment={environment} />
474+
<EnvironmentCombo
475+
environment={environment}
476+
className="max-w-[18ch]"
477+
tooltipSideOffset={6}
478+
tooltipSide="top"
479+
/>
456480
</TableCell>
457481
<TableCell alignment="right">{environment.planConcurrencyLimit}</TableCell>
458482
<TableCell alignment="right">
@@ -523,7 +547,7 @@ function NotUpgradable({ environments }: { environments: EnvironmentWithConcurre
523547
</>
524548
) : null}
525549
<div className="mt-3 flex flex-col gap-3">
526-
<Table>
550+
<Table variant="bright/no-hover">
527551
<TableHeader>
528552
<TableRow>
529553
<TableHeaderCell className="pl-0">Environment</TableHeaderCell>
@@ -682,7 +706,7 @@ function PurchaseConcurrencyModal({
682706
</div>
683707
<div className="grid grid-cols-2 text-xs">
684708
<span className="text-text-dimmed">
685-
({extraConcurrency / concurrencyPricing.stepSize} bundles)
709+
({simplur`${extraConcurrency / concurrencyPricing.stepSize} bundle[|s]`})
686710
</span>
687711
<span className="justify-self-end text-text-dimmed">/mth</span>
688712
</div>
@@ -703,8 +727,11 @@ function PurchaseConcurrencyModal({
703727
</div>
704728
<div className="grid grid-cols-2 text-xs">
705729
<span className="text-text-dimmed">
706-
({(amountValue - extraConcurrency) / concurrencyPricing.stepSize} bundles @{" "}
707-
{formatCurrency(concurrencyPricing.centsPerStep / 100, true)}/mth)
730+
(
731+
{simplur`${
732+
(amountValue - extraConcurrency) / concurrencyPricing.stepSize
733+
} bundle[|s]`}{" "}
734+
@ {formatCurrency(concurrencyPricing.centsPerStep / 100, true)}/mth)
708735
</span>
709736
<span className="justify-self-end text-text-dimmed">/mth</span>
710737
</div>
@@ -723,7 +750,7 @@ function PurchaseConcurrencyModal({
723750
</div>
724751
<div className="grid grid-cols-2 text-xs">
725752
<span className="text-text-dimmed">
726-
({amountValue / concurrencyPricing.stepSize} bundles)
753+
({simplur`${amountValue / concurrencyPricing.stepSize} bundle[|s]`})
727754
</span>
728755
<span className="justify-self-end text-text-dimmed">/mth</span>
729756
</div>

docs/limits.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import RateLimitHitUseBatchTrigger from "/snippets/rate-limit-hit-use-batchtrigg
1313
| Hobby | 25 concurrent runs |
1414
| Pro | 100+ concurrent runs |
1515

16-
Additional bundles above the Pro tier are available for $50/month per 50 concurrent runs. Contact us via [email](https://trigger.dev/contact) or [Discord](https://trigger.dev/discord) to request more.
16+
Extra concurrency above the Pro tier limit is available via the dashboard. Click the "Concurrency" page from the left sidebar when on the Pro plan to purchase more.
1717

1818
## Rate limits
1919

0 commit comments

Comments
 (0)