[WEB-2273] Fix: page alignments (#5541)

* chore: headers + common containers

* fix: filters code splitting

* fix: home header

* fix: header changes

* chore: page alignments fixed

* fix: uncommented filters

* fix: used enums

* fix: cards + filters

* fix: enum changes

* fix: reverted package changes

* fix: reverted package changes

* fix: Card + tags seperated + naming fixed

* fix: card + tags seperated + naming fixed

* fix: mobile headers fixed partially

* fix: build errors + minor css

* fix: checkbox spacing

* fix: review changes

* fix: lint errors

* fix: minor review changes

* fix: header-alignments

* fix: tabs

* fix: settings page

* fix: subgroup page

* fix: mobile headers

* fix: settings mobile header made observable

* fix: lint error + edge case handling
This commit is contained in:
Akshita Goyal 2024-09-06 18:38:53 +05:30 committed by GitHub
parent 751cd6c862
commit c95aa6a0f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
52 changed files with 234 additions and 219 deletions

View file

@ -11,6 +11,7 @@ export interface HeaderProps {
showOnMobile?: boolean;
}
const HeaderContext = React.createContext<THeaderVariant | null>(null);
const Header = (props: HeaderProps) => {
const {
variant = EHeaderVariant.PRIMARY,
@ -23,13 +24,15 @@ const Header = (props: HeaderProps) => {
const style = getHeaderStyle(variant, setHeight, showOnMobile);
return (
<Row
variant={variant === EHeaderVariant.PRIMARY ? ERowVariant.HUGGING : ERowVariant.REGULAR}
className={cn(style, className)}
{...rest}
>
{children}
</Row>
<HeaderContext.Provider value={variant}>
<Row
variant={variant === EHeaderVariant.PRIMARY ? ERowVariant.HUGGING : ERowVariant.REGULAR}
className={cn(style, className)}
{...rest}
>
{children}
</Row>
</HeaderContext.Provider>
);
};
@ -40,9 +43,23 @@ const LeftItem = (props: HeaderProps) => (
{props.children}
</div>
);
const RightItem = (props: HeaderProps) => (
<div className={cn("flex justify-end gap-3 w-auto items-baseline", props.className)}>{props.children}</div>
);
const RightItem = (props: HeaderProps) => {
const variant = React.useContext(HeaderContext);
if (variant === undefined) throw new Error("RightItem must be used within Header");
return (
<div
className={cn(
"flex justify-end gap-3 w-auto items-start",
{
"items-baseline": variant === EHeaderVariant.TERNARY,
},
props.className
)}
>
{props.children}
</div>
);
};
Header.LeftItem = LeftItem;
Header.RightItem = RightItem;

View file

@ -36,12 +36,12 @@ const AnalyticsPage = observer(() => {
<div className="flex h-full flex-col overflow-hidden bg-custom-background-100">
<Tab.Group as={Fragment} defaultIndex={analytics_tab === "custom" ? 1 : 0}>
<Header variant={EHeaderVariant.SECONDARY}>
<Tab.List as="div" className="flex space-x-2 border-b h-[50px] border-custom-border-200">
<Tab.List as="div" className="flex space-x-2 h-full">
{ANALYTICS_TABS.map((tab) => (
<Tab key={tab.key} as={Fragment}>
{({ selected }) => (
<button
className={`text-sm group relative flex items-center gap-1 h-[50px] px-3 cursor-pointer transition-all font-medium outline-none ${
className={`text-sm group relative flex items-center gap-1 h-full px-3 cursor-pointer transition-all font-medium outline-none ${
selected ? "text-custom-primary-100 " : "hover:text-custom-text-200"
}`}
>

View file

@ -48,63 +48,63 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
return (
<Header>
<Header.LeftItem>
<div className="flex w-full justify-between">
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem
type="text"
link={
<BreadcrumbLink
label={breadcrumbLabel}
disableTooltip
icon={<UserActivityIcon className="h-4 w-4 text-custom-text-300" />}
/>
}
/>
</Breadcrumbs>
<div className="hidden md:flex md:items-center">{showProfileIssuesFilter && <ProfileIssuesFilter />}</div>
<div className="flex gap-4 md:hidden">
<CustomMenu
maxHeight={"md"}
className="flex flex-grow justify-center text-sm text-custom-text-200"
placement="bottom-start"
customButton={
<div className="flex items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1.5">
<span className="flex flex-grow justify-center text-sm text-custom-text-200">{type}</span>
<ChevronDown className="h-4 w-4 text-custom-text-400" />
</div>
}
customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
closeOnSelect
>
<></>
{tabsList.map((tab) => (
<CustomMenu.MenuItem className="flex items-center gap-2" key={tab.route}>
<Link
key={tab.route}
href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}
className="w-full text-custom-text-300"
>
{tab.label}
</Link>
</CustomMenu.MenuItem>
))}
</CustomMenu>
<button
className="block transition-all md:hidden"
onClick={() => {
toggleProfileSidebar();
}}
>
<PanelRight
className={cn(
"block h-4 w-4 md:hidden",
!profileSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200"
)}
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem
type="text"
link={
<BreadcrumbLink
label={breadcrumbLabel}
disableTooltip
icon={<UserActivityIcon className="h-4 w-4 text-custom-text-300" />}
/>
</button>
</div>
</div>
}
/>
</Breadcrumbs>
</Header.LeftItem>
<Header.RightItem>
<div className="hidden md:flex md:items-center">{showProfileIssuesFilter && <ProfileIssuesFilter />}</div>
<div className="flex gap-4 md:hidden">
<CustomMenu
maxHeight={"md"}
className="flex flex-grow justify-center text-sm text-custom-text-200"
placement="bottom-start"
customButton={
<div className="flex items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1.5">
<span className="flex flex-grow justify-center text-sm text-custom-text-200">{type}</span>
<ChevronDown className="h-4 w-4 text-custom-text-400" />
</div>
}
customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
closeOnSelect
>
<></>
{tabsList.map((tab) => (
<CustomMenu.MenuItem className="flex items-center gap-2" key={tab.route}>
<Link
key={tab.route}
href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}
className="w-full text-custom-text-300"
>
{tab.label}
</Link>
</CustomMenu.MenuItem>
))}
</CustomMenu>
<button
className="block transition-all md:hidden"
onClick={() => {
toggleProfileSidebar();
}}
>
<PanelRight
className={cn(
"block h-4 w-4 md:hidden",
!profileSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200"
)}
/>
</button>
</div>
</Header.RightItem>
</Header>
);
});

View file

@ -8,7 +8,7 @@ import { ChevronDown } from "lucide-react";
// types
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "@plane/types";
// ui
import { CustomMenu, Row } from "@plane/ui";
import { CustomMenu } from "@plane/ui";
// components
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues";
// constants
@ -109,18 +109,18 @@ export const ProfileIssuesMobileHeader = observer(() => {
);
return (
<div className="flex justify-start border-b border-custom-border-200 py-2 md:hidden">
<div className="flex justify-evenly border-b border-custom-border-200 py-2 md:hidden">
<CustomMenu
maxHeight={"md"}
className="flex justify-center text-sm text-custom-text-200"
className="flex flex-grow justify-center text-sm text-custom-text-200"
placement="bottom-start"
customButton={
<Row className="flex flex-start text-sm text-custom-text-200">
<div className="flex flex-center text-sm text-custom-text-200">
Layout
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={1} />
</Row>
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={2} />
</div>
}
customButtonClassName="flex flex-start text-custom-text-200 text-sm"
customButtonClassName="flex flex-center text-custom-text-200 text-sm"
closeOnSelect
>
{ISSUE_LAYOUTS.map((layout, index) => {
@ -139,15 +139,15 @@ export const ProfileIssuesMobileHeader = observer(() => {
);
})}
</CustomMenu>
<div className="flex items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
<div className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
<FiltersDropdown
title="Filters"
placement="bottom-end"
menuButton={
<Row className="flex flex-start text-sm text-custom-text-200">
<div className="flex flex-center text-sm text-custom-text-200">
Filters
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={1} />
</Row>
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={2} />
</div>
}
isFiltersApplied={isIssueFilterActive(issueFilters)}
>
@ -165,15 +165,15 @@ export const ProfileIssuesMobileHeader = observer(() => {
/>
</FiltersDropdown>
</div>
<div className="flex items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
<div className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
<FiltersDropdown
title="Display"
placement="bottom-end"
menuButton={
<Row className="flex flex-start text-sm text-custom-text-200">
<div className="flex flex-center text-sm text-custom-text-200">
Display
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={1} />
</Row>
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={2} />
</div>
}
>
<DisplayFiltersSelection

View file

@ -291,6 +291,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
</Button>
{!isCompletedCycle && (
<Button
className="h-full self-start"
onClick={() => {
setTrackElement("Cycle issues page");
toggleCreateIssueModal(true, EIssuesStoreType.CYCLE);

View file

@ -55,25 +55,23 @@ export const CyclesListHeader: FC = observer(() => {
/>
</Breadcrumbs>
</Header.LeftItem>
<Header.RightItem>
{canUserCreateCycle && currentProjectDetails ? (
<div className="flex items-center gap-3">
<CyclesViewHeader projectId={currentProjectDetails.id} />
<Button
variant="primary"
size="sm"
onClick={() => {
setTrackElement("Cycles page");
toggleCreateCycleModal(true);
}}
>
<div className="hidden sm:block">Add</div> Cycle
</Button>
</div>
) : (
<></>
)}
</Header.RightItem>
{canUserCreateCycle && currentProjectDetails ? (
<Header.RightItem>
<CyclesViewHeader projectId={currentProjectDetails.id} />
<Button
variant="primary"
size="sm"
onClick={() => {
setTrackElement("Cycles page");
toggleCreateCycleModal(true);
}}
>
<div className="hidden sm:block">Add</div> Cycle
</Button>
</Header.RightItem>
) : (
<></>
)}
</Header>
);
});

View file

@ -8,7 +8,7 @@ import { Calendar, ChevronDown, Kanban, List } from "lucide-react";
// types
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
// ui
import { CustomMenu, Row } from "@plane/ui";
import { CustomMenu } from "@plane/ui";
// components
import { ProjectAnalyticsModal } from "@/components/analytics";
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues/issue-layouts";
@ -107,10 +107,10 @@ export const ProjectIssuesMobileHeader = observer(() => {
className="flex flex-grow justify-center text-sm text-custom-text-200"
placement="bottom-start"
customButton={
<Row className="flex flex-start text-sm text-custom-text-200">
<div className="flex flex-start text-sm text-custom-text-200">
Layout
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={1} />
</Row>
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={2} />
</div>
}
customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
closeOnSelect

View file

@ -17,7 +17,7 @@ export const ModulesListMobileHeader = observer(() => {
className="flex flex-grow justify-start text-custom-text-200 text-sm py-2 border-b border-custom-border-200 bg-custom-sidebar-background-100"
// placement="bottom-start"
customButton={
<Row className="flex flex-grow justify-start text-custom-text-200 text-sm gap-2">
<Row className="flex flex-grow justify-center text-custom-text-200 text-sm gap-2">
<span>Layout</span> <ChevronDown className="h-4 w-4 text-custom-text-200 my-auto" strokeWidth={1} />
</Row>
}

View file

@ -57,27 +57,25 @@ export const PagesListHeader = observer(() => {
</Breadcrumbs>
</div>
</Header.LeftItem>
<Header.RightItem>
{canUserCreatePage ? (
<div className="flex items-center gap-2">
<Button
variant="primary"
size="sm"
onClick={() => {
setTrackElement("Project pages page");
toggleCreatePageModal({
isOpen: true,
pageAccess: pageType === "private" ? EPageAccess.PRIVATE : EPageAccess.PUBLIC,
});
}}
>
Add page
</Button>
</div>
) : (
<></>
)}
</Header.RightItem>
{canUserCreatePage ? (
<Header.RightItem>
<Button
variant="primary"
size="sm"
onClick={() => {
setTrackElement("Project pages page");
toggleCreatePageModal({
isOpen: true,
pageAccess: pageType === "private" ? EPageAccess.PRIVATE : EPageAccess.PUBLIC,
});
}}
>
Add page
</Button>
</Header.RightItem>
) : (
<></>
)}
</Header>
);
});

View file

@ -45,9 +45,9 @@ const AutomationSettingsPage = observer(() => {
return (
<>
<PageHead title={pageTitle} />
<section className={`w-full overflow-y-auto py-8 pr-9 ${canPerformProjectAdminActions ? "" : "opacity-60"}`}>
<div className="flex items-center border-b border-custom-border-100 py-3.5">
<h3 className="text-xl font-medium">Automations</h3>
<section className={`w-full overflow-y-auto ${canPerformProjectAdminActions ? "" : "opacity-60"}`}>
<div className="flex flex-col items-start border-b border-custom-border-100 pb-3.5">
<h3 className="text-xl font-medium leading-normal">Automations</h3>
</div>
<AutoArchiveAutomation handleChange={handleChange} />
<AutoCloseAutomation handleChange={handleChange} />

View file

@ -30,7 +30,7 @@ const EstimatesSettingsPage = observer(() => {
<>
<PageHead title={pageTitle} />
<div
className={`w-full overflow-y-auto py-8 pr-9 ${canPerformProjectAdminActions ? "" : "pointer-events-none opacity-60"}`}
className={`w-full overflow-y-auto ${canPerformProjectAdminActions ? "" : "pointer-events-none opacity-60"}`}
>
<EstimateRoot
workspaceSlug={workspaceSlug?.toString()}

View file

@ -29,7 +29,7 @@ const FeaturesSettingsPage = observer(() => {
return (
<>
<PageHead title={pageTitle} />
<section className={`w-full overflow-y-auto py-8 pr-9 ${canPerformProjectAdminActions ? "" : "opacity-60"}`}>
<section className={`w-full overflow-y-auto ${canPerformProjectAdminActions ? "" : "opacity-60"}`}>
<ProjectFeaturesList
workspaceSlug={workspaceSlug.toString()}
projectId={projectId.toString()}

View file

@ -42,7 +42,7 @@ const LabelsSettingsPage = observer(() => {
return (
<>
<PageHead title={pageTitle} />
<div ref={scrollableContainerRef} className="h-full w-full gap-10 overflow-y-auto py-2 pr-9">
<div ref={scrollableContainerRef} className="h-full w-full gap-10 overflow-y-auto">
<ProjectSettingsLabelList />
</div>
</>

View file

@ -2,7 +2,8 @@
import { FC, ReactNode } from "react";
// components
import { AppHeader, ContentWrapper } from "@/components/core";
import { ContentWrapper } from "@plane/ui";
import { AppHeader } from "@/components/core";
// local components
import { ProjectSettingHeader } from "./header";
import { ProjectSettingsSidebar } from "./sidebar";
@ -16,14 +17,12 @@ const ProjectSettingLayout: FC<IProjectSettingLayout> = (props) => {
return (
<>
<AppHeader header={<ProjectSettingHeader />} />
<ContentWrapper>
<div className="inset-y-0 z-20 flex flex-grow-0 h-full w-full">
<div className="w-80 flex-shrink-0 overflow-y-hidden pt-8 sm:hidden hidden md:block lg:block">
<ProjectSettingsSidebar />
</div>
<div className="w-full pl-10 sm:pl-10 md:pl-3 lg:pl-3 overflow-y-scroll vertical-scrollbar scrollbar-md">
{children}
</div>
<ContentWrapper className="flex-row inset-y-0 gap-4">
<div className="w-80 flex-shrink-0 overflow-y-hidden sm:hidden hidden md:block lg:block">
<ProjectSettingsSidebar />
</div>
<div className="flex flex-col relative w-full overflow-hidden">
<div className="w-full overflow-x-hidden overflow-y-scroll vertical-scrollbar scrollbar-md">{children}</div>
</div>
</ContentWrapper>
</>

View file

@ -25,7 +25,7 @@ const MembersSettingsPage = observer(() => {
return (
<>
<PageHead title={pageTitle} />
<section className={`w-full overflow-y-auto py-8 pr-9`}>
<section className={`w-full overflow-y-auto`}>
<ProjectSettingsMemberDefaults />
<ProjectMemberList />
</section>

View file

@ -57,7 +57,7 @@ const GeneralSettingsPage = observer(() => {
</>
)}
<div className={`w-full overflow-y-auto py-8 pr-9 ${isAdmin ? "" : "opacity-60"}`}>
<div className={`w-full overflow-y-auto ${isAdmin ? "" : "opacity-60"}`}>
{currentProjectDetails && workspaceSlug && projectId && !isLoading ? (
<ProjectDetailsForm
project={currentProjectDetails}

View file

@ -27,7 +27,7 @@ export const ProjectSettingsSidebar = observer(() => {
if (!currentProjectRole) {
return (
<div className="flex w-80 flex-col gap-6 px-5">
<div className="flex w-[280px] flex-col gap-6">
<div className="flex flex-col gap-2">
<span className="text-xs font-semibold text-custom-sidebar-text-400">SETTINGS</span>
<Loader className="flex w-full flex-col gap-2">
@ -41,7 +41,7 @@ export const ProjectSettingsSidebar = observer(() => {
}
return (
<div className="flex w-80 flex-col gap-6 px-5">
<div className="flex w-[280px] flex-col gap-6">
<div className="flex flex-col gap-2">
<span className="text-xs font-semibold text-custom-sidebar-text-400">SETTINGS</span>
<div className="flex w-full flex-col gap-1">

View file

@ -27,14 +27,12 @@ const StatesSettingsPage = observer(() => {
return (
<>
<PageHead title={pageTitle} />
<div className="py-8 pr-9">
<div className="flex items-center border-b border-custom-border-100 py-3.5">
<h3 className="text-xl font-medium">States</h3>
</div>
{workspaceSlug && projectId && (
<ProjectStateRoot workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} />
)}
<div className="flex items-center border-b border-custom-border-100">
<h3 className="text-xl font-medium">States</h3>
</div>
{workspaceSlug && projectId && (
<ProjectStateRoot workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} />
)}
</>
);
});

View file

@ -21,7 +21,7 @@ export const ViewMobileHeader = observer(() => {
return (
<>
<div className="md:hidden flex justify-evenly border-b border-custom-border-200 py-2 z-[13] bg-custom-background-100">
<Row className="flex items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
<Row className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
<ViewOrderByDropdown
sortBy={filters.sortBy}
sortKey={filters.sortKey}
@ -32,7 +32,7 @@ export const ViewMobileHeader = observer(() => {
isMobile
/>
</Row>
<div className="flex flex-grow items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
<div className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
<FiltersDropdown
icon={<ListFilter className="h-3 w-3" />}
title="Filters"
@ -41,7 +41,7 @@ export const ViewMobileHeader = observer(() => {
menuButton={
<Row className="flex items-center text-sm text-custom-text-200">
Filters
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={1} />
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={2} />
</Row>
}
>

View file

@ -57,7 +57,7 @@ const ApiTokensPage = observer(() => {
<section className="w-full overflow-y-auto">
{tokens.length > 0 ? (
<>
<div className="flex items-center justify-between border-b border-custom-border-200 py-3.5">
<div className="flex items-center justify-between border-b border-custom-border-200 pb-3.5">
<h3 className="text-xl font-medium">API tokens</h3>
<Button variant="primary" onClick={() => setIsCreateTokenModalOpen(true)}>
Add API token

View file

@ -103,7 +103,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
"opacity-60": !canPerformWorkspaceMemberActions,
})}
>
<div className="flex items-center justify-between gap-4 pb-3.5">
<div className="flex justify-between gap-4 pb-3.5 items-start ">
<h4 className="text-xl font-medium">Members</h4>
<div className="ml-auto flex items-center gap-1.5 rounded-md border border-custom-border-200 bg-custom-background-100 px-2.5 py-1.5">
<Search className="h-3.5 w-3.5 text-custom-text-400" />

View file

@ -1,3 +1,4 @@
import { observer } from "mobx-react";
import { useParams, usePathname } from "next/navigation";
// constants
import { EUserWorkspaceRoles } from "@/constants/workspace";
@ -9,7 +10,7 @@ import { WORKSPACE_SETTINGS_LINKS } from "@/plane-web/constants/workspace";
// plane web helpers
import { shouldRenderSettingLink } from "@/plane-web/helpers/workspace.helper";
export const MobileWorkspaceSettingsTabs = () => {
export const MobileWorkspaceSettingsTabs = observer(() => {
const router = useAppRouter();
const { workspaceSlug } = useParams();
const pathname = usePathname();
@ -28,10 +29,11 @@ export const MobileWorkspaceSettingsTabs = () => {
shouldRenderSettingLink(item.key) &&
workspaceMemberInfo >= item.access && (
<div
className={`${item.highlight(pathname, `/${workspaceSlug}`)
? "text-custom-primary-100 text-sm py-2 px-3 whitespace-nowrap flex flex-grow cursor-pointer justify-around border-b border-custom-primary-200"
: "text-custom-text-200 flex flex-grow cursor-pointer justify-around border-b border-custom-border-200 text-sm py-2 px-3 whitespace-nowrap"
}`}
className={`${
item.highlight(pathname, `/${workspaceSlug}`)
? "text-custom-primary-100 text-sm py-2 px-3 whitespace-nowrap flex flex-grow cursor-pointer justify-around border-b border-custom-primary-200"
: "text-custom-text-200 flex flex-grow cursor-pointer justify-around border-b border-custom-border-200 text-sm py-2 px-3 whitespace-nowrap"
}`}
key={index}
onClick={() => router.push(`/${workspaceSlug}${item.href}`)}
>
@ -41,4 +43,4 @@ export const MobileWorkspaceSettingsTabs = () => {
)}
</div>
);
};
});

View file

@ -28,7 +28,7 @@ export const WorkspaceSettingsSidebar = observer(() => {
const workspaceMemberInfo = currentWorkspaceRole || EUserWorkspaceRoles.GUEST;
return (
<div className="flex w-80 flex-col gap-6">
<div className="flex w-[280px] flex-col gap-6">
<div className="flex flex-col gap-2">
<span className="text-xs font-semibold text-custom-sidebar-text-400">SETTINGS</span>
<div className="flex w-full flex-col gap-1">

View file

@ -90,8 +90,8 @@ const WebhookDetailsPage = observer(() => {
<>
<PageHead title={pageTitle} />
<DeleteWebhookModal isOpen={deleteWebhookModal} onClose={() => setDeleteWebhookModal(false)} />
<div className="w-full space-y-8 overflow-y-auto md:py-8 py-4 md:pr-9 pr-4">
<div className="-m-5">
<div className="w-full space-y-8 overflow-y-auto">
<div className="">
<WebhookForm onSubmit={async (data) => await handleUpdateWebhook(data)} data={currentWebhook} />
</div>
{currentWebhook && <WebhookDeleteSection openDeleteModal={() => setDeleteWebhookModal(true)} />}
@ -100,4 +100,4 @@ const WebhookDetailsPage = observer(() => {
);
});
export default WebhookDetailsPage;
export default WebhookDetailsPage;

View file

@ -63,7 +63,7 @@ const WebhooksListPage = observer(() => {
/>
{Object.keys(webhooks).length > 0 ? (
<div className="flex h-full w-full flex-col">
<div className="flex items-center justify-between gap-4 border-b border-custom-border-200 py-3.5">
<div className="flex items-center justify-between gap-4 border-b border-custom-border-200 pb-3.5">
<div className="text-xl font-medium">Webhooks</div>
<Button variant="primary" size="sm" onClick={() => setShowCreateWebhookModal(true)}>
Add webhook

View file

@ -81,7 +81,7 @@ export const WorkspaceActiveCyclesUpgrade = observer(() => {
<div className="grid h-full grid-cols-1 gap-5 pb-8 lg:grid-cols-2 xl:grid-cols-3">
{WORKSPACE_ACTIVE_CYCLES_DETAILS.map((item) => (
<div key={item.title} className="flex min-h-32 w-full flex-col gap-2 rounded-md bg-custom-background-80 p-4">
<div className="flex items-center gap-2">
<div className="flex items-center gap-2 justify-between">
<h3 className="font-medium">{item.title}</h3>
<item.icon className="h-4 w-4 text-blue-500" />
</div>

View file

@ -10,7 +10,7 @@ export const BillingRoot = () => (
<h3 className="text-xl font-medium">Billing and Plans</h3>
</div>
</div>
<div className="px-4 py-6">
<div className="py-6">
<div>
<h4 className="text-md mb-1 leading-6">Current plan</h4>
<p className="mb-3 text-sm text-custom-text-200">You are currently using the free plan</p>

View file

@ -26,7 +26,7 @@ export const ApiTokenListItem: React.FC<Props> = (props) => {
return (
<>
<DeleteApiTokenModal isOpen={deleteModalOpen} onClose={() => setDeleteModalOpen(false)} tokenId={token.id} />
<div className="group relative flex flex-col justify-center border-b border-custom-border-200 px-4 py-3">
<div className="group relative flex flex-col justify-center border-b border-custom-border-200 py-3">
<Tooltip tooltipContent="Delete token" isMobile={isMobile}>
<button
onClick={() => setDeleteModalOpen(true)}

View file

@ -41,7 +41,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
handleClose={() => setmonthModal(false)}
handleChange={handleChange}
/>
<div className="flex flex-col gap-4 border-b border-custom-border-100 px-4 py-6">
<div className="flex flex-col gap-4 border-b border-custom-border-100 py-6">
<div className="flex items-center justify-between">
<div className="flex items-start gap-3">
<div className="flex items-center justify-center rounded bg-custom-background-90 p-3">
@ -68,7 +68,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
{currentProjectDetails ? (
currentProjectDetails.archive_in !== 0 && (
<div className="ml-12">
<div className="mx-6">
<div className="flex w-full items-center justify-between gap-2 rounded border border-custom-border-200 bg-custom-background-90 px-5 py-4">
<div className="w-1/2 text-sm font-medium">Auto-archive issues that are closed for</div>
<div className="w-1/2">
@ -104,7 +104,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
</div>
)
) : (
<Loader className="ml-12">
<Loader className="mx-6">
<Loader.Item height="50px" />
</Loader>
)}

View file

@ -68,7 +68,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
handleClose={() => setmonthModal(false)}
handleChange={handleChange}
/>
<div className="flex flex-col gap-4 border-b border-custom-border-200 px-4 py-6">
<div className="flex flex-col gap-4 border-b border-custom-border-200 py-6">
<div className="flex items-center justify-between">
<div className="flex items-start gap-3">
<div className="flex items-center justify-center rounded bg-custom-background-90 p-3">
@ -95,7 +95,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
{currentProjectDetails ? (
currentProjectDetails.close_in !== 0 && (
<div className="ml-12">
<div className="mx-6">
<div className="flex flex-col rounded border border-custom-border-200 bg-custom-background-90">
<div className="flex w-full items-center justify-between gap-2 px-5 py-4">
<div className="w-1/2 text-sm font-medium">Auto-close issues that are inactive for</div>
@ -155,7 +155,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
)}
{selectedOption?.name
? selectedOption.name
: currentDefaultState?.name ?? <span className="text-custom-text-200">State</span>}
: (currentDefaultState?.name ?? <span className="text-custom-text-200">State</span>)}
</div>
}
onChange={(val: string) => {
@ -171,7 +171,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
</div>
)
) : (
<Loader className="ml-12">
<Loader className="mx-6">
<Loader.Item height="50px" />
</Loader>
)}

View file

@ -112,7 +112,7 @@ export const WidgetIssuesList: React.FC<WidgetIssuesListProps> = (props) => {
</div>
</>
) : (
<div className="h-full grid place-items-center">
<div className="h-full grid place-items-center my-6">
{type === "assigned" && <AssignedIssuesEmptyState type={tab} />}
{type === "created" && <CreatedIssuesEmptyState type={tab} />}
</div>

View file

@ -41,10 +41,10 @@ export const EstimateRoot: FC<TEstimateRoot> = observer((props) => {
{loader === "init-loader" || isSWRLoading ? (
<EstimateLoaderScreen />
) : (
<div className="space-y-12">
<div className="space-y-2">
{/* header */}
<div className="text-xl font-medium text-custom-text-100 border-b border-custom-border-200 py-3.5">
Estimates
<div className="flex flex-col items-start border-b border-custom-border-100 pb-3.5">
<h3 className="text-xl font-medium leading-normal">Estimates</h3>
</div>
{/* current active estimate section */}

View file

@ -83,7 +83,7 @@ const IntegrationGuide = observer(() => {
{EXPORTERS_LIST.map((service) => (
<div
key={service.provider}
className="flex items-center justify-between gap-2 border-b border-custom-border-100 bg-custom-background-100 px-4 py-6"
className="flex items-center justify-between gap-2 border-b border-custom-border-100 bg-custom-background-100 py-6"
>
<div className="flex w-full items-start justify-between gap-4">
<div className="item-center flex gap-2.5">

View file

@ -10,7 +10,7 @@ const smallButton = <ListFilter className="h-3 " />;
const largeButton = (
<div className={cn(getButtonStyling("neutral-primary", "sm"), "text-custom-text-300")}>
<ListFilter className="h-3 " />
<span className="hidden lg:flex">Filters</span>
<span className="hidden xl:flex">Filters</span>
<ChevronDown className="h-3 w-3" strokeWidth={2} />
</div>
@ -21,8 +21,8 @@ export const FiltersRoot: FC = () => (
<FiltersDropdown
menuButton={
<>
<div className="hidden 2xl:flex">{largeButton}</div>
<div className="flex 2xl:hidden">{smallButton}</div>
<div className="hidden xl:flex">{largeButton}</div>
<div className="flex xl:hidden">{smallButton}</div>
</>
}
title=""

View file

@ -34,8 +34,8 @@ export const InboxIssueOrderByDropdown: FC = observer(() => {
<CustomMenu
customButton={
<>
<div className="hidden 2xl:flex">{largeButton}</div>
<div className="flex 2xl:hidden">{smallButton}</div>
<div className="hidden xl:flex">{largeButton}</div>
<div className="flex xl:hidden">{smallButton}</div>
</>
}
placement="bottom-end"

View file

@ -81,7 +81,7 @@ export const InboxSidebar: FC<IInboxSidebarProps> = observer((props) => {
<div
key={option?.key}
className={cn(
`text-sm relative flex items-center gap-1 h-[50px] px-3 cursor-pointer transition-all font-medium`,
`text-sm relative flex items-center gap-1 h-full px-3 cursor-pointer transition-all font-medium`,
currentTab === option?.key ? `text-custom-primary-100` : `hover:text-custom-text-200`
)}
onClick={() => {

View file

@ -135,7 +135,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
const isGroupByCreatedBy = group_by === "created_by";
return (
<ContentWrapper className={`flex-row relative gap-4`}>
<ContentWrapper className={`flex-row relative gap-4 py-4`}>
{list &&
list.length > 0 &&
list.map((subList: IGroupByColumn) => {

View file

@ -17,7 +17,7 @@ export const HeaderSubGroupByCard: FC<IHeaderSubGroupByCard> = observer((props)
const { icon, title, count, column_id, kanbanFilters, handleKanbanFilters } = props;
return (
<div
className={`relative flex w-full flex-shrink-0 flex-row items-center gap-2 rounded-sm p-1.5 cursor-pointer`}
className={`relative flex w-full flex-shrink-0 flex-row items-center gap-1 rounded-sm py-1.5 cursor-pointer`}
onClick={() => handleKanbanFilters("sub_group_by", column_id)}
>
<div className="flex h-[20px] w-[20px] flex-shrink-0 items-center justify-center overflow-hidden rounded-sm transition-all hover:bg-custom-background-80">

View file

@ -12,6 +12,8 @@ import {
TIssueGroupByOptions,
TIssueOrderByOptions,
} from "@plane/types";
// UI
import { Row } from "@plane/ui";
// hooks
import { useCycle, useLabel, useMember, useModule, useProject, useProjectState } from "@/hooks/store";
import { useIssueStoreType } from "@/hooks/use-issue-layout-store";
@ -160,7 +162,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
return (
<div key={_list.id} className="flex flex-shrink-0 flex-col">
<div className="sticky top-[50px] z-[3] py-1 flex w-full items-center bg-custom-background-100 border-y-[0.5px] border-custom-border-200">
<div className="sticky left-0 flex-shrink-0">
<Row className="sticky left-0 flex-shrink-0">
<HeaderSubGroupByCard
column_id={_list.id}
icon={_list.icon}
@ -169,7 +171,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
kanbanFilters={kanbanFilters}
handleKanbanFilters={handleKanbanFilters}
/>
</div>
</Row>
</div>
{subGroupByVisibilityToggle.showIssues && (
@ -295,7 +297,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
return (
<div className="relative">
<div className="sticky top-0 z-[4] h-[50px] bg-custom-background-90 px-2">
<Row className="sticky top-0 z-[4] h-[50px] bg-custom-background-90">
<SubGroupSwimlaneHeader
getGroupIssueCount={getGroupIssueCount}
group_by={group_by}
@ -305,7 +307,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
list={groupByList}
showEmptyGroup={showEmptyGroup}
/>
</div>
</Row>
{sub_group_by && (
<SubGroupSwimlane

View file

@ -8,7 +8,7 @@ export const KanbanQuickAddIssueButton: FC<TQuickAddIssueButton> = observer((pro
return (
<div
className="flex w-full cursor-pointer items-center gap-2 p-3 py-1.5 text-custom-text-350 hover:text-custom-text-300"
className="flex w-full cursor-pointer items-center gap-2 py-1.5 text-custom-text-350 hover:text-custom-text-300"
onClick={onClick}
>
<PlusIcon className="h-3.5 w-3.5 stroke-2" />

View file

@ -63,13 +63,13 @@ export const ProjectSettingsLabelList: React.FC = observer(() => {
data={selectDeleteLabel ?? null}
onClose={() => setSelectDeleteLabel(null)}
/>
<div className="flex items-center justify-between border-b border-custom-border-100 py-3.5">
<div className="flex items-center justify-between border-b border-custom-border-100 pb-3.5">
<h3 className="text-xl font-medium">Labels</h3>
<Button variant="primary" onClick={newLabel} size="sm">
Add label
</Button>
</div>
<div className="w-full py-8">
<div className="w-full py-2">
{showLabelForm && (
<div className="my-2 w-full rounded border border-custom-border-200 px-3.5 py-2">
<CreateUpdateLabelInline

View file

@ -20,7 +20,7 @@ export const ProfileStateDistribution: React.FC<Props> = ({ stateDistribution, u
return (
<div className="flex flex-col space-y-2">
<h3 className="text-lg font-medium">Issues by state</h3>
<Card>
<Card className="h-full">
{userProfile.state_distribution.length > 0 ? (
<div className="grid grid-cols-1 gap-x-6 md:grid-cols-2">
<div>

View file

@ -141,7 +141,7 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="relative mt-6 h-44 w-full">
<div className="relative h-44 w-full">
<div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent" />
<img src={watch("cover_image")!} alt={watch("cover_image")!} className="h-44 w-full rounded-md object-cover" />
<div className="z-5 absolute bottom-4 flex w-full items-end justify-between gap-3 px-4">

View file

@ -118,7 +118,7 @@ export const ProjectsBaseHeader = observer(() => {
setTrackElement("Projects page");
toggleCreateProjectModal(true);
}}
className="items-center gap-1 my-auto"
className="items-center gap-1"
>
<span className="hidden sm:inline-block">Add</span> Project
</Button>

View file

@ -67,9 +67,9 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
default_assignee:
formData.default_assignee === "none"
? null
: formData.default_assignee ?? currentProjectDetails?.default_assignee,
: (formData.default_assignee ?? currentProjectDetails?.default_assignee),
project_lead:
formData.project_lead === "none" ? null : formData.project_lead ?? currentProjectDetails?.project_lead,
formData.project_lead === "none" ? null : (formData.project_lead ?? currentProjectDetails?.project_lead),
})
.then(() => {
setToast({
@ -85,12 +85,12 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
return (
<>
<div className="flex items-center border-b border-custom-border-100 py-3.5">
<div className="flex items-center border-b border-custom-border-100 pb-3.5">
<h3 className="text-xl font-medium">Defaults</h3>
</div>
<div className="flex w-full flex-col gap-2 pb-4">
<div className="flex w-full items-center gap-4 py-8">
<div className="flex w-full items-center gap-4 py-4">
<div className="flex w-1/2 flex-col gap-2">
<h4 className="text-sm">Project Lead</h4>
<div className="">

View file

@ -56,12 +56,12 @@ export const ProjectFeaturesList: FC<Props> = observer((props) => {
if (!currentUser) return <></>;
return (
<div className="mx-4 space-y-6">
<div className="space-y-6">
{Object.keys(PROJECT_FEATURES_LIST).map((featureSectionKey) => {
const feature = PROJECT_FEATURES_LIST[featureSectionKey];
return (
<div key={featureSectionKey} className="">
<div className="flex flex-col justify-center border-b border-custom-border-100 py-3">
<div className="flex flex-col justify-center border-b border-custom-border-100">
<h3 className="text-xl font-medium">{feature.title}</h3>
<h4 className="text-sm leading-5 text-custom-text-200">{feature.description}</h4>
</div>

View file

@ -2,7 +2,7 @@ import { forwardRef } from "react";
import { ContentWrapper } from "@plane/ui";
export const KanbanIssueBlockLoader = forwardRef<HTMLSpanElement>((props, ref) => (
<span ref={ref} className="block h-28 m-1.5 animate-pulse bg-custom-background-80 rounded" />
<span ref={ref} className="block h-28 animate-pulse bg-custom-background-80 rounded" />
));
KanbanIssueBlockLoader.displayName = "KanbanIssueBlockLoader";

View file

@ -27,7 +27,7 @@ export const ViewOrderByDropdown: React.FC<Props> = (props) => {
];
const buttonClassName = isMobile
? "flex items-center text-sm text-custom-text-200 gap-2"
? "flex items-center text-sm text-custom-text-200 gap-2 w-full"
: `${getButtonStyling("neutral-primary", "sm")} px-2 text-custom-text-300`;
const chevronClassName = isMobile ? "h-4 w-4 text-custom-text-200" : "h-3 w-3";
@ -38,11 +38,11 @@ export const ViewOrderByDropdown: React.FC<Props> = (props) => {
<span className={buttonClassName}>
{!isMobile && <ArrowDownWideNarrow className="h-3 w-3" />}
<span className="flex-shrink-0"> {orderByDetails?.label}</span>
<ChevronDown className={chevronClassName} strokeWidth={1} />
<ChevronDown className={chevronClassName} strokeWidth={2} />
</span>
}
placement="bottom-end"
className="w-full"
className="w-full flex justify-center"
maxHeight="lg"
closeOnSelect
>

View file

@ -61,7 +61,7 @@ export const WebhookForm: FC<Props> = observer((props) => {
return (
<form onSubmit={handleSubmit(handleFormSubmit)}>
<div className="space-y-5 p-5">
<div className="space-y-5 ">
<div className="text-xl font-medium text-custom-text-200">{data ? "Webhook details" : "Create webhook"}</div>
<div className="space-y-3">
<div className="space-y-1">
@ -85,7 +85,7 @@ export const WebhookForm: FC<Props> = observer((props) => {
</div>
</div>
{data ? (
<div className="p-5 pt-0 space-y-5">
<div className="pt-0 space-y-5">
<WebhookSecretKey data={data} />
<Button type="submit" loading={isSubmitting}>
{isSubmitting ? "Updating" : "Update"}

View file

@ -30,7 +30,7 @@ export const WebhooksListItem: FC<IWebhookListItem> = (props) => {
return (
<div className="border-b border-custom-border-200">
<Link href={`/${workspaceSlug}/settings/webhooks/${webhook?.id}`}>
<span className="flex items-center justify-between gap-4 px-3.5 py-[18px]">
<span className="flex items-center justify-between gap-4 py-[18px]">
<h5 className="truncate text-base font-medium">{webhook.url}</h5>
<ToggleSwitch value={webhook.is_active} onChange={handleToggle} />
</span>

View file

@ -171,7 +171,7 @@ export const WorkspaceDetails: FC = observer(() => {
)}
/>
<div className={`w-full overflow-y-auto md:pr-9 pr-4 ${isAdmin ? "" : "opacity-60"}`}>
<div className="flex items-center gap-5 border-b border-custom-border-100 pb-7">
<div className="flex gap-5 border-b border-custom-border-100 pb-7 items-start">
<div className="flex flex-col gap-1">
<button type="button" onClick={() => setIsImageUploadModalOpen(true)} disabled={!isAdmin}>
{watch("logo") && watch("logo") !== null && watch("logo") !== "" ? (
@ -190,7 +190,7 @@ export const WorkspaceDetails: FC = observer(() => {
</button>
</div>
<div className="flex flex-col gap-1">
<h3 className="text-lg font-semibold leading-6">{watch("name")}</h3>
<div className="text-lg font-semibold leading-6 mb:-my-5">{watch("name")}</div>
<button type="button" onClick={handleCopyUrl} className="text-sm tracking-tight text-left">{`${
typeof window !== "undefined" && window.location.origin.replace("http://", "").replace("https://", "")
}/${currentWorkspace.slug}`}</button>
@ -212,7 +212,7 @@ export const WorkspaceDetails: FC = observer(() => {
</div>
</div>
<div className="my-10 flex flex-col gap-8">
<div className="my-8 flex flex-col gap-8">
<div className="grid-col grid w-full grid-cols-1 items-center justify-between gap-10 xl:grid-cols-2 2xl:grid-cols-3">
<div className="flex flex-col gap-1">
<h4 className="text-sm">Workspace name</h4>

View file

@ -104,7 +104,7 @@ export const GlobalViewsHeader: React.FC = observer(() => {
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
return (
<Header variant={EHeaderVariant.SECONDARY}>
<Header variant={EHeaderVariant.SECONDARY} className="min-h-[44px]">
<CreateUpdateWorkspaceViewModal isOpen={createViewModal} onClose={() => setCreateViewModal(false)} />
<div
ref={containerRef}