dashboard storybook improvements (#4369)
## Problem solved
Short description of the bug fixed or feature added
<!-- start pr-codex -->
---
## PR-Codex overview
This PR adds mobile viewport options to Storybook stories and updates UI components for mobile viewports.
### Detailed summary
- Added mobile viewport options to Storybook stories
- Updated UI components for mobile viewports in various settings pages and embedded wallets
- Adjusted button sizes and styles for different viewport sizes
> The following files were skipped due to too many changes: `pnpm-lock.yaml`, `apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/Sidebar.stories.tsx`
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
This commit is contained in:
@@ -52,7 +52,7 @@ function StoryLayout(props: {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-end p-4 border-b mb-5 gap-2">
|
||||
<div className="flex justify-end p-4 border-b gap-2">
|
||||
<Button
|
||||
onClick={() => setTheme("dark")}
|
||||
size="sm"
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
"@storybook/addon-interactions": "^8.2.9",
|
||||
"@storybook/addon-links": "^8.2.9",
|
||||
"@storybook/addon-onboarding": "^8.2.9",
|
||||
"@storybook/addon-viewport": "^8.2.9",
|
||||
"@storybook/blocks": "^8.2.9",
|
||||
"@storybook/nextjs": "^8.2.9",
|
||||
"@storybook/react": "^8.2.9",
|
||||
|
||||
@@ -3,42 +3,36 @@ import { ThirdwebProvider } from "thirdweb/react";
|
||||
import type { Project } from "../../../../@/api/projects";
|
||||
import type { Team } from "../../../../@/api/team";
|
||||
import { Button } from "../../../../@/components/ui/button";
|
||||
import { Separator } from "../../../../@/components/ui/separator";
|
||||
import { BadgeContainer } from "../../../../stories/utils";
|
||||
import { BadgeContainer, mobileViewport } from "../../../../stories/utils";
|
||||
import { TeamHeaderDesktopUI, TeamHeaderMobileUI } from "./TeamHeaderUI";
|
||||
|
||||
const meta = {
|
||||
title: "Team/Team selector",
|
||||
component: Story,
|
||||
component: Variants,
|
||||
parameters: {
|
||||
nextjs: {
|
||||
appDirectory: true,
|
||||
},
|
||||
},
|
||||
} satisfies Meta<typeof Story>;
|
||||
} satisfies Meta<typeof Variants>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const AllVariants: Story = {
|
||||
args: {},
|
||||
export const Desktop: Story = {
|
||||
args: {
|
||||
type: "desktop",
|
||||
},
|
||||
};
|
||||
|
||||
function Story() {
|
||||
return (
|
||||
<div className="dark:bg-zinc-900 bg-zinc-300 p-6">
|
||||
<h2 className="text-3xl mb-6 font-semibold tracking-tight">Desktop</h2>
|
||||
<Variants type="desktop" />
|
||||
<Separator className="my-10" />
|
||||
<h2 className="mt-10 mb-6 text-3xl font-semibold tracking-tight">
|
||||
Mobile
|
||||
</h2>
|
||||
<div className="w-[400px]">
|
||||
<Variants type="mobile" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export const Mobile: Story = {
|
||||
args: {
|
||||
type: "mobile",
|
||||
},
|
||||
parameters: {
|
||||
viewport: mobileViewport("iphone14"),
|
||||
},
|
||||
};
|
||||
|
||||
function Variants(props: {
|
||||
type: "mobile" | "desktop";
|
||||
@@ -48,7 +42,9 @@ function Variants(props: {
|
||||
|
||||
return (
|
||||
<ThirdwebProvider>
|
||||
<div className={"flex flex-col gap-6"}>
|
||||
<div
|
||||
className={"flex flex-col gap-6 bg-gray-700 px-4 py-10 min-h-screen"}
|
||||
>
|
||||
<BadgeContainer label="Team, Free">
|
||||
<Comp
|
||||
teamsAndProjects={teamsAndProjects}
|
||||
|
||||
+13
-3
@@ -1,5 +1,8 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { BadgeContainer } from "../../../../../../../stories/utils";
|
||||
import {
|
||||
BadgeContainer,
|
||||
mobileViewport,
|
||||
} from "../../../../../../../stories/utils";
|
||||
import { DangerSettingCard } from "./DangerSettingCard";
|
||||
|
||||
const meta = {
|
||||
@@ -15,13 +18,20 @@ const meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const AllVariants: Story = {
|
||||
export const Desktop: Story = {
|
||||
args: {},
|
||||
};
|
||||
|
||||
export const Mobile: Story = {
|
||||
args: {},
|
||||
parameters: {
|
||||
viewport: mobileViewport("iphone14"),
|
||||
},
|
||||
};
|
||||
|
||||
function Story() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground">
|
||||
<div className="min-h-screen bg-background text-foreground py-4">
|
||||
<div className="lg:p-10 container max-w-[1000px] flex flex-col gap-8">
|
||||
<BadgeContainer label="Base">
|
||||
<DangerSettingCard
|
||||
|
||||
+9
-1
@@ -1,6 +1,7 @@
|
||||
import type { Team } from "@/api/team";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { mobileViewport } from "../../../../../../../stories/utils";
|
||||
import SettingsLayout from "../layout";
|
||||
import {
|
||||
DeleteTeamCard,
|
||||
@@ -21,10 +22,17 @@ const meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const AllVariants: Story = {
|
||||
export const Desktop: Story = {
|
||||
args: {},
|
||||
};
|
||||
|
||||
export const Mobile: Story = {
|
||||
args: {},
|
||||
parameters: {
|
||||
viewport: mobileViewport("iphone14"),
|
||||
},
|
||||
};
|
||||
|
||||
const testTeam: Team = {
|
||||
id: "team-id-foo-bar",
|
||||
name: "Team XYZ",
|
||||
|
||||
+13
-3
@@ -1,5 +1,8 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { BadgeContainer } from "../../../../../../../stories/utils";
|
||||
import {
|
||||
BadgeContainer,
|
||||
mobileViewport,
|
||||
} from "../../../../../../../stories/utils";
|
||||
import { SettingsCard } from "./SettingsCard";
|
||||
|
||||
const meta = {
|
||||
@@ -15,13 +18,20 @@ const meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const AllVariants: Story = {
|
||||
export const Desktop: Story = {
|
||||
args: {},
|
||||
};
|
||||
|
||||
export const Mobile: Story = {
|
||||
args: {},
|
||||
parameters: {
|
||||
viewport: mobileViewport("iphone14"),
|
||||
},
|
||||
};
|
||||
|
||||
function Story() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground">
|
||||
<div className="min-h-screen bg-background text-foreground py-6">
|
||||
<div className="lg:p-10 container max-w-[1100px] flex flex-col gap-10">
|
||||
<BadgeContainer label="No Header">
|
||||
<SettingsCard
|
||||
|
||||
+48
-72
@@ -1,6 +1,8 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { Badge } from "../../../../../../../@/components/ui/badge";
|
||||
import { cn } from "../../../../../../../@/lib/utils";
|
||||
import {
|
||||
BadgeContainer,
|
||||
mobileViewport,
|
||||
} from "../../../../../../../stories/utils";
|
||||
import { TeamSettingsSidebar } from "../_components/sidebar/TeamSettingsSidebar";
|
||||
import { TeamSettingsMobileNav } from "../_components/sidebar/TeamsMobileNav";
|
||||
|
||||
@@ -17,83 +19,57 @@ const meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const AllVariants: Story = {
|
||||
export const Desktop: Story = {
|
||||
args: {
|
||||
theme: "dark",
|
||||
type: "desktop",
|
||||
},
|
||||
};
|
||||
|
||||
function Story() {
|
||||
return (
|
||||
<div className={"min-h-screen bg-zinc-800 text-foreground"}>
|
||||
<div className="lg:p-10 container max-w-[1100px]">
|
||||
<div className="grid gap-8 grid-cols-2">
|
||||
<HighlightContainer title="Desktop">
|
||||
<TeamSettingsSidebar teamSlug="foo" />
|
||||
</HighlightContainer>
|
||||
export const Mobile: Story = {
|
||||
args: {
|
||||
type: "mobile",
|
||||
},
|
||||
parameters: {
|
||||
viewport: mobileViewport("iphone14"),
|
||||
},
|
||||
};
|
||||
|
||||
<div>
|
||||
<HighlightContainer
|
||||
className="max-w-[400px]"
|
||||
title="Mobile - full nav"
|
||||
>
|
||||
<TeamSettingsMobileNav
|
||||
activeLink={{
|
||||
href: "/team/foo/settings",
|
||||
name: "Foo",
|
||||
}}
|
||||
teamSlug="foo"
|
||||
setShowFull={() => {}}
|
||||
showFull={true}
|
||||
/>
|
||||
</HighlightContainer>
|
||||
|
||||
<HighlightContainer
|
||||
className="max-w-[400px]"
|
||||
title="Mobile - mini - General Page"
|
||||
>
|
||||
<TeamSettingsMobileNav
|
||||
activeLink={{
|
||||
href: "/team/foo/settings",
|
||||
name: "General",
|
||||
}}
|
||||
teamSlug="foo"
|
||||
setShowFull={() => {}}
|
||||
showFull={false}
|
||||
/>
|
||||
</HighlightContainer>
|
||||
|
||||
<HighlightContainer title="Mobile - mini - Billing page">
|
||||
<TeamSettingsMobileNav
|
||||
activeLink={{
|
||||
href: "/team/foo/billing",
|
||||
name: "Billing",
|
||||
}}
|
||||
teamSlug="foo"
|
||||
setShowFull={() => {}}
|
||||
showFull={false}
|
||||
/>
|
||||
</HighlightContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function HighlightContainer(props: {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
title: string;
|
||||
function Story(props: {
|
||||
type: "mobile" | "desktop";
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<Badge className="mb-2 bg-background"> {props.title} </Badge>
|
||||
<div
|
||||
className={cn("p-2 mb-10 rounded-lg bg-background", props.className)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
<div
|
||||
className={"min-h-screen text-foreground lg:max-w-[1100px] py-6 mx-auto"}
|
||||
>
|
||||
{props.type === "desktop" && <TeamSettingsSidebar teamSlug="foo" />}
|
||||
|
||||
{props.type === "mobile" && (
|
||||
<div className="flex flex-col gap-4">
|
||||
<BadgeContainer label="Mobile - Expanded">
|
||||
<TeamSettingsMobileNav
|
||||
activeLink={{
|
||||
href: "/team/foo/settings",
|
||||
name: "Foo",
|
||||
}}
|
||||
teamSlug="foo"
|
||||
setShowFull={() => {}}
|
||||
showFull={true}
|
||||
/>
|
||||
</BadgeContainer>
|
||||
|
||||
<BadgeContainer label="Mobile - Mini">
|
||||
<TeamSettingsMobileNav
|
||||
activeLink={{
|
||||
href: "/team/foo/billing",
|
||||
name: "Billing",
|
||||
}}
|
||||
teamSlug="foo"
|
||||
setShowFull={() => {}}
|
||||
showFull={false}
|
||||
/>
|
||||
</BadgeContainer>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+12
-2
@@ -2,7 +2,10 @@ import type { Team } from "@/api/team";
|
||||
import type { TeamAccountRole, TeamMember } from "@/api/team-members";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { BadgeContainer } from "../../../../../../../stories/utils";
|
||||
import {
|
||||
BadgeContainer,
|
||||
mobileViewport,
|
||||
} from "../../../../../../../stories/utils";
|
||||
import SettingsLayout from "../layout";
|
||||
import { InviteSection } from "./InviteSection";
|
||||
import { ManageMembersSection } from "./ManageMembersSection";
|
||||
@@ -21,10 +24,17 @@ const meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const AllVariants: Story = {
|
||||
export const Desktop: Story = {
|
||||
args: {},
|
||||
};
|
||||
|
||||
export const Mobile: Story = {
|
||||
args: {},
|
||||
parameters: {
|
||||
viewport: mobileViewport("iphone14"),
|
||||
},
|
||||
};
|
||||
|
||||
const freeTeam: Team = {
|
||||
id: "team-id-foo-bar",
|
||||
name: "Team XYZ",
|
||||
|
||||
+20
-1
@@ -1,5 +1,6 @@
|
||||
import type { ApiKey, ApiKeyService } from "@3rdweb-sdk/react/hooks/useApi";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { mobileViewport } from "../../../stories/utils";
|
||||
import { InAppWalletSettingsUI } from "./index";
|
||||
|
||||
const meta = {
|
||||
@@ -27,6 +28,24 @@ export const FreePlan: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const GrowthPlanMobile: Story = {
|
||||
args: {
|
||||
canEditAdvancedFeatures: true,
|
||||
},
|
||||
parameters: {
|
||||
viewport: mobileViewport("iphone14"),
|
||||
},
|
||||
};
|
||||
|
||||
export const FreePlanMobile: Story = {
|
||||
args: {
|
||||
canEditAdvancedFeatures: false,
|
||||
},
|
||||
parameters: {
|
||||
viewport: mobileViewport("iphone14"),
|
||||
},
|
||||
};
|
||||
|
||||
const embeddedWalletService: ApiKeyService = {
|
||||
id: "embeddedWallets",
|
||||
name: "embeddedWallets", // important
|
||||
@@ -56,7 +75,7 @@ function Variants(props: {
|
||||
canEditAdvancedFeatures: boolean;
|
||||
}) {
|
||||
return (
|
||||
<div className="min-h-screen bg-background p-6 text-foreground max-w-[1140px] mx-auto">
|
||||
<div className="min-h-screen bg-background px-4 py-6 text-foreground max-w-[1140px] mx-auto">
|
||||
<div className="flex gap-10 flex-col">
|
||||
<InAppWalletSettingsUI
|
||||
canEditAdvancedFeatures={props.canEditAdvancedFeatures}
|
||||
|
||||
@@ -23,7 +23,7 @@ export const AllVariants: Story = {
|
||||
function Variants() {
|
||||
return (
|
||||
<div className="bg-background p-7 min-h-screen text-foreground">
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col gap-8 max-w-[500px] mx-auto">
|
||||
<BadgeContainer label="upgradeRequired">
|
||||
<GatedSwitch upgradeRequired />
|
||||
</BadgeContainer>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { StarIcon } from "lucide-react";
|
||||
import { BadgeContainer } from "./utils";
|
||||
|
||||
const meta = {
|
||||
title: "Shadcn/Buttons",
|
||||
@@ -12,23 +14,54 @@ const meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Variants: Story = {
|
||||
args: {
|
||||
theme: "light",
|
||||
},
|
||||
export const AllVariants: Story = {
|
||||
args: {},
|
||||
};
|
||||
|
||||
function Component() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background p-6 text-foreground">
|
||||
<div className="flex gap-6">
|
||||
<Button> Default </Button>
|
||||
<Button variant="primary"> Primary </Button>
|
||||
<Button variant="secondary"> Secondary </Button>
|
||||
<Button variant="ghost"> Ghost </Button>
|
||||
<Button variant="outline"> Outline </Button>
|
||||
<Button variant="destructive"> Destructive </Button>
|
||||
</div>
|
||||
<div className="min-h-screen bg-background p-6 text-foregroun flex flex-col gap-6">
|
||||
<Variants size="default" />
|
||||
<Variants size="sm" />
|
||||
<Variants size="icon" />
|
||||
<Variants size="lg" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Variants(props: {
|
||||
size: "default" | "icon" | "sm" | "lg";
|
||||
}) {
|
||||
return (
|
||||
<BadgeContainer label={`Size: ${props.size}`}>
|
||||
<div className="flex gap-6">
|
||||
<Button size={props.size}>
|
||||
{props.size === "icon" ? <StarIcon className="size-4" /> : "Default"}
|
||||
</Button>
|
||||
<Button variant="primary" size={props.size}>
|
||||
{props.size === "icon" ? <StarIcon className="size-4" /> : "Primary"}
|
||||
</Button>
|
||||
<Button variant="secondary" size={props.size}>
|
||||
{props.size === "icon" ? (
|
||||
<StarIcon className="size-4" />
|
||||
) : (
|
||||
"Secondary"
|
||||
)}
|
||||
</Button>
|
||||
<Button variant="ghost" size={props.size}>
|
||||
{props.size === "icon" ? <StarIcon className="size-4" /> : "Ghost"}
|
||||
</Button>
|
||||
<Button variant="outline" size={props.size}>
|
||||
{props.size === "icon" ? <StarIcon className="size-4" /> : "Outline"}
|
||||
</Button>
|
||||
<Button variant="destructive" size={props.size}>
|
||||
{props.size === "icon" ? (
|
||||
<StarIcon className="size-4" />
|
||||
) : (
|
||||
"Desctructive"
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</BadgeContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { INITIAL_VIEWPORTS } from "@storybook/addon-viewport";
|
||||
import { Badge } from "../@/components/ui/badge";
|
||||
|
||||
export function StoryBadge(props: {
|
||||
@@ -24,3 +25,12 @@ export function BadgeContainer(props: {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function mobileViewport(
|
||||
key: "iphone14" | "iphone14promax" | "ipad11p" | "ipad12p",
|
||||
) {
|
||||
return {
|
||||
viewports: INITIAL_VIEWPORTS,
|
||||
defaultViewport: key,
|
||||
};
|
||||
}
|
||||
|
||||
Generated
+9
-6
@@ -136,7 +136,7 @@ importers:
|
||||
version: 5.5.4
|
||||
vitest:
|
||||
specifier: 1.6.0
|
||||
version: 1.6.0(@types/[email protected])(@vitest/[email protected]([email protected]))([email protected])([email protected])
|
||||
version: 1.6.0(@types/[email protected])(@vitest/[email protected])([email protected])([email protected])
|
||||
yalc:
|
||||
specifier: 1.0.0-pre.53
|
||||
version: 1.0.0-pre.53
|
||||
@@ -438,6 +438,9 @@ importers:
|
||||
'@storybook/addon-onboarding':
|
||||
specifier: ^8.2.9
|
||||
version: 8.2.9([email protected])([email protected](@babel/[email protected](@babel/[email protected]))([email protected])([email protected]))
|
||||
'@storybook/addon-viewport':
|
||||
specifier: ^8.2.9
|
||||
version: 8.2.9([email protected](@babel/[email protected](@babel/[email protected]))([email protected])([email protected]))
|
||||
'@storybook/blocks':
|
||||
specifier: ^8.2.9
|
||||
version: 8.2.9([email protected]([email protected]))([email protected])([email protected](@babel/[email protected](@babel/[email protected]))([email protected])([email protected]))
|
||||
@@ -25451,7 +25454,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@codspeed/core': 3.1.0
|
||||
vite: 5.4.2(@types/[email protected])([email protected])
|
||||
vitest: 1.6.0(@types/[email protected])(@vitest/[email protected]([email protected]))([email protected])([email protected])
|
||||
vitest: 1.6.0(@types/[email protected])(@vitest/[email protected])([email protected])([email protected])
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
|
||||
@@ -31877,7 +31880,7 @@ snapshots:
|
||||
redent: 3.0.0
|
||||
optionalDependencies:
|
||||
'@types/bun': 1.0.12
|
||||
vitest: 1.6.0(@types/[email protected])(@vitest/[email protected]([email protected]))([email protected])([email protected])
|
||||
vitest: 1.6.0(@types/[email protected])(@vitest/[email protected])([email protected])([email protected])
|
||||
|
||||
'@testing-library/[email protected](@types/[email protected])([email protected](@types/[email protected])(@vitest/[email protected])([email protected])([email protected]))':
|
||||
dependencies:
|
||||
@@ -32679,7 +32682,7 @@ snapshots:
|
||||
std-env: 3.7.0
|
||||
strip-literal: 2.1.0
|
||||
test-exclude: 6.0.0
|
||||
vitest: 1.6.0(@types/[email protected])(@vitest/[email protected]([email protected]))([email protected])([email protected])
|
||||
vitest: 1.6.0(@types/[email protected])(@vitest/[email protected])([email protected])([email protected])
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -32714,7 +32717,7 @@ snapshots:
|
||||
pathe: 1.1.2
|
||||
picocolors: 1.0.1
|
||||
sirv: 2.0.4
|
||||
vitest: 1.6.0(@types/node@22.0.2)(@vitest/[email protected])([email protected])([email protected])
|
||||
vitest: 1.6.0(@types/node@20.14.9)(@vitest/[email protected])([email protected])([email protected])
|
||||
|
||||
'@vitest/[email protected]':
|
||||
dependencies:
|
||||
@@ -45969,7 +45972,7 @@ snapshots:
|
||||
fsevents: 2.3.3
|
||||
terser: 5.31.0
|
||||
|
||||
[email protected](@types/[email protected])(@vitest/[email protected]([email protected]))([email protected])([email protected]):
|
||||
[email protected](@types/[email protected])(@vitest/[email protected])([email protected])([email protected]):
|
||||
dependencies:
|
||||
'@vitest/expect': 1.6.0
|
||||
'@vitest/runner': 1.6.0
|
||||
|
||||
Reference in New Issue
Block a user