Skip to content
This repository was archived by the owner on Jan 31, 2025. It is now read-only.
Closed
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
26 changes: 23 additions & 3 deletions apps/hub/src/components/breadcrumbs/environment-breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { EnvironmentSelect } from "@/domains/project/components/environment-select";
import { useNavigate } from "@tanstack/react-router";
import { projectEnvironmentQueryOptions } from "@/domains/project/queries";
import { useSuspenseQuery } from "@tanstack/react-query";
import { Link, useNavigate } from "@tanstack/react-router";
import { useContext } from "react";
import { Fragment } from "react/jsx-runtime";
import { NavItem } from "../header/nav-item";
import { MobileBreadcrumbsContext } from "./mobile-breadcrumbs";
import { ProjectBreadcrumb } from "./project-breadcrumb";
import { Separator } from "./separator";

Expand All @@ -12,6 +18,9 @@ export function EnvironmentBreadcrumb({
environmentId,
projectId,
}: EnvironmentBreadcrumbProps) {
const { data } = useSuspenseQuery(
projectEnvironmentQueryOptions({ projectId, environmentId }),
);
const navigate = useNavigate();

const handleEnvironmentChange = (environmentId: string) => {
Expand All @@ -20,13 +29,24 @@ export function EnvironmentBreadcrumb({
params: { projectId, environmentId },
});
};
const isMobile = useContext(MobileBreadcrumbsContext);

const Element = isMobile ? NavItem : Fragment;

return (
<>
<ProjectBreadcrumb projectId={projectId} />
<Separator />
<div>
<Element>
<Link
to="/projects/$projectId/environments/$environmentId"
params={{ projectId, environmentId }}
className="flex items-center gap-2"
>
{data.namespace.displayName}
</Link>
<EnvironmentSelect
variant="discrete"
projectId={projectId}
value={environmentId}
onCreateClick={() =>
Expand All @@ -35,7 +55,7 @@ export function EnvironmentBreadcrumb({
showCreateEnvironment
onValueChange={handleEnvironmentChange}
/>
</div>
</Element>
</>
);
}
28 changes: 14 additions & 14 deletions apps/hub/src/components/breadcrumbs/group-breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,29 @@ export function GroupBreadcrumb({ groupId }: GroupBreadcrumbProps) {

return (
<Element>
<Link
to="/teams/$groupId"
params={{ groupId }}
className="flex items-center gap-2"
>
<GroupAvatar
avatarUrl={data.avatarUrl}
displayName={data.displayName}
className={isMobile ? "size-4" : "size-5"}
/>
{data.displayName}
</Link>
{groupsCount > 1 ? (
<GroupSelect
variant="discrete"
showCreateGroup
onCreateClick={() =>
navigate({ to: ".", search: { modal: "create-group" } })
}
value={groupId}
onValueChange={handleGroupChange}
/>
) : (
<Link
to="/teams/$groupId"
params={{ groupId }}
className="flex items-center gap-2"
>
<GroupAvatar
avatarUrl={data.avatarUrl}
displayName={data.displayName}
className={isMobile ? "size-4" : "size-5"}
/>
{data.displayName}
</Link>
)}
) : null}
</Element>
);
}
28 changes: 14 additions & 14 deletions apps/hub/src/components/breadcrumbs/project-breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,21 @@ export function ProjectBreadcrumb({ projectId }: ProjectBreadcrumbProps) {
<GroupBreadcrumb groupId={data.developerGroupId} />
<Separator />
<Element>
<Link
to="/projects/$projectId"
params={{ projectId }}
className="flex items-center gap-2"
>
<ProjectAvatar
displayName={data.displayName}
logoUrl={data.logoUrl}
className={isMobile ? "size-4" : "size-5"}
/>
{data.displayName}
</Link>
{projectsCount > 1 ? (
<GroupProjectSelect
variant="discrete"
showCreateProject
onCreateClick={() =>
navigate({
Expand All @@ -55,20 +68,7 @@ export function ProjectBreadcrumb({ projectId }: ProjectBreadcrumbProps) {
value={projectId}
onValueChange={handleProjectChange}
/>
) : (
<Link
to="/projects/$projectId"
params={{ projectId }}
className="flex items-center gap-2"
>
<ProjectAvatar
displayName={data.displayName}
logoUrl={data.logoUrl}
className={isMobile ? "size-4" : "size-5"}
/>
{data.displayName}
</Link>
)}
) : null}
</Element>
</>
);
Expand Down
4 changes: 3 additions & 1 deletion apps/hub/src/domains/group/components/group-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ import { type ComponentProps, useCallback } from "react";
interface GroupSelectProps extends ComponentProps<typeof Select> {
showCreateGroup?: boolean;
onCreateClick?: () => void;
variant?: ComponentProps<typeof SelectTrigger>["variant"];
}

export function GroupSelect({
showCreateGroup,
onCreateClick,
onValueChange,
variant,
...props
}: GroupSelectProps) {
const { data } = useSuspenseQuery(projectsQueryOptions());
Expand All @@ -39,7 +41,7 @@ export function GroupSelect({

return (
<Select {...props} onValueChange={handleValueChange}>
<SelectTrigger>
<SelectTrigger variant={variant}>
<SelectValue placeholder="Select team..." />
</SelectTrigger>
<SelectContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ interface EnvironmentSelectProps extends ComponentProps<typeof Select> {
projectId: string;
showCreateEnvironment?: boolean;
onCreateClick?: () => void;
variant?: ComponentProps<typeof SelectTrigger>["variant"];
}

export function EnvironmentSelect({
showCreateEnvironment,
onCreateClick,
onValueChange,
projectId,
variant,
...props
}: EnvironmentSelectProps) {
const { data } = useSuspenseQuery(projectEnvironmentsQueryOptions(projectId));
Expand All @@ -40,7 +42,7 @@ export function EnvironmentSelect({

return (
<Select {...props} onValueChange={handleValueChange}>
<SelectTrigger>
<SelectTrigger variant={variant}>
<SelectValue placeholder="Select environment..." />
</SelectTrigger>
<SelectContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ interface GroupProjectSelectProps extends ComponentProps<typeof Select> {
groupId: string;
showCreateProject?: boolean;
onCreateClick?: () => void;
variant?: ComponentProps<typeof SelectTrigger>["variant"];
}

export function GroupProjectSelect({
groupId,
showCreateProject,
onCreateClick,
onValueChange,
variant,
...props
}: GroupProjectSelectProps) {
const { data } = useSuspenseQuery(groupProjectsQueryOptions(groupId));
Expand All @@ -41,7 +43,7 @@ export function GroupProjectSelect({

return (
<Select onValueChange={handleValueChange} {...props}>
<SelectTrigger>
<SelectTrigger variant={variant}>
<SelectValue placeholder="Select project..." />
</SelectTrigger>
<SelectContent>
Expand Down
23 changes: 17 additions & 6 deletions packages/components/src/ui/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import * as SelectPrimitive from "@radix-ui/react-select";
import * as React from "react";

import { faCheck, faChevronDown, faChevronUp } from "@rivet-gg/icons";
import { faCheck, faChevronDown, faChevronUp, faSelect } from "@rivet-gg/icons";
import { Icon } from "@rivet-gg/icons";
import { cn } from "../lib/utils";

Expand All @@ -16,19 +16,30 @@ const SelectValue = SelectPrimitive.Value;

const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> & {
variant?: "discrete";
}
>(({ className, children, variant, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex whitespace-nowrap h-10 w-full items-center justify-between gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
"flex group/select whitespace-nowrap hover:bg-secondary transition-colors h-10 w-full items-center justify-between gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
{
"border-0 w-auto ring-0 px-1 focus:ring-0 focus:ring-transparent aria-expanded:bg-secondary":
variant === "discrete",
},
className,
)}
{...props}
>
{children}
{variant === "discrete" ? null : children}
<SelectPrimitive.Icon asChild>
<Icon icon={faChevronDown} className="h-4 w-4 opacity-50" />
<Icon
icon={variant === "discrete" ? faSelect : faChevronDown}
className={cn(
"h-4 w-4 group-hover/select:opacity-100 transition-opacity group-aria-expanded/select:opacity-100 opacity-50",
)}
/>
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
));
Expand Down
Loading