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
27 changes: 6 additions & 21 deletions apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ import {
import { useMemo } from "react";
import { LoadingContent } from "@/components/LoadingContent";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
} from "@/components/ui/card";
import { Card, CardDescription, CardHeader } from "@/components/ui/card";
import {
DropdownMenu,
DropdownMenuContent,
Expand Down Expand Up @@ -494,7 +489,7 @@ export function Rules({
</TableBody>
</Table>
) : (
<NoRules onCreateRule={onCreateRule} />
<NoRules />
)}
Comment on lines +492 to 493
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Empty state lost the “Add Rule” CTA — users can’t create a rule when the list is empty.
The Add button only exists in the table header, which isn’t rendered when hasRules is false. Restore a CTA in the empty state.

Apply these diffs:

For the call site:

-            <NoRules />
+            <NoRules
+              onCreateRule={onCreateRule}
+              showAddRuleButton={showAddRuleButton}
+            />

For the NoRules component:

-function NoRules() {
-  return (
-    <CardHeader>
-      <CardDescription>You don't have any rules yet.</CardDescription>
-    </CardHeader>
-  );
-}
+function NoRules({
+  onCreateRule,
+  showAddRuleButton = true,
+}: {
+  onCreateRule: () => void;
+  showAddRuleButton?: boolean;
+}) {
+  return (
+    <CardHeader className="flex items-center justify-between">
+      <CardDescription>You don't have any rules yet.</CardDescription>
+      {showAddRuleButton && <AddRuleButton onClick={onCreateRule} />}
+    </CardHeader>
+  );
+}

Also applies to: 549-555

🤖 Prompt for AI Agents
In apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx around lines 492-493
(and similarly 549-555), the empty state currently renders <NoRules /> without
the "Add Rule" CTA so users cannot create rules when the list is empty; update
the call sites to pass an onAdd (or onCreateRule) handler/prop (the same handler
used by the table header Add button) into <NoRules onAdd={...} /> and change the
NoRules component to accept that prop and render a visible, accessible "Add
Rule" button in the empty-state UI that invokes the handler (styled/positioned
to match the header CTA and using the same route or modal logic), ensuring
keyboard accessibility and any existing analytics/event hooks are preserved.

</LoadingContent>
</Card>
Expand Down Expand Up @@ -551,21 +546,11 @@ export function ActionBadges({
);
}

function NoRules({ onCreateRule }: { onCreateRule: () => void }) {
function NoRules() {
return (
<>
<CardHeader>
<CardDescription>
You don't have any rules yet.
<br />
You can teach your AI assistant how to handle your emails by chatting
with it or create rules manually.
</CardDescription>
</CardHeader>
<CardContent>
<AddRuleButton onClick={onCreateRule} />
</CardContent>
</>
<CardHeader>
<CardDescription>You don't have any rules yet.</CardDescription>
</CardHeader>
);
}

Expand Down
58 changes: 47 additions & 11 deletions apps/web/app/(app)/[emailAccountId]/setup/SetupContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
type LucideIcon,
ChromeIcon,
} from "lucide-react";
import { useLocalStorage } from "usehooks-ts";
import { PageHeading, SectionDescription } from "@/components/Typography";
import { Card } from "@/components/ui/card";
import { prefixPath } from "@/utils/path";
Expand Down Expand Up @@ -112,6 +113,8 @@ const StepItem = ({
completed,
actionText,
linkProps,
onMarkDone,
showMarkDone,
}: {
href: string;
icon: React.ReactNode;
Expand All @@ -122,12 +125,18 @@ const StepItem = ({
completed: boolean;
actionText: string;
linkProps?: { target?: string; rel?: string };
onMarkDone?: () => void;
showMarkDone?: boolean;
}) => {
const handleMarkDone = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
onMarkDone?.();
};

return (
<Link
<div
className={`border-b border-border last:border-0 ${completed ? "opacity-60" : ""}`}
href={href}
{...linkProps}
>
<div className="flex items-center justify-between gap-8 p-4">
<div className="flex max-w-lg items-center">
Expand All @@ -144,7 +153,7 @@ const StepItem = ({
</div>
</div>

<div className="flex items-center">
<div className="flex items-center gap-2">
{completed ? (
<div className="flex size-6 items-center justify-center rounded-full bg-green-100 dark:bg-green-900/50">
<CheckIcon
Expand All @@ -153,13 +162,29 @@ const StepItem = ({
/>
</div>
) : (
<div className="rounded-md bg-blue-100 px-3 py-1 text-sm text-blue-600 hover:bg-blue-200 dark:bg-blue-900/50 dark:text-blue-400 dark:hover:bg-blue-900/75">
{actionText}
</div>
<>
{showMarkDone && (
<button
type="button"
onClick={handleMarkDone}
className="rounded-md bg-slate-100 px-3 py-1 text-sm text-slate-600 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-400 dark:hover:bg-slate-700"
>
Mark Done
</button>
)}

<Link
href={href}
{...linkProps}
className="rounded-md bg-blue-100 px-3 py-1 text-sm text-blue-600 hover:bg-blue-200 dark:bg-blue-900/50 dark:text-blue-400 dark:hover:bg-blue-900/75"
>
{actionText}
</Link>
</>
)}
</div>
</div>
</Link>
</div>
);
};

Expand All @@ -182,6 +207,15 @@ function Checklist({
isBulkUnsubscribeConfigured: boolean;
isAiAssistantConfigured: boolean;
}) {
const [isExtensionInstalled, setIsExtensionInstalled] = useLocalStorage(
"inbox-zero-extension-installed",
false,
);

const handleMarkExtensionDone = () => {
setIsExtensionInstalled(true);
};

return (
<Card className="mb-6 overflow-hidden">
<div className="border-b border-border p-4">
Expand Down Expand Up @@ -217,8 +251,8 @@ function Checklist({
icon={<ArchiveIcon size={20} />}
iconBg="bg-purple-100 dark:bg-purple-900/50"
iconColor="text-purple-500 dark:text-purple-400"
title="Unsubscribe from emails you don't read"
timeEstimate="5 minutes"
title="Unsubscribe from a newsletter you don't read"
timeEstimate="2 minutes"
completed={isBulkUnsubscribeConfigured}
actionText="View"
/>
Expand All @@ -243,8 +277,10 @@ function Checklist({
iconColor="text-orange-500 dark:text-orange-400"
title="Install the Inbox Zero Tabs extension"
timeEstimate="1 minute"
completed={false}
completed={isExtensionInstalled}
actionText="Install"
onMarkDone={handleMarkExtensionDone}
showMarkDone={true}
/>
)}
</Card>
Expand Down
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2.9.19
v2.9.20
Loading