refactor: migrate web @plane/propel Button to @makeplane/propel

Replace in-repo Button and getButtonStyling in apps/web with
@makeplane/propel Button. Map sizes sm/base/lg/xl to xs/sm/md/lg,
error variants to danger, and link to ghost. Stretch is required.
Links use render; CustomMenu and dropdown chrome use the styled
element so we do not nest buttons.
This commit is contained in:
anmolsinghbhatia
2026-08-28 19:03:30 +05:30
parent 3478d4fac4
commit 4baa06367e
164 changed files with 1884 additions and 1387 deletions

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { DraftIcon } from "@plane/propel/icons";
import { EIssuesStoreType } from "@plane/types";
import { Breadcrumbs, Header } from "@plane/ui";
@@ -66,15 +66,16 @@ export const WorkspaceDraftHeader = observer(function WorkspaceDraftHeader() {
<Header.RightItem>
{joinedProjectIds && joinedProjectIds.length > 0 && (
<Button
variant="primary"
size="lg"
className="items-center gap-1"
onClick={() => setIsDraftIssueModalOpen(true)}
disabled={!isAuthorizedUser}
>
{t("workspace_draft_issues.draft_an_issue")}
</Button>
<span className="items-center gap-1">
<Button
variant="primary"
size="md"
stretch="auto"
label={t("workspace_draft_issues.draft_an_issue")}
onClick={() => setIsDraftIssueModalOpen(true)}
disabled={!isAuthorizedUser}
/>
</span>
)}
</Header.RightItem>
</Header>

View File

@@ -8,7 +8,7 @@ import { observer } from "mobx-react";
import { Shapes } from "lucide-react";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { HomeIcon } from "@plane/propel/icons";
import { Breadcrumbs, Header } from "@plane/ui";
// components
@@ -37,15 +37,16 @@ export const WorkspaceDashboardHeader = observer(function WorkspaceDashboardHead
</div>
</Header.LeftItem>
<Header.RightItem>
<Button
variant="secondary"
size="lg"
onClick={() => toggleWidgetSettings(true)}
className="my-auto mb-0"
prependIcon={<Shapes />}
>
<div className="hidden sm:hidden md:block">{t("home.manage_widgets")}</div>
</Button>
<span className="my-auto mb-0">
<Button
variant="secondary"
size="md"
stretch="auto"
onClick={() => toggleWidgetSettings(true)}
icon={<Shapes />}
label={t("home.manage_widgets")}
/>
</span>
</Header.RightItem>
</Header>
</>

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
// plane imports
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
// components
import { PageHead } from "@/components/core/page-title";
import { DownloadActivityButton } from "@/components/profile/activity/download-button";
@@ -64,9 +64,13 @@ function ProfileActivityPage() {
{activityPages}
{pageCount < totalPages && resultsCount !== 0 && (
<div className="flex w-full items-center justify-center text-11">
<Button variant="secondary" onClick={handleLoadMore}>
{t("common.load_more")}
</Button>
<Button
variant="secondary"
size="sm"
stretch="auto"
label={t("common.load_more")}
onClick={handleLoadMore}
/>
</div>
)}
</div>

View File

@@ -19,7 +19,7 @@ import { ProfileIssuesFilter } from "@/components/profile/profile-issues-filter"
// hooks
import { useAppTheme } from "@/hooks/store/use-app-theme";
import { useUser, useUserPermissions } from "@/hooks/store/user";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/elements/button";
type TUserProfileHeader = {
userProjectsData: IUserProfileProjectSegregation | undefined;
@@ -96,16 +96,9 @@ export const UserProfileHeader = observer(function UserProfileHeader(props: TUse
))}
</CustomMenu>
<div className="shrink-0 md:hidden">
<Button
variant="ghost"
size="lg"
onClick={() => {
toggleProfileSidebar();
}}
appendIcon={
<PanelRight className={!profileSidebarCollapsed ? "text-accent-primary" : "text-secondary"} />
}
></Button>
<Button variant="ghost" size="md" stretch="auto" onClick={() => toggleProfileSidebar()}>
<PanelRight className={!profileSidebarCollapsed ? "text-accent-primary" : "text-secondary"} />
</Button>
</div>
</div>
</Header.RightItem>

View File

@@ -9,7 +9,7 @@ import { useRouter } from "next/navigation";
import useSWR from "swr";
// ui
import { Banner } from "@plane/propel/banner";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { ArchiveIcon } from "@plane/propel/icons";
import { Loader } from "@plane/ui";
// components
@@ -74,10 +74,11 @@ function ArchivedIssueDetailsPage({ params }: Route.ComponentProps) {
action={
<Button
variant="secondary"
size="sm"
stretch="auto"
label="Go to archives"
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/archives/issues/`)}
>
Go to archives
</Button>
/>
}
className="border-b border-subtle"
/>

View File

@@ -8,7 +8,7 @@ import { useCallback, useRef, useState } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// icons
import { ChartNoAxesColumn, PanelRight, SlidersHorizontal } from "lucide-react";
import { PanelRight, SlidersHorizontal } from "lucide-react";
// plane imports
import {
EIssueFilterType,
@@ -18,7 +18,7 @@ import {
} from "@plane/constants";
import { usePlatformOS } from "@plane/hooks";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { IconButton } from "@plane/propel/icon-button";
import { CycleIcon } from "@plane/propel/icons";
import { Tooltip } from "@plane/propel/tooltip";
@@ -232,22 +232,23 @@ export const CycleIssuesHeader = observer(function CycleIssuesHeader() {
{canUserCreateIssue && (
<>
<Button onClick={() => setAnalyticsModal(true)} variant="secondary" size="lg">
<span className="hidden @4xl:flex">Analytics</span>
<span className="@4xl:hidden">
<ChartNoAxesColumn className="size-3.5" />
</span>
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
label="Analytics"
onClick={() => setAnalyticsModal(true)}
/>
{!isCompletedCycle && (
<Button
variant="primary"
size="lg"
size="md"
stretch="auto"
label={t("issue.add.label")}
onClick={() => {
toggleCreateIssueModal(true, EIssuesStoreType.CYCLE);
}}
>
{t("issue.add.label")}
</Button>
/>
)}
</>
)}

View File

@@ -9,7 +9,7 @@ import { useParams } from "next/navigation";
// ui
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { CycleIcon } from "@plane/propel/icons";
import { Breadcrumbs, Header } from "@plane/ui";
// components
@@ -62,14 +62,13 @@ export const CyclesListHeader = observer(function CyclesListHeader() {
<CyclesViewHeader projectId={currentProjectDetails.id} />
<Button
variant="primary"
size="lg"
size="md"
stretch="auto"
label={t("project_cycles.add_cycle")}
onClick={() => {
toggleCreateCycleModal(true);
}}
>
<div className="block sm:hidden">{t("add")}</div>
<div className="hidden sm:block">{t("project_cycles.add_cycle")}</div>
</Button>
/>
</Header.RightItem>
) : (
<></>

View File

@@ -8,7 +8,7 @@ import { useCallback, useRef, useState } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// icons
import { ChartNoAxesColumn, PanelRight, SlidersHorizontal } from "lucide-react";
import { PanelRight, SlidersHorizontal } from "lucide-react";
// plane imports
import {
EIssueFilterType,
@@ -16,7 +16,7 @@ import {
EUserPermissions,
EUserPermissionsLevel,
} from "@plane/constants";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { ModuleIcon } from "@plane/propel/icons";
import { Tooltip } from "@plane/propel/tooltip";
import type { ICustomSearchSelectOption, IIssueDisplayFilterOptions, IIssueDisplayProperties } from "@plane/types";
@@ -227,22 +227,26 @@ export const ModuleIssuesHeader = observer(function ModuleIssuesHeader() {
{canUserCreateIssue ? (
<>
<Button className="hidden md:block" onClick={() => setAnalyticsModal(true)} variant="secondary" size="lg">
<span className="hidden @4xl:flex">Analytics</span>
<span className="@4xl:hidden">
<ChartNoAxesColumn className="size-3.5" />
</span>
</Button>
<Button
variant="primary"
size="lg"
className="hidden sm:flex"
onClick={() => {
toggleCreateIssueModal(true, EIssuesStoreType.MODULE);
}}
>
Add work item
</Button>
<span className="hidden md:block">
<Button
variant="secondary"
size="md"
stretch="auto"
label="Analytics"
onClick={() => setAnalyticsModal(true)}
/>
</span>
<span className="hidden sm:flex">
<Button
variant="primary"
size="md"
stretch="auto"
label="Add work item"
onClick={() => {
toggleCreateIssueModal(true, EIssuesStoreType.MODULE);
}}
/>
</span>
</>
) : (
<></>

View File

@@ -10,7 +10,7 @@ import { useParams } from "next/navigation";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { ModuleIcon } from "@plane/propel/icons";
import { Breadcrumbs, Header } from "@plane/ui";
// components
@@ -67,14 +67,13 @@ export const ModulesListHeader = observer(function ModulesListHeader() {
{canUserCreateModule ? (
<Button
variant="primary"
size="md"
stretch="auto"
label={t("project_module.add_module")}
onClick={() => {
toggleCreateModuleModal(true);
}}
size="lg"
>
<div className="block sm:hidden">{t("add")}</div>
<div className="hidden sm:block">{t("project_module.add_module")}</div>
</Button>
/>
) : (
<></>
)}

View File

@@ -9,12 +9,9 @@ import { observer } from "mobx-react";
import Link from "next/link";
import useSWR from "swr";
// plane types
import { getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { TSearchEntityRequestPayload, TWebhookConnectionQueryParams } from "@plane/types";
import { EFileAssetType } from "@plane/types";
// plane ui
// plane utils
import { cn } from "@plane/utils";
// components
import { LogoSpinner } from "@/components/common/logo-spinner";
import { PageHead } from "@/components/core/page-title";
@@ -165,12 +162,16 @@ function PageDetailsPage({ params }: Route.ComponentProps) {
<p className="mt-3 text-center text-13 text-secondary">
The page you are trying to access doesn{"'"}t exist or you don{"'"}t have permission to view it.
</p>
<Link
href={`/${workspaceSlug}/projects/${projectId}/pages`}
className={cn(getButtonStyling("secondary", "base"), "mt-5")}
>
View other Pages
</Link>
<span className="mt-5">
<Button
variant="secondary"
size="sm"
stretch="auto"
label="View other Pages"
nativeButton={false}
render={<Link href={`/${workspaceSlug}/projects/${projectId}/pages`} />}
/>
</span>
</div>
);

View File

@@ -10,7 +10,7 @@ import { useParams, useRouter, useSearchParams } from "next/navigation";
// constants
import { EPageAccess } from "@plane/constants";
// plane types
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { PageIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { TPage } from "@plane/types";
@@ -79,9 +79,14 @@ export const PagesListHeader = observer(function PagesListHeader() {
</Header.LeftItem>
{canCurrentUserCreatePage && (
<Header.RightItem>
<Button variant="primary" size="lg" onClick={handleCreatePage} loading={isCreatingPage}>
{isCreatingPage ? "Adding" : "Add page"}
</Button>
<Button
variant="primary"
size="md"
stretch="auto"
label={isCreatingPage ? "Adding" : "Add page"}
onClick={handleCreatePage}
loading={isCreatingPage}
/>
</Header.RightItem>
)}
</Header>

View File

@@ -15,7 +15,7 @@ import {
EUserPermissions,
EUserPermissionsLevel,
} from "@plane/constants";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { LockIcon, ViewsIcon } from "@plane/propel/icons";
import { Tooltip } from "@plane/propel/tooltip";
import type { ICustomSearchSelectOption, IIssueDisplayFilterOptions, IIssueDisplayProperties } from "@plane/types";
@@ -198,13 +198,13 @@ export const ProjectViewIssuesHeader = observer(function ProjectViewIssuesHeader
{canUserCreateIssue && (
<Button
variant="primary"
size="lg"
size="md"
stretch="auto"
label="Add work item"
onClick={() => {
toggleCreateIssueModal(true, EIssuesStoreType.PROJECT_VIEW);
}}
>
Add work item
</Button>
/>
)}
<div className="hidden md:block">
<ViewQuickActions

View File

@@ -7,7 +7,7 @@
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { ViewsIcon } from "@plane/propel/icons";
import { Breadcrumbs, Header } from "@plane/ui";
// components
@@ -47,9 +47,13 @@ export const ProjectViewsHeader = observer(function ProjectViewsHeader() {
<Header.RightItem>
<ViewListHeader />
<div>
<Button variant="primary" size="lg" onClick={() => toggleCreateViewModal(true)}>
Add view
</Button>
<Button
variant="primary"
size="md"
stretch="auto"
label="Add view"
onClick={() => toggleCreateViewModal(true)}
/>
</div>
</Header.RightItem>
</Header>

View File

@@ -7,7 +7,7 @@
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { RecentStickyIcon } from "@plane/propel/icons";
import { Breadcrumbs, Header } from "@plane/ui";
// components
@@ -45,15 +45,15 @@ export const WorkspaceStickyHeader = observer(function WorkspaceStickyHeader() {
<StickySearch />
<Button
variant="primary"
size="lg"
size="md"
stretch="auto"
label="Add sticky"
onClick={() => {
toggleShowNewSticky(true);
stickyOperations.create();
}}
loading={creatingSticky}
>
Add sticky
</Button>
/>
</Header.RightItem>
</Header>
</>

View File

@@ -10,7 +10,7 @@ import { useParams } from "next/navigation";
// plane imports
import { EIssueFilterType, ISSUE_DISPLAY_FILTERS_BY_PAGE, DEFAULT_GLOBAL_VIEWS_LIST } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { ViewsIcon } from "@plane/propel/icons";
import type { IIssueDisplayFilterOptions, IIssueDisplayProperties, ICustomSearchSelectOption } from "@plane/types";
import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types";
@@ -143,9 +143,13 @@ export const GlobalIssuesHeader = observer(function GlobalIssuesHeader() {
/>
</FiltersDropdown>
)}
<Button variant="primary" size="lg" onClick={() => setCreateViewModal(true)}>
{t("workspace_views.add_view")}
</Button>
<Button
variant="primary"
size="md"
stretch="auto"
label={t("workspace_views.add_view")}
onClick={() => setCreateViewModal(true)}
/>
<div className="hidden md:block">
{viewDetails && <WorkspaceViewQuickActions workspaceSlug={workspaceSlug?.toString()} view={viewDetails} />}
{isDefaultView && defaultViewDetails && (

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
// types
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { SearchIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { IWorkspaceBulkInviteFormData } from "@plane/types";
@@ -136,9 +136,13 @@ const WorkspaceMembersSettingsPage = observer(function WorkspaceMembersSettingsP
memberType="workspace"
/>
{canPerformWorkspaceAdminActions && (
<Button variant="primary" size="lg" onClick={() => setInviteModal(true)}>
{t("workspace_settings.settings.members.add_member")}
</Button>
<Button
variant="primary"
size="md"
stretch="auto"
label={t("workspace_settings.settings.members.add_member")}
onClick={() => setInviteModal(true)}
/>
)}
</div>
</div>

View File

@@ -10,7 +10,7 @@ import useSWR from "swr";
// plane imports
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
// components
import { EmptyStateCompact } from "@plane/propel/empty-state";
import { NotAuthorizedView } from "@/components/auth-screens/not-authorized-view";
@@ -78,9 +78,13 @@ function WebhooksListPage({ params }: Route.ComponentProps) {
title={t("workspace_settings.settings.webhooks.title")}
description={t("workspace_settings.settings.webhooks.description")}
control={
<Button variant="primary" size="lg" onClick={() => setShowCreateWebhookModal(true)}>
{t("workspace_settings.settings.webhooks.add_webhook")}
</Button>
<Button
variant="primary"
size="md"
stretch="auto"
label={t("workspace_settings.settings.webhooks.add_webhook")}
onClick={() => setShowCreateWebhookModal(true)}
/>
}
/>
{Object.keys(webhooks).length > 0 ? (

View File

@@ -8,8 +8,7 @@ import { observer } from "mobx-react";
import Link from "next/link";
import { useTheme } from "next-themes";
// plane imports
import { Button, getButtonStyling } from "@plane/propel/button";
import { cn } from "@plane/utils";
import { Button } from "@makeplane/propel/components/button";
// assets
import ProjectDarkEmptyState from "@/app/assets/empty-state/project-settings/no-projects-dark.png?url";
import ProjectLightEmptyState from "@/app/assets/empty-state/project-settings/no-projects-light.png?url";
@@ -31,10 +30,21 @@ function ProjectSettingsPage() {
need to get things done.
</div>
<div className="flex gap-2">
<Link href="https://plane.so/" target="_blank" className={cn(getButtonStyling("secondary", "base"))}>
Learn more about projects
</Link>
<Button onClick={() => toggleCreateProjectModal(true)}>Start your first project</Button>
<Button
variant="secondary"
size="sm"
stretch="auto"
label="Learn more about projects"
nativeButton={false}
render={<Link href="https://plane.so/" target="_blank" />}
/>
<Button
variant="primary"
size="sm"
stretch="auto"
label="Start your first project"
onClick={() => toggleCreateProjectModal(true)}
/>
</div>
</div>
);

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
import Link from "next/link";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button, getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { PlaneLogo } from "@plane/propel/icons";
import type { IWorkspace } from "@plane/types";
// assets
@@ -86,12 +86,21 @@ const CreateWorkspacePage = observer(function CreateWorkspacePage() {
{t("workspace_creation.errors.creation_disabled.description")}
</p>
<div className="mt-6 flex gap-4">
<Button variant="primary" onClick={() => router.back()}>
{t("common.go_back")}
</Button>
<a href={getMailtoHref()} className={getButtonStyling("secondary", "base")}>
{t("workspace_creation.errors.creation_disabled.request_button")}
</a>
<Button
variant="primary"
size="sm"
stretch="auto"
label={t("common.go_back")}
onClick={() => router.back()}
/>
<Button
variant="secondary"
size="sm"
stretch="auto"
label={t("workspace_creation.errors.creation_disabled.request_button")}
nativeButton={false}
render={<a href={getMailtoHref()} />}
/>
</div>
</div>
) : (

View File

@@ -14,7 +14,7 @@ import { CheckCircle2 } from "lucide-react";
import { ROLE } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// types
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { PlaneLogo } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { IWorkspaceMemberInvitation } from "@plane/types";
@@ -162,21 +162,22 @@ function UserInvitationsPage() {
<div className="flex items-center gap-3">
<Button
variant="primary"
size="md"
stretch="auto"
label={t("accept_and_join")}
type="submit"
size="lg"
onClick={submitInvitations}
disabled={isJoiningWorkspaces || invitationsRespond.length === 0}
loading={isJoiningWorkspaces}
>
{t("accept_and_join")}
</Button>
<Link href={`/${redirectWorkspaceSlug}`}>
<span>
<Button variant="secondary" size="lg">
{t("go_home")}
</Button>
</span>
</Link>
/>
<Button
variant="secondary"
size="md"
stretch="auto"
label={t("go_home")}
nativeButton={false}
render={<Link href={`/${redirectWorkspaceSlug}`} />}
/>
</div>
</div>
</div>

View File

@@ -7,7 +7,7 @@
// plane imports
import { isRouteErrorResponse } from "react-router";
import { Banner } from "@plane/propel/banner";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { Card, ECardVariant } from "@plane/propel/card";
import { InfoFillIcon } from "@plane/propel/icons";
@@ -19,14 +19,8 @@ interface ErrorActionsProps {
function ErrorActions({ onGoHome, onReload }: ErrorActionsProps) {
return (
<div className="flex gap-3 pt-2">
<Button variant="primary" size="lg" onClick={onGoHome}>
Go to home
</Button>
{onReload && (
<Button variant="secondary" size="lg" onClick={onReload}>
Reload page
</Button>
)}
<Button variant="primary" size="md" stretch="auto" label="Go to home" onClick={onGoHome} />
{onReload && <Button variant="secondary" size="md" stretch="auto" label="Reload page" onClick={onReload} />}
</div>
);
}

View File

@@ -6,7 +6,7 @@
import { useTheme } from "next-themes";
// plane imports
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
// assets
import maintenanceModeDarkModeImage from "@/app/assets/instance/maintenance-mode-dark.svg?url";
import maintenanceModeLightModeImage from "@/app/assets/instance/maintenance-mode-light.svg?url";
@@ -80,9 +80,7 @@ export function ProdErrorComponent({ onGoHome }: ProdErrorComponentProps) {
</div>
<div className="flex items-center justify-start gap-6">
<Button variant="primary" size="lg" onClick={onGoHome}>
Go to home
</Button>
<Button variant="primary" size="md" stretch="auto" label="Go to home" onClick={onGoHome} />
</div>
</div>
</div>

View File

@@ -6,7 +6,7 @@
import Link from "next/link";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
// images
import Image404 from "@/app/assets/404.svg?url";
// types
@@ -32,13 +32,16 @@ function PageNotFound() {
temporarily unavailable.
</p>
</div>
<Link href="/">
<span className="flex justify-center">
<Button variant="secondary" size="lg">
Go to Home
</Button>
</span>
</Link>
<span className="flex justify-center">
<Button
variant="secondary"
size="md"
stretch="auto"
label="Go to Home"
nativeButton={false}
render={<Link href="/" />}
/>
</span>
</div>
</div>
</div>

View File

@@ -11,7 +11,7 @@ import { observer } from "mobx-react";
import { CircleAlert, XCircle } from "lucide-react";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { IEmailCheckData } from "@plane/types";
import { Input, Spinner } from "@plane/ui";
import { cn, checkEmailValidity } from "@plane/utils";
@@ -100,9 +100,15 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
</p>
)}
</div>
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
{isSubmitting ? <Spinner height="20px" width="20px" /> : t("common.continue")}
</Button>
<Button
type="submit"
variant="primary"
size="lg"
disabled={isButtonDisabled}
stretch="full"
loading={isSubmitting}
label={t("common.continue")}
/>
</form>
);
});

View File

@@ -12,10 +12,10 @@ import { Controller, useForm } from "react-hook-form";
import { CircleCheck } from "lucide-react";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button, getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { Input } from "@plane/ui";
import { cn, checkEmailValidity } from "@plane/utils";
import { checkEmailValidity } from "@plane/utils";
// hooks
import useTimer from "@/hooks/use-timer";
// services
@@ -117,20 +117,26 @@ export const ForgotPasswordForm = observer(function ForgotPasswordForm() {
)}
</div>
<Button
type="submit"
variant="primary"
className="w-full"
size="xl"
size="lg"
stretch="full"
label={
resendTimerCode > 0
? t("auth.common.resend_in", { seconds: resendTimerCode })
: t("auth.forgot_password.send_reset_link")
}
type="submit"
disabled={!isValid}
loading={isSubmitting || resendTimerCode > 0}
>
{resendTimerCode > 0
? t("auth.common.resend_in", { seconds: resendTimerCode })
: t("auth.forgot_password.send_reset_link")}
</Button>
<Link href="/" className={cn("w-full", getButtonStyling("link", "lg"))}>
{t("auth.common.back_to_sign_in")}
</Link>
/>
<Button
variant="ghost"
size="md"
stretch="full"
label={t("auth.common.back_to_sign_in")}
nativeButton={false}
render={<Link href="/" />}
/>
</form>
</FormContainer>
);

View File

@@ -12,7 +12,7 @@ import { Eye, EyeOff, Info, XCircle } from "lucide-react";
// plane imports
import { API_BASE_URL, E_PASSWORD_STRENGTH } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { CloseIcon } from "@plane/propel/icons";
import { Input, PasswordStrengthIndicator, Spinner } from "@plane/ui";
import { getPasswordStrength } from "@plane/utils";
@@ -279,31 +279,36 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
<div className="space-y-2.5">
{mode === EAuthModes.SIGN_IN ? (
<>
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
{isSubmitting ? (
<Spinner height="20px" width="20px" />
) : isSMTPConfigured ? (
t("common.continue")
) : (
t("common.go_to_workspace")
)}
</Button>
<Button
type="submit"
variant="primary"
size="lg"
stretch="full"
disabled={isButtonDisabled}
loading={isSubmitting}
label={isSMTPConfigured ? t("common.continue") : t("common.go_to_workspace")}
/>
{isSMTPConfigured && (
<Button
variant="secondary"
size="lg"
stretch="full"
label={t("auth.common.sign_in_with_unique_code")}
type="button"
onClick={redirectToUniqueCodeSignIn}
variant="secondary"
className="w-full"
size="xl"
>
{t("auth.common.sign_in_with_unique_code")}
</Button>
/>
)}
</>
) : (
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
{isSubmitting ? <Spinner height="20px" width="20px" /> : "Create account"}
</Button>
<Button
type="submit"
variant="primary"
size="lg"
disabled={isButtonDisabled}
stretch="full"
loading={isSubmitting}
label={"Create account"}
/>
)}
</div>
</form>

View File

@@ -12,7 +12,7 @@ import { Eye, EyeOff } from "lucide-react";
// ui
import { API_BASE_URL, E_PASSWORD_STRENGTH } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { Input, PasswordStrengthIndicator } from "@plane/ui";
// components
import { getPasswordStrength } from "@plane/utils";
@@ -195,9 +195,14 @@ export const ResetPasswordForm = observer(function ResetPasswordForm() {
<span className="text-13 text-danger-primary">{t("auth.common.password.errors.match")}</span>
)}
</div>
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
{t("auth.common.password.submit")}
</Button>
<Button
variant="primary"
size="lg"
stretch="full"
label={t("auth.common.password.submit")}
type="submit"
disabled={isButtonDisabled}
/>
</form>
</FormContainer>
);

View File

@@ -13,7 +13,7 @@ import { Eye, EyeOff } from "lucide-react";
// plane imports
import { E_PASSWORD_STRENGTH } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { Input, PasswordStrengthIndicator } from "@plane/ui";
// components
@@ -198,9 +198,14 @@ export const SetPasswordForm = observer(function SetPasswordForm() {
<span className="text-13 text-danger-primary">{t("auth.common.password.errors.match")}</span>
)}
</div>
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
{t("common.continue")}
</Button>
<Button
variant="primary"
size="lg"
stretch="full"
label={t("common.continue")}
type="submit"
disabled={isButtonDisabled}
/>
</form>
</FormContainer>
);

View File

@@ -8,7 +8,7 @@ import { useEffect, useState } from "react";
import { CircleCheck, XCircle } from "lucide-react";
import { API_BASE_URL } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { Input, Spinner } from "@plane/ui";
// constants
// helpers
@@ -162,15 +162,15 @@ export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) {
</div>
<div className="space-y-2.5">
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
{isRequestingNewCode ? (
t("auth.common.unique_code.sending_code")
) : isSubmitting ? (
<Spinner height="20px" width="20px" />
) : (
t("common.continue")
)}
</Button>
<Button
type="submit"
variant="primary"
size="lg"
stretch="full"
disabled={isButtonDisabled}
loading={isSubmitting}
label={isRequestingNewCode ? t("auth.common.unique_code.sending_code") : t("common.continue")}
/>
</div>
</form>
);

View File

@@ -7,7 +7,7 @@
import { useState } from "react";
import { useTranslation } from "@plane/i18n";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TrashIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
@@ -81,12 +81,14 @@ export function DeactivateAccountModal(props: Props) {
</div>
</div>
<div className="mb-2 flex items-center justify-end gap-2 p-4 sm:px-6">
<Button variant="secondary" size="lg" onClick={handleClose}>
{t("cancel")}
</Button>
<Button variant="error-fill" size="lg" onClick={handleDeleteAccount}>
{isDeactivating ? t("deactivating") : t("confirm")}
</Button>
<Button variant="secondary" size="md" stretch="auto" label={t("cancel")} onClick={handleClose} />
<Button
variant="danger"
size="md"
stretch="auto"
label={isDeactivating ? t("deactivating") : t("confirm")}
onClick={handleDeleteAccount}
/>
</div>
</ModalCore>
);

View File

@@ -9,7 +9,7 @@ import { AlertOctagon, BarChart4, CircleDashed, Folder, Microscope } from "lucid
// plane imports
import { MARKETING_PRICING_PAGE_LINK } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { SearchIcon } from "@plane/propel/icons";
import { ContentWrapper } from "@plane/ui";
import { cn } from "@plane/utils";
@@ -91,15 +91,15 @@ export const WorkspaceActiveCyclesUpgrade = observer(function WorkspaceActiveCyc
<p className="text-14 font-medium text-tertiary">{t("active_cycles_description")}</p>
</div>
<div className="flex items-center gap-3">
<a
className={`${getButtonStyling("primary", "base")} cursor-pointer`}
href={MARKETING_PRICING_PAGE_LINK}
target="_blank"
rel="noreferrer"
>
<ProIcon className="h-3.5 w-3.5 text-on-color" />
{t("upgrade")}
</a>
<Button
variant="primary"
size="sm"
stretch="auto"
label={t("upgrade")}
icon={<ProIcon className="h-3.5 w-3.5 text-on-color" />}
nativeButton={false}
render={<a href={MARKETING_PRICING_PAGE_LINK} target="_blank" rel="noreferrer" />}
/>
</div>
<span className="absolute top-0 left-0">
<img

View File

@@ -7,7 +7,7 @@
import type { ColumnDef, Row, Table } from "@tanstack/react-table";
import { Download } from "lucide-react";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { AnalyticsTableDataMap, TAnalyticsTabsBase } from "@plane/types";
import { DataTable } from "./data-table";
import { TableLoader } from "./loader";
@@ -39,11 +39,12 @@ export function InsightTable<T extends Exclude<TAnalyticsTabsBase, "overview">>(
actions={(table: Table<AnalyticsTableDataMap[T]>) => (
<Button
variant="secondary"
prependIcon={<Download className="h-3.5 w-3.5" />}
size="sm"
stretch="auto"
icon={<Download className="h-3.5 w-3.5" />}
onClick={() => onExport?.(table.getFilteredRowModel().rows)}
>
<div>{t("exporter.csv.short_description")}</div>
</Button>
label={t("exporter.csv.short_description")}
/>
)}
/>
</div>

View File

@@ -6,11 +6,10 @@
import { observer } from "mobx-react";
// plane package imports
import { getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/elements/button";
import { Logo } from "@plane/propel/emoji-icon-picker";
import { ChevronDownIcon, ProjectIcon } from "@plane/propel/icons";
import { CustomSearchSelect } from "@plane/ui";
import { cn } from "@plane/utils";
// hooks
import { useProject } from "@/hooks/store/use-project";
@@ -50,7 +49,7 @@ export const ProjectSelect = observer(function ProjectSelect(props: Props) {
options={options}
className="border-none p-0"
customButton={
<div className={cn(getButtonStyling("secondary", "lg"), "gap-2")}>
<Button variant="secondary" size="md" stretch="auto" render={<div />}>
<ProjectIcon className="h-4 w-4" />
{value && value.length > 3
? `3+ projects`
@@ -61,7 +60,7 @@ export const ProjectSelect = observer(function ProjectSelect(props: Props) {
.join(", ")
: "All projects"}
<ChevronDownIcon className="h-3 w-3" aria-hidden="true" />
</div>
</Button>
}
customButtonClassName="border-none p-0 bg-transparent hover:bg-transparent w-auto h-auto"
multiple

View File

@@ -15,7 +15,7 @@ import { Download } from "lucide-react";
import type { ChartXAxisDateGrouping } from "@plane/constants";
import { ANALYTICS_X_AXIS_VALUES, ANALYTICS_Y_AXIS_VALUES, CHART_COLOR_PALETTES, EChartModels } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { BarChart } from "@plane/propel/charts/bar-chart";
import { EmptyStateCompact } from "@plane/propel/empty-state";
import type { TBarItem, TChart, TChartDatum, ChartXAxisProperty, ChartYAxisMetric } from "@plane/types";
@@ -228,11 +228,12 @@ const PriorityChart = observer(function PriorityChart(props: Props) {
actions={(table: Table<TChartDatum>) => (
<Button
variant="secondary"
prependIcon={<Download className="h-3.5 w-3.5" />}
size="sm"
stretch="auto"
icon={<Download className="h-3.5 w-3.5" />}
onClick={() => exportCSV(table.getRowModel().rows, [...defaultColumns, ...columns], workspaceSlug)}
>
<div>{t("exporter.csv.short_description")}</div>
</Button>
label={t("exporter.csv.short_description")}
/>
)}
/>
</>

View File

@@ -6,7 +6,7 @@
import React from "react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
// assets
import emptyApiTokens from "@/app/assets/empty-state/api-token.svg?url";
@@ -27,9 +27,9 @@ export function ApiTokenEmptyState(props: Props) {
<p className="mb-7 text-tertiary sm:mb-8">
Create API tokens for safe and easy data sharing with external apps, maintaining control and security.
</p>
<Button className="flex items-center gap-1.5" onClick={onClick}>
Add token
</Button>
<span className="flex items-center gap-1.5">
<Button variant="primary" size="sm" stretch="auto" label="Add token" onClick={onClick} />
</span>
</div>
</div>
);

View File

@@ -10,7 +10,7 @@ import { Controller, useForm } from "react-hook-form";
import { Calendar } from "lucide-react";
// types
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { IApiToken } from "@plane/types";
// ui
@@ -251,14 +251,19 @@ export function CreateApiTokenForm(props: Props) {
<span className="text-11">{t("workspace_settings.settings.api_tokens.never_expires")}</span>
</div>
<div className="flex items-center gap-2">
<Button variant="secondary" onClick={handleClose}>
{t("cancel")}
</Button>
<Button variant="primary" type="submit" loading={isSubmitting}>
{isSubmitting
? t("workspace_settings.settings.api_tokens.generating")
: t("workspace_settings.settings.api_tokens.generate_token")}
</Button>
<Button variant="secondary" size="sm" stretch="auto" label={t("cancel")} onClick={handleClose} />
<Button
variant="primary"
size="sm"
stretch="auto"
label={
isSubmitting
? t("workspace_settings.settings.api_tokens.generating")
: t("workspace_settings.settings.api_tokens.generate_token")
}
type="submit"
loading={isSubmitting}
/>
</div>
</div>
</form>

View File

@@ -5,7 +5,7 @@
*/
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { CopyIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { Tooltip } from "@plane/propel/tooltip";
@@ -58,9 +58,7 @@ export function GeneratedTokenDetails(props: Props) {
? `Expires ${renderFormattedDate(tokenDetails.expired_at)} at ${renderFormattedTime(tokenDetails.expired_at)}`
: "Never expires"}
</p>
<Button variant="secondary" onClick={handleClose}>
{t("close")}
</Button>
<Button variant="secondary" size="sm" stretch="auto" label={t("close")} onClick={handleClose} />
</div>
</div>
);

View File

@@ -6,7 +6,7 @@
import Link from "next/link";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
// layouts
import DefaultLayout from "@/layouts/default-layout";
@@ -23,16 +23,22 @@ export function NotAWorkspaceMember() {
</p>
</div>
<div className="flex items-center justify-center gap-2">
<Link href="/invitations">
<span>
<Button variant="secondary">Check pending invites</Button>
</span>
</Link>
<Link href="/create-workspace">
<span>
<Button variant="primary">Create new workspace</Button>
</span>
</Link>
<Button
variant="secondary"
size="sm"
stretch="auto"
label="Check pending invites"
nativeButton={false}
render={<Link href="/invitations" />}
/>
<Button
variant="primary"
size="sm"
stretch="auto"
label="Create new workspace"
nativeButton={false}
render={<Link href="/create-workspace" />}
/>
</div>
</div>
</div>

View File

@@ -7,7 +7,7 @@
import { useParams } from "next/navigation";
// react-hook-form
import { Controller, useForm } from "react-hook-form";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { IProject } from "@plane/types";
// ui
import { Input, EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
@@ -123,12 +123,15 @@ export function SelectMonthModal({ type, initialValues, isOpen, handleClose, han
</div>
</div>
<div className="mt-5 flex justify-end gap-2">
<Button variant="secondary" size="lg" onClick={onClose}>
Cancel
</Button>
<Button variant="primary" size="lg" type="submit" loading={isSubmitting}>
{isSubmitting ? "Submitting..." : "Submit"}
</Button>
<Button variant="secondary" size="md" stretch="auto" label="Cancel" onClick={onClose} />
<Button
variant="primary"
size="md"
stretch="auto"
label={isSubmitting ? "Submitting..." : "Submit"}
type="submit"
loading={isSubmitting}
/>
</div>
</form>
</ModalCore>

View File

@@ -7,7 +7,7 @@
import React from "react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
type Props = {
title: string;
@@ -33,12 +33,13 @@ export function EmptyState({ title, description, image, primaryButton, secondary
{primaryButton && (
<Button
variant="primary"
prependIcon={primaryButton.icon}
size="sm"
stretch="auto"
label={primaryButton.text}
icon={primaryButton.icon}
onClick={primaryButton.onClick}
disabled={disabled}
>
{primaryButton.text}
</Button>
/>
)}
{secondaryButton}
</div>

View File

@@ -8,7 +8,7 @@ import { Component, Fragment } from "react";
import type { ErrorInfo, ReactNode } from "react";
import { AlertTriangle } from "lucide-react";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
type Props = {
children: ReactNode;
@@ -26,9 +26,7 @@ function LayoutErrorFallback({ onRetry }: { onRetry: () => void }) {
<div className="flex h-full w-full flex-col items-center justify-center gap-3 text-center">
<AlertTriangle className="size-8 text-tertiary" />
<p className="text-14 text-secondary">{t("something_went_wrong")}</p>
<Button variant="secondary" size="sm" onClick={onRetry}>
{t("common.retry")}
</Button>
<Button variant="secondary" size="xs" stretch="auto" label={t("common.retry")} onClick={onRetry} />
</div>
);
}

View File

@@ -7,7 +7,7 @@
import React, { useState } from "react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
type Props = {
title: string;
@@ -49,14 +49,15 @@ export function NewEmptyState({ title, description, image, primaryButton, disabl
<div className="relative flex items-start justify-center">
{primaryButton && (
<Button
className={`relative m-3 max-w-min !px-6 ${comicBox?.direction === "left" ? "flex-row-reverse" : ""}`}
size="xl"
variant="primary"
onClick={primaryButton.onClick}
disabled={disabled}
>
{primaryButton.text}
<span className={`relative m-3 max-w-min ${comicBox?.direction === "left" ? "flex-row-reverse" : ""}`}>
<Button
size="lg"
stretch="auto"
variant="primary"
onClick={primaryButton.onClick}
disabled={disabled}
label={primaryButton.text}
/>
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
@@ -69,7 +70,7 @@ export function NewEmptyState({ title, description, image, primaryButton, disabl
comicBox?.direction === "left" ? "left-0 ml-2.5" : "right-0 mr-2.5"
} h-1.5 w-1.5 rounded-full`}
/>
</Button>
</span>
)}
{comicBox &&
isHovered &&

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
// plane imports
import type { EditorRefApi } from "@plane/editor";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { CopyIcon, ChevronLeftIcon, ChevronRightIcon } from "@plane/propel/icons";
import { setToast, TOAST_TYPE } from "@plane/propel/toast";
import { Tooltip } from "@plane/propel/tooltip";
@@ -160,20 +160,25 @@ export const DescriptionVersionsModal = observer(function DescriptionVersionsMod
<IconButton type="button" variant="ghost" size="base" onClick={handleCopyMarkdown} icon={CopyIcon} />
</Tooltip>
<div className="flex items-center gap-2">
<Button variant="secondary" size="lg" onClick={handleClose} tabIndex={1}>
{t("common.cancel")}
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
label={t("common.cancel")}
onClick={handleClose}
tabIndex={1}
/>
{!isRestoreDisabled && (
<Button
variant="primary"
size="lg"
size="md"
stretch="auto"
label={t("common.actions.restore")}
onClick={() => {
handleRestore(activeVersionDescription ?? "<p></p>");
handleClose();
}}
>
{t("common.actions.restore")}
</Button>
/>
)}
</div>
</div>

View File

@@ -5,7 +5,7 @@
*/
import { Controller, useForm } from "react-hook-form";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { Calendar } from "@plane/propel/calendar";
import { CloseIcon } from "@plane/propel/icons";
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
@@ -120,18 +120,16 @@ export function DateFilterModal({ title, handleClose, isOpen, onSelect }: Props)
</h6>
)}
<div className="flex justify-end gap-4">
<Button variant="secondary" size="lg" onClick={handleClose}>
Cancel
</Button>
<Button variant="secondary" size="md" stretch="auto" label="Cancel" onClick={handleClose} />
<Button
variant="primary"
size="lg"
size="md"
stretch="auto"
label="Apply"
type="button"
onClick={handleSubmit(handleFormSubmit)}
disabled={isInvalid}
>
Apply
</Button>
/>
</div>
</form>
</ModalCore>

View File

@@ -16,7 +16,8 @@ import { Popover } from "@headlessui/react";
import { ACCEPTED_COVER_IMAGE_MIME_TYPES_FOR_REACT_DROPZONE, MAX_FILE_SIZE } from "@plane/constants";
import { useOutsideClickDetector } from "@plane/hooks";
import { Tabs } from "@plane/propel/tabs";
import { Button, getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { Button as ButtonElement } from "@makeplane/propel/elements/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { EFileAssetType } from "@plane/types";
import { Input, Loader } from "@plane/ui";
@@ -192,9 +193,15 @@ function ImagePickerPopoverComponent<TFieldValues extends FieldValues = FieldVal
return (
<Popover className="relative z-19" ref={ref} tabIndex={tabIndex} onKeyDown={handleKeyDown}>
<Popover.Button className={getButtonStyling("secondary", "sm")} onClick={handleOnClick} disabled={disabled}>
<ButtonElement
variant="secondary"
size="xs"
stretch="auto"
disabled={disabled}
render={<Popover.Button onClick={handleOnClick} disabled={disabled} />}
>
{label}
</Popover.Button>
</ButtonElement>
{isOpen && (
<Popover.Panel
@@ -241,9 +248,13 @@ function ImagePickerPopoverComponent<TFieldValues extends FieldValues = FieldVal
/>
)}
/>
<Button variant="primary" size="xl" onClick={() => setSearchParams(formData.search)}>
Search
</Button>
<Button
variant="primary"
size="lg"
stretch="auto"
label="Search"
onClick={() => setSearchParams(formData.search)}
/>
</div>
{unsplashImages ? (
unsplashImages.length > 0 ? (
@@ -349,22 +360,23 @@ function ImagePickerPopoverComponent<TFieldValues extends FieldValues = FieldVal
<div className="flex h-12 items-start justify-end gap-2">
<Button
variant="secondary"
size="sm"
stretch="auto"
label="Cancel"
onClick={() => {
setIsOpen(false);
setImage(null);
}}
>
Cancel
</Button>
/>
<Button
variant="primary"
className="w-full"
size="sm"
stretch="full"
label={isImageUploading ? "Uploading" : "Upload & Save"}
onClick={handleSubmit}
disabled={!image}
loading={isImageUploading}
>
{isImageUploading ? "Uploading" : "Upload & Save"}
</Button>
/>
</div>
</div>
</Tabs.Content>

View File

@@ -13,7 +13,7 @@ import { useForm } from "react-hook-form";
import { Combobox } from "@headlessui/react";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { SearchIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { ISearchIssueResponse, IUser } from "@plane/types";
@@ -199,12 +199,15 @@ export const BulkDeleteIssuesModal = observer(function BulkDeleteIssuesModal(pro
{issues.length > 0 && (
<div className="flex items-center justify-end gap-2 p-3">
<Button variant="secondary" size="lg" onClick={handleClose}>
Cancel
</Button>
<Button variant="error-fill" size="lg" onClick={handleSubmit(handleDelete)} loading={isSubmitting}>
{isSubmitting ? "Deleting..." : "Delete selected work items"}
</Button>
<Button variant="secondary" size="md" stretch="auto" label="Cancel" onClick={handleClose} />
<Button
variant="danger"
size="md"
stretch="auto"
label={isSubmitting ? "Deleting..." : "Delete selected work items"}
onClick={handleSubmit(handleDelete)}
loading={isSubmitting}
/>
</div>
)}
</form>

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { Input, EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
import { cn } from "@plane/utils";
@@ -201,16 +201,28 @@ export const ChangeEmailModal = observer(function ChangeEmailModal(props: Props)
</div>
)}
<div className="flex items-center justify-end gap-2 border-t-[0.5px] border-subtle py-4">
<Button type="button" variant="secondary" size="lg" onClick={handleClose}>
{changeEmailT("actions.cancel")}
</Button>
<Button type="submit" variant="primary" size="lg" disabled={isSubmitting}>
{isSubmitting
? changeEmailT("states.sending")
: secondStep
? changeEmailT("actions.confirm")
: changeEmailT("actions.continue")}
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
label={changeEmailT("actions.cancel")}
type="button"
onClick={handleClose}
/>
<Button
variant="primary"
size="md"
stretch="auto"
label={
isSubmitting
? changeEmailT("states.sending")
: secondStep
? changeEmailT("actions.confirm")
: changeEmailT("actions.continue")
}
type="submit"
disabled={isSubmitting}
/>
</div>
</form>
</ModalCore>

View File

@@ -10,7 +10,7 @@ import { Combobox } from "@headlessui/react";
// i18n
import { useTranslation } from "@plane/i18n";
// types
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { SearchIcon, CloseIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { Tooltip } from "@plane/propel/tooltip";
@@ -313,27 +313,29 @@ export function ExistingIssuesListModal(props: Props) {
</Combobox.Options>
</Combobox>
<div className="flex items-center justify-between p-3">
<Button
variant="link"
onClick={handleSelectIssues}
disabled={filteredIssues.length === 0}
className={filteredIssues.length === 0 ? "p-0" : ""}
>
{selectedIssues.length === issues.length ? t("issue.select.deselect_all") : t("issue.select.select_all")}
</Button>
<span className={filteredIssues.length === 0 ? "p-0" : ""}>
<Button
variant="ghost"
size="sm"
stretch="auto"
label={
selectedIssues.length === issues.length ? t("issue.select.deselect_all") : t("issue.select.select_all")
}
onClick={handleSelectIssues}
disabled={filteredIssues.length === 0}
/>
</span>
<div className="flex items-center justify-end gap-2">
<Button variant="secondary" size="lg" onClick={handleClose}>
{t("common.cancel")}
</Button>
<Button variant="secondary" size="md" stretch="auto" label={t("common.cancel")} onClick={handleClose} />
<Button
variant="primary"
size="lg"
size="md"
stretch="auto"
label={isSubmitting ? t("common.adding") : t("issue.select.add_selected")}
onClick={onSubmit}
loading={isSubmitting}
disabled={isSubmitting || selectedIssues.length === 0}
>
{isSubmitting ? t("common.adding") : t("issue.select.add_selected")}
</Button>
/>
</div>
</div>
</ModalCore>

View File

@@ -13,7 +13,7 @@ import { AlertCircle } from "lucide-react";
import { Popover, Transition } from "@headlessui/react";
// plane imports
import type { EditorRefApi } from "@plane/editor";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { Input } from "@plane/ui";
// components
@@ -180,13 +180,14 @@ export function GptAssistantPopover(props: Props) {
const responseActionButton = response !== "" && (
<Button
variant="primary"
size="sm"
stretch="auto"
label="Use this response"
onClick={() => {
onResponse(response);
onClose();
}}
>
Use this response
</Button>
/>
);
const generateResponseButtonText = isSubmitting
@@ -287,12 +288,15 @@ export function GptAssistantPopover(props: Props) {
</>
)}
<div className="flex items-center gap-2">
<Button variant="secondary" onClick={onClose}>
Close
</Button>
<Button variant="primary" onClick={handleSubmit(handleAIResponse)} loading={isSubmitting}>
{generateResponseButtonText}
</Button>
<Button variant="secondary" size="sm" stretch="auto" label="Close" onClick={onClose} />
<Button
variant="primary"
size="sm"
stretch="auto"
label={generateResponseButtonText}
onClick={handleSubmit(handleAIResponse)}
loading={isSubmitting}
/>
</div>
</div>
</Popover.Panel>

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
import { useDropzone } from "react-dropzone";
// plane imports
import { ACCEPTED_AVATAR_IMAGE_MIME_TYPES_FOR_REACT_DROPZONE, MAX_FILE_SIZE } from "@plane/constants";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { UserCirclePropertyIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { EFileAssetType } from "@plane/types";
@@ -143,16 +143,25 @@ export const UserImageUploadModal = observer(function UserImageUploadModal(props
</div>
<p className="my-4 text-13 text-secondary">File formats supported- .jpeg, .jpg, .png, .webp</p>
<div className="flex items-center justify-between">
<Button variant="error-fill" size="lg" onClick={handleImageRemove} disabled={!value}>
{isRemoving ? "Removing" : "Remove"}
</Button>
<Button
variant="danger"
size="md"
stretch="auto"
label={isRemoving ? "Removing" : "Remove"}
onClick={handleImageRemove}
disabled={!value}
/>
<div className="flex items-center gap-2">
<Button variant="secondary" size="lg" onClick={handleClose}>
Cancel
</Button>
<Button variant="primary" size="lg" onClick={handleSubmit} disabled={!image} loading={isImageUploading}>
{isImageUploading ? "Uploading" : "Upload & Save"}
</Button>
<Button variant="secondary" size="md" stretch="auto" label="Cancel" onClick={handleClose} />
<Button
variant="primary"
size="md"
stretch="auto"
label={isImageUploading ? "Uploading" : "Upload & Save"}
onClick={handleSubmit}
disabled={!image}
loading={isImageUploading}
/>
</div>
</div>
</div>

View File

@@ -10,7 +10,7 @@ import { useParams } from "next/navigation";
import { useDropzone } from "react-dropzone";
// plane imports
import { ACCEPTED_AVATAR_IMAGE_MIME_TYPES_FOR_REACT_DROPZONE, MAX_FILE_SIZE } from "@plane/constants";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { UserCirclePropertyIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { EFileAssetType } from "@plane/types";
@@ -156,16 +156,26 @@ export const WorkspaceImageUploadModal = observer(function WorkspaceImageUploadM
</div>
<p className="my-4 text-13 text-secondary">File formats supported- .jpeg, .jpg, .png, .webp</p>
<div className="flex items-center justify-between">
<Button variant="error-fill" size="lg" onClick={handleImageRemove} disabled={!value} loading={isRemoving}>
{isRemoving ? "Removing" : "Remove"}
</Button>
<Button
variant="danger"
size="md"
stretch="auto"
label={isRemoving ? "Removing" : "Remove"}
onClick={handleImageRemove}
disabled={!value}
loading={isRemoving}
/>
<div className="flex items-center gap-2">
<Button variant="secondary" size="lg" onClick={handleClose}>
Cancel
</Button>
<Button variant="primary" size="lg" onClick={handleSubmit} disabled={!image} loading={isImageUploading}>
{isImageUploading ? "Uploading" : "Upload & Save"}
</Button>
<Button variant="secondary" size="md" stretch="auto" label="Cancel" onClick={handleClose} />
<Button
variant="primary"
size="md"
stretch="auto"
label={isImageUploading ? "Uploading" : "Upload & Save"}
onClick={handleSubmit}
disabled={!image}
loading={isImageUploading}
/>
</div>
</div>
</div>

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
import { useForm } from "react-hook-form";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { IUserTheme } from "@plane/types";
import { applyCustomTheme } from "@plane/utils";
@@ -116,9 +116,14 @@ export const CustomThemeSelector = observer(function CustomThemeSelector() {
</div>
<div className="mt-5 flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
{/* Save Theme Button */}
<Button variant="primary" size="lg" type="submit" loading={isSubmitting || isLoadingPalette}>
{isSubmitting ? t("common.saving") : isLoadingPalette ? "Generating" : t("set_theme")}
</Button>
<Button
variant="primary"
size="md"
stretch="auto"
label={isSubmitting ? t("common.saving") : isLoadingPalette ? "Generating" : t("set_theme")}
type="submit"
loading={isSubmitting || isLoadingPalette}
/>
{/* Import/Export Section */}
<CustomThemeDownloadConfigButton getValues={getValues} />
</div>

View File

@@ -8,7 +8,7 @@ import { observer } from "mobx-react";
import type { UseFormGetValues } from "react-hook-form";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { setToast, TOAST_TYPE } from "@plane/propel/toast";
import type { IUserTheme } from "@plane/types";
@@ -58,8 +58,13 @@ export const CustomThemeDownloadConfigButton = observer(function CustomThemeDown
};
return (
<Button variant="secondary" size="lg" type="button" onClick={handleDownloadConfig}>
Download config
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
label="Download config"
type="button"
onClick={handleDownloadConfig}
/>
);
});

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
import type { UseFormSetValue } from "react-hook-form";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { setToast, TOAST_TYPE } from "@plane/propel/toast";
import type { IUserTheme } from "@plane/types";
@@ -93,9 +93,14 @@ export const CustomThemeImportConfigButton = observer(function CustomThemeImport
return (
<>
<input ref={fileInputRef} type="file" accept=".json" onChange={handleUploadConfig} className="hidden" />
<Button variant="secondary" size="lg" type="button" onClick={() => fileInputRef.current?.click()}>
Import config
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
label="Import config"
type="button"
onClick={() => fileInputRef.current?.click()}
/>
</>
);
});

View File

@@ -6,7 +6,7 @@
import { useState } from "react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
// hooks
@@ -69,12 +69,16 @@ export function ArchiveCycleModal(props: Props) {
Are you sure you want to archive the cycle? All your archives can be restored later.
</p>
<div className="mt-3 flex justify-end gap-2">
<Button variant="secondary" size="lg" onClick={onClose}>
Cancel
</Button>
<Button variant="primary" size="lg" tabIndex={1} onClick={handleArchiveCycle} loading={isArchiving}>
{isArchiving ? "Archiving" : "Archive"}
</Button>
<Button variant="secondary" size="md" stretch="auto" label="Cancel" onClick={onClose} />
<Button
variant="primary"
size="md"
stretch="auto"
label={isArchiving ? "Archiving" : "Archive"}
tabIndex={1}
onClick={handleArchiveCycle}
loading={isArchiving}
/>
</div>
</div>
</ModalCore>

View File

@@ -10,7 +10,7 @@ import { Controller, useForm } from "react-hook-form";
import { ETabIndices } from "@plane/constants";
// types
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { ICycle } from "@plane/types";
// ui
import { Input, TextArea } from "@plane/ui";
@@ -184,18 +184,31 @@ export function CycleForm(props: Props) {
</div>
</div>
<div className="flex items-center justify-end gap-2 border-t-[0.5px] border-subtle px-5 py-4">
<Button variant="secondary" size="lg" onClick={handleClose} tabIndex={getIndex("cancel")}>
{t("common.cancel")}
</Button>
<Button variant="primary" size="lg" type="submit" loading={isSubmitting} tabIndex={getIndex("submit")}>
{data
? isSubmitting
? t("common.updating")
: t("project_cycles.update_cycle")
: isSubmitting
? t("common.creating")
: t("project_cycles.create_cycle")}
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
label={t("common.cancel")}
onClick={handleClose}
tabIndex={getIndex("cancel")}
/>
<Button
variant="primary"
size="md"
stretch="auto"
label={
data
? isSubmitting
? t("common.updating")
: t("project_cycles.update_cycle")
: isSubmitting
? t("common.creating")
: t("project_cycles.create_cycle")
}
type="submit"
loading={isSubmitting}
tabIndex={getIndex("submit")}
/>
</div>
</form>
);

View File

@@ -7,7 +7,7 @@
import React from "react";
import { AlertCircle } from "lucide-react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TransferIcon } from "@plane/propel/icons";
type Props = {
@@ -27,9 +27,15 @@ export function TransferIssues(props: Props) {
{canTransferIssues && (
<div>
<Button variant="primary" size="lg" prependIcon={<TransferIcon />} onClick={handleClick} disabled={disabled}>
Transfer work items
</Button>
<Button
variant="primary"
size="md"
stretch="auto"
label="Transfer work items"
icon={<TransferIcon />}
onClick={handleClick}
disabled={disabled}
/>
</div>
)}
</div>

View File

@@ -6,7 +6,6 @@
import React from "react";
// helpers
import { Button } from "@plane/propel/button";
import { Tooltip } from "@plane/propel/tooltip";
import { cn } from "@plane/utils";
// types
@@ -78,11 +77,10 @@ function BorderButton(props: ButtonProps) {
isMobile={isMobile}
renderByDefault={renderToolTipByDefault}
>
<Button
variant="ghost"
size="sm"
<button
type="button"
className={cn(
"flex h-full w-full items-center justify-start gap-1.5 border-[0.5px] border-strong",
"inline-flex h-5 w-full items-center justify-start gap-1.5 rounded-sm border-[0.5px] border-strong px-1.5 text-caption-md-medium",
{
"bg-layer-transparent-active": isActive,
},
@@ -90,7 +88,7 @@ function BorderButton(props: ButtonProps) {
)}
>
{children}
</Button>
</button>
</Tooltip>
);
}
@@ -106,16 +104,15 @@ function BackgroundButton(props: ButtonProps) {
isMobile={isMobile}
renderByDefault={renderToolTipByDefault}
>
<Button
variant="ghost"
size="sm"
<button
type="button"
className={cn(
"flex h-full w-full items-center justify-between gap-1.5 bg-layer-3 hover:bg-layer-1-hover",
"inline-flex h-5 w-full items-center justify-between gap-1.5 rounded-sm bg-layer-3 px-1.5 text-caption-md-medium hover:bg-layer-1-hover",
className
)}
>
{children}
</Button>
</button>
</Tooltip>
);
}
@@ -131,11 +128,10 @@ function TransparentButton(props: ButtonProps) {
isMobile={isMobile}
renderByDefault={renderToolTipByDefault}
>
<Button
variant="ghost"
size="sm"
<button
type="button"
className={cn(
"flex h-full w-full items-center justify-between gap-1.5",
"inline-flex h-5 w-full items-center justify-between gap-1.5 rounded-sm px-1.5 text-caption-md-medium",
{
"bg-layer-transparent-active": isActive,
},
@@ -143,7 +139,7 @@ function TransparentButton(props: ButtonProps) {
)}
>
{children}
</Button>
</button>
</Tooltip>
);
}

View File

@@ -4,16 +4,15 @@
* See the LICENSE file for details.
*/
import { useCallback, useMemo } from "react";
import { useMemo } from "react";
import { observer } from "mobx-react";
// plane imports
import { ISSUE_LAYOUT_MAP } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@makeplane/propel/elements/button";
import { CheckIcon } from "@plane/propel/icons";
import { EIssueLayoutTypes } from "@plane/types";
import { getButtonStyling } from "@plane/propel/button";
import { Dropdown } from "@plane/ui";
import { cn } from "@plane/utils";
import { CustomMenu } from "@plane/ui";
// components
import { IssueLayoutIcon } from "@/components/issues/issue-layouts/layout-icon";
@@ -25,59 +24,37 @@ type TLayoutDropDown = {
export const LayoutDropDown = observer(function LayoutDropDown(props: TLayoutDropDown) {
const { onChange, value = EIssueLayoutTypes.LIST, disabledLayouts = [] } = props;
// plane i18n
const { t } = useTranslation();
// derived values
const availableLayouts = useMemo(
() => Object.values(ISSUE_LAYOUT_MAP).filter((layout) => !disabledLayouts.includes(layout.key)),
[disabledLayouts]
);
const options = useMemo(
() =>
availableLayouts.map((issueLayout) => ({
data: issueLayout.key,
value: issueLayout.key,
})),
[availableLayouts]
);
const buttonContent = useCallback((isOpen: boolean, buttonValue: string | string[] | undefined) => {
const dropdownValue = ISSUE_LAYOUT_MAP[buttonValue as EIssueLayoutTypes];
return (
<div className="flex items-center gap-2 text-secondary">
<IssueLayoutIcon layout={dropdownValue.key} strokeWidth={2} className={`size-3.5 text-secondary`} />
<span className="text-11 font-medium">{t(dropdownValue.i18n_label)}</span>
</div>
);
}, []);
const itemContent = useCallback((props: { value: string; selected: boolean }) => {
const dropdownValue = ISSUE_LAYOUT_MAP[props.value as EIssueLayoutTypes];
return (
<div className={cn("flex w-full items-center justify-between gap-2 text-secondary")}>
<div className="flex items-center gap-2">
<IssueLayoutIcon layout={dropdownValue.key} strokeWidth={2} className={`size-3 text-secondary`} />
<span className="text-11 font-medium">{t(dropdownValue.i18n_label)}</span>
</div>
{props.selected && <CheckIcon className="h-3.5 w-3.5 flex-shrink-0" />}
</div>
);
}, []);
const keyExtractor = useCallback((option: any) => option.value, []);
const selectedLayout = ISSUE_LAYOUT_MAP[value];
return (
<Dropdown
onChange={onChange as (value: string) => void}
value={value?.toString()}
keyExtractor={keyExtractor}
options={options}
buttonContainerClassName={cn(getButtonStyling("secondary", "lg"))}
buttonContent={buttonContent}
renderItem={itemContent}
disableSearch
/>
<CustomMenu
customButton={
<Button variant="secondary" size="md" stretch="auto" render={<div />}>
<IssueLayoutIcon layout={selectedLayout.key} strokeWidth={2} className="size-3.5 text-secondary" />
<span className="text-11 font-medium">{t(selectedLayout.i18n_label)}</span>
</Button>
}
placement="bottom-end"
closeOnSelect
>
{availableLayouts.map((issueLayout) => (
<CustomMenu.MenuItem
key={issueLayout.key}
className="flex items-center justify-between gap-2"
onClick={() => onChange(issueLayout.key)}
>
<div className="flex items-center gap-2">
<IssueLayoutIcon layout={issueLayout.key} strokeWidth={2} className="size-3 text-secondary" />
<span className="text-11 font-medium">{t(issueLayout.i18n_label)}</span>
</div>
{value === issueLayout.key && <CheckIcon className="h-3.5 w-3.5 flex-shrink-0" />}
</CustomMenu.MenuItem>
))}
</CustomMenu>
);
});

View File

@@ -13,7 +13,7 @@ import type { EditorRefApi } from "@plane/editor";
// i18n
import { useTranslation } from "@plane/i18n";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { GlobeIcon, LockIcon } from "@plane/propel/icons";
import type { ISvgIcons } from "@plane/propel/icons";
import { Tooltip } from "@plane/propel/tooltip";
@@ -177,16 +177,18 @@ export function IssueCommentToolbar(props: Props) {
</div>
{showSubmitButton && (
<div className="sticky right-1">
<Button
type="submit"
variant="primary"
className="px-2.5 py-1.5 text-11"
onClick={handleSubmit}
disabled={isSubmitButtonDisabled}
loading={isSubmitting}
>
{t(submitButtonText)}
</Button>
<span className="px-2.5 py-1.5 text-11">
<Button
variant="primary"
size="sm"
stretch="auto"
label={t(submitButtonText)}
type="submit"
onClick={handleSubmit}
disabled={isSubmitButtonDisabled}
loading={isSubmitting}
/>
</span>
</div>
)}
</div>

View File

@@ -9,7 +9,7 @@ import { Fragment, useState } from "react";
import { usePopper } from "react-popper";
import { Popover } from "@headlessui/react";
// plane imports
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
type Props = {
label: string;
@@ -32,7 +32,7 @@ export function ComicBoxButton(props: Props) {
setIsHovered(false);
};
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
const [referenceElement, setReferenceElement] = useState<HTMLSpanElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>();
const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: "right-end",
@@ -49,18 +49,25 @@ export function ComicBoxButton(props: Props) {
return (
<Popover as="div" className="relative">
<Popover.Button as={Fragment}>
<Button variant="primary" size="lg" ref={setReferenceElement} onClick={onClick} disabled={disabled}>
{icon}
<span className="leading-4">{label}</span>
<span className="relative inline-flex" ref={setReferenceElement}>
<Button
variant="primary"
size="md"
stretch="auto"
onClick={onClick}
disabled={disabled}
icon={icon}
label={label}
/>
<span className="relative h-2 w-2">
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
className={`bg-blue-300 absolute right-0 z-10 h-2.5 w-2.5 animate-ping rounded-full`}
className="bg-blue-300 absolute right-0 z-10 h-2.5 w-2.5 animate-ping rounded-full"
/>
<div className={`bg-blue-400/40 absolute right-0 mt-0.5 mr-0.5 h-1.5 w-1.5 rounded-full`} />
<div className="bg-blue-400/40 absolute right-0 mt-0.5 mr-0.5 h-1.5 w-1.5 rounded-full" />
</span>
</Button>
</span>
</Popover.Button>
{isHovered && (
<Popover.Panel className="fixed z-10" static>

View File

@@ -7,7 +7,7 @@
import React from "react";
import { observer } from "mobx-react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
// utils
import { cn } from "@plane/utils";
@@ -50,15 +50,15 @@ function CustomButton({
}) {
return (
<Button
variant={variant}
size={size}
variant="primary"
size="sm"
stretch="auto"
label={config.text}
icon={config.appendIcon}
iconPosition="end"
onClick={config.onClick}
prependIcon={config.prependIcon}
appendIcon={config.appendIcon}
disabled={config.disabled}
>
{config.text}
</Button>
/>
);
}

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
// plane imports
import { EEstimateSystem, ESTIMATE_SYSTEMS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { ChevronLeftIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { IEstimateFormData, TEstimateSystemKeys, TEstimatePointsObject, TEstimateTypeError } from "@plane/types";
@@ -200,13 +200,23 @@ export const CreateEstimateModal = observer(function CreateEstimateModal(props:
</div>
<div className="relative flex items-center justify-end gap-3 border-t border-subtle px-5 pt-5">
<Button variant="secondary" size="lg" onClick={handleClose} disabled={buttonLoader}>
{t("common.cancel")}
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
label={t("common.cancel")}
onClick={handleClose}
disabled={buttonLoader}
/>
{estimatePoints && (
<Button variant="primary" size="lg" onClick={handleCreateEstimate} disabled={buttonLoader}>
{buttonLoader ? t("common.creating") : t("project_settings.estimates.create.label")}
</Button>
<Button
variant="primary"
size="md"
stretch="auto"
label={buttonLoader ? t("common.creating") : t("project_settings.estimates.create.label")}
onClick={handleCreateEstimate}
disabled={buttonLoader}
/>
)}
</div>
</div>

View File

@@ -7,7 +7,7 @@
import { useState } from "react";
import { observer } from "mobx-react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
// hooks
@@ -76,12 +76,22 @@ export const DeleteEstimateModal = observer(function DeleteEstimateModal(props:
</div>
<div className="relative flex items-center justify-end gap-3 border-t border-subtle px-5 pt-5">
<Button variant="secondary" size="lg" onClick={handleClose} disabled={buttonLoader}>
Cancel
</Button>
<Button variant="error-fill" size="lg" onClick={handleDeleteEstimate} disabled={buttonLoader}>
{buttonLoader ? "Deleting" : "Delete Estimate"}
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
label="Cancel"
onClick={handleClose}
disabled={buttonLoader}
/>
<Button
variant="danger"
size="md"
stretch="auto"
label={buttonLoader ? "Deleting" : "Delete Estimate"}
onClick={handleDeleteEstimate}
disabled={buttonLoader}
/>
</div>
</div>
</ModalCore>

View File

@@ -9,7 +9,7 @@ import { useCallback, useState } from "react";
import { observer } from "mobx-react";
// plane imports
import { estimateCount } from "@plane/constants";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { PlusIcon } from "@plane/propel/icons";
import type { TEstimatePointsObject, TEstimateSystemKeys, TEstimateTypeError } from "@plane/types";
import { Sortable } from "@plane/ui";
@@ -171,9 +171,14 @@ export const EstimatePointCreateRoot = observer(function EstimatePointCreateRoot
/>
))}
{estimatePoints && estimatePoints.length + (estimatePointCreate?.length || 0) <= estimateCount.max - 1 && (
<Button variant="link" prependIcon={<PlusIcon />} onClick={handleCreate}>
Add {estimateType}
</Button>
<Button
variant="ghost"
size="sm"
stretch="auto"
icon={<PlusIcon />}
onClick={handleCreate}
label={`Add ${estimateType}`}
/>
)}
</div>
);

View File

@@ -16,7 +16,7 @@ import {
// ISSUE_DISPLAY_FILTERS_BY_PAGE,
} from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
// import { Tooltip } from "@plane/propel/tooltip";
// import { EIssuesStoreType } from "@plane/types";
@@ -208,9 +208,14 @@ export const ExportForm = observer(function ExportForm(props: Props) {
}
/>
<div className="px-4 py-3">
<Button variant="primary" size="lg" type="submit" loading={exportLoading}>
{exportLoading ? `${t("workspace_settings.settings.exports.exporting")}...` : t("export")}
</Button>
<Button
variant="primary"
size="md"
stretch="auto"
label={exportLoading ? `${t("workspace_settings.settings.exports.exporting")}...` : t("export")}
type="submit"
loading={exportLoading}
/>
</div>
</div>
{/* Rich Filters */}

View File

@@ -10,7 +10,7 @@ import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// types
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { IUser, IImporterService } from "@plane/types";
// ui
@@ -153,14 +153,20 @@ export const Exporter = observer(function Exporter(props: Props) {
onCheckedChange={setMultiple}
/>
<div className="flex justify-end gap-2">
<Button variant="secondary" onClick={handleClose}>
{t("cancel")}
</Button>
<Button variant="primary" onClick={ExportCSVToMail} disabled={exportLoading} loading={exportLoading}>
{exportLoading
? `${t("workspace_settings.settings.exports.exporting")}...`
: t("workspace_settings.settings.exports.title")}
</Button>
<Button variant="secondary" size="sm" stretch="auto" label={t("cancel")} onClick={handleClose} />
<Button
variant="primary"
size="sm"
stretch="auto"
label={
exportLoading
? `${t("workspace_settings.settings.exports.exporting")}...`
: t("workspace_settings.settings.exports.title")
}
onClick={ExportCSVToMail}
disabled={exportLoading}
loading={exportLoading}
/>
</div>
</div>
</ModalCore>

View File

@@ -10,7 +10,7 @@ import useSWR, { mutate } from "swr";
import { MoveLeft, MoveRight, RefreshCw } from "lucide-react";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { EmptyStateCompact } from "@plane/propel/empty-state";
import type { IExportData } from "@plane/types";
import { Table } from "@plane/ui";
@@ -78,31 +78,38 @@ export const PrevExports = observer(function PrevExports(props: Props) {
<div className="flex items-center justify-between border-b border-subtle pb-3.5">
<div className="flex items-center gap-2">
<h3 className="text-h6-medium text-primary">{t("workspace_settings.settings.exports.previous_exports")}</h3>
<Button variant="tertiary" className="shrink-0" onClick={handleRefresh}>
<RefreshCw className={`h-3 w-3 ${refreshing ? "animate-spin" : ""}`} />
{refreshing ? t("refreshing") : t("refresh_status")}
</Button>
<span className="shrink-0">
<Button
variant="tertiary"
size="sm"
stretch="auto"
onClick={handleRefresh}
icon={<RefreshCw className={`h-3 w-3 ${refreshing ? "animate-spin" : ""}`} />}
label={refreshing ? t("refreshing") : t("refresh_status")}
/>
</span>
</div>
{Array.isArray(exporterServices?.results) && exporterServices.results.length > 0 && (
<div className="flex items-center gap-2 text-11">
<Button
variant="secondary"
size="sm"
size="xs"
stretch="auto"
label={t("prev")}
icon={<MoveLeft />}
disabled={!exporterServices?.prev_page_results}
onClick={() => exporterServices?.prev_page_results && setCursor(exporterServices?.prev_cursor)}
prependIcon={<MoveLeft />}
>
{t("prev")}
</Button>
/>
<Button
variant="secondary"
size="sm"
size="xs"
stretch="auto"
label={t("next")}
icon={<MoveRight />}
iconPosition="end"
disabled={!exporterServices?.next_page_results}
onClick={() => exporterServices?.next_page_results && setCursor(exporterServices?.next_cursor)}
appendIcon={<MoveRight />}
>
{t("next")}
</Button>
/>
</div>
)}
</div>

View File

@@ -6,7 +6,7 @@
import { useState } from "react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { IExportData } from "@plane/types";
// helpers
import { getDate, renderFormattedDate } from "@plane/utils";
@@ -66,9 +66,7 @@ export function SingleExport({ service, refreshing }: Props) {
{service.status == "completed" && (
<div>
<a target="_blank" href={service?.url} rel="noopener noreferrer">
<Button variant="primary" className="w-full">
{isLoading ? "Downloading..." : "Download"}
</Button>
<Button variant="primary" size="sm" stretch="full" label={isLoading ? "Downloading..." : "Download"} />
</a>
</div>
)}

View File

@@ -6,10 +6,8 @@
import { useTranslation } from "@plane/i18n";
// ui
import { getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { PlaneLogo } from "@plane/propel/icons";
// helpers
import { cn } from "@plane/utils";
export function ProductUpdatesFooter() {
const { t } = useTranslation();
@@ -58,18 +56,15 @@ export function ProductUpdatesFooter() {
Forum
</a>
</div>
<a
href="https://plane.so/pages"
target="_blank"
className={cn(
getButtonStyling("secondary", "base"),
"flex items-center gap-1.5 text-center font-medium underline-offset-2 outline-none hover:underline"
)}
rel="noreferrer"
>
<PlaneLogo className="h-4 w-auto text-primary" />
{t("powered_by_plane_pages")}
</a>
<Button
variant="secondary"
size="sm"
stretch="auto"
label={t("powered_by_plane_pages")}
icon={<PlaneLogo className="h-4 w-auto text-primary" />}
nativeButton={false}
render={<a href="https://plane.so/pages" target="_blank" rel="noreferrer" />}
/>
</div>
);
}

View File

@@ -10,7 +10,7 @@ import { Controller, useForm } from "react-hook-form";
// plane types
// plane ui
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { TLinkEditableFields } from "@plane/types";
import { Input, ModalCore } from "@plane/ui";
import type { TLinkOperations } from "./use-links";
@@ -126,13 +126,15 @@ export const LinkCreateUpdateModal = observer(function LinkCreateUpdateModal(pro
</div>
</div>
<div className="flex items-center justify-end gap-2 border-t-[0.5px] border-subtle px-5 py-4">
<Button variant="secondary" size="lg" onClick={onClose}>
{t("Cancel")}
</Button>
<Button variant="primary" size="lg" type="submit" loading={isSubmitting}>
{preloadedData?.id ? (isSubmitting ? t("updating") : t("update")) : isSubmitting ? t("adding") : t("add")}{" "}
{t("home.quick_links.title")}
</Button>
<Button variant="secondary" size="md" stretch="auto" label={t("Cancel")} onClick={onClose} />
<Button
variant="primary"
size="md"
stretch="auto"
label={`${preloadedData?.id ? (isSubmitting ? t("updating") : t("update")) : isSubmitting ? t("adding") : t("add")} ${t("home.quick_links.title")}`}
type="submit"
loading={isSubmitting}
/>
</div>
</form>
</ModalCore>

View File

@@ -10,7 +10,7 @@ import { Clock, FileStack, MoreHorizontal, MoveRight } from "lucide-react";
// plane imports
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { IconButton, getIconButtonStyling } from "@plane/propel/icon-button";
import {
LinkIcon,
@@ -328,7 +328,10 @@ export const InboxIssueActionsHeader = observer(function InboxIssueActionsHeader
{canMarkAsAccepted && (
<Button
variant="secondary"
size="lg"
size="md"
stretch="auto"
icon={<CheckCircleFilledIcon className="size-4 shrink-0 text-success-secondary" />}
label={t("inbox_issue.actions.accept")}
onClick={() =>
handleActionWithPermission(
isProjectAdmin,
@@ -336,16 +339,16 @@ export const InboxIssueActionsHeader = observer(function InboxIssueActionsHeader
t("inbox_issue.errors.accept_permission")
)
}
>
<CheckCircleFilledIcon className="size-4 shrink-0 text-success-secondary" />
{t("inbox_issue.actions.accept")}
</Button>
/>
)}
{canMarkAsDeclined && (
<Button
variant="secondary"
size="lg"
size="md"
stretch="auto"
icon={<CloseCircleFilledIcon className="size-4 shrink-0 text-danger-secondary" />}
label={t("inbox_issue.actions.decline")}
onClick={() =>
handleActionWithPermission(
isProjectAdmin,
@@ -353,26 +356,27 @@ export const InboxIssueActionsHeader = observer(function InboxIssueActionsHeader
t("inbox_issue.errors.decline_permission")
)
}
>
<CloseCircleFilledIcon className="size-4 shrink-0 text-danger-secondary" />
{t("inbox_issue.actions.decline")}
</Button>
/>
)}
{isAcceptedOrDeclined ? (
<div className="flex items-center gap-2">
<Button
variant="secondary"
size="lg"
prependIcon={<LinkIcon className="h-2.5 w-2.5" />}
size="md"
stretch="auto"
label={t("inbox_issue.actions.copy")}
icon={<LinkIcon className="h-2.5 w-2.5" />}
onClick={() => handleCopyIssueLink(workItemLink)}
>
{t("inbox_issue.actions.copy")}
</Button>
/>
<ControlLink href={workItemLink} onClick={() => router.push(workItemLink)} target="_self">
<Button variant="secondary" size="lg" prependIcon={<NewTabIcon className="h-2.5 w-2.5" />}>
{t("inbox_issue.actions.open")}
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
label={t("inbox_issue.actions.open")}
icon={<NewTabIcon className="h-2.5 w-2.5" />}
/>
</ControlLink>
</div>
) : (

View File

@@ -5,10 +5,9 @@
*/
import { ListFilter } from "lucide-react";
import { getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/elements/button";
// plane imports
import { ChevronDownIcon } from "@plane/propel/icons";
import { cn } from "@plane/utils";
// components
import { FiltersDropdown } from "@/components/issues/issue-layouts/filters";
// hooks
@@ -20,11 +19,11 @@ import { InboxIssueOrderByDropdown } from "./sorting/order-by";
const smallButton = <ListFilter className="size-3" />;
const largeButton = (
<div className={cn(getButtonStyling("secondary", "base"), "px-2 text-tertiary")}>
<Button variant="secondary" size="sm" stretch="auto" render={<div />}>
<ListFilter className="size-3" />
<span>Filters</span>
<ChevronDownIcon className="size-3" strokeWidth={2} />
</div>
</Button>
);
export function FiltersRoot() {
const windowSize = useSize();

View File

@@ -8,13 +8,10 @@ import { observer } from "mobx-react";
import { ArrowDownWideNarrow, ArrowUpWideNarrow } from "lucide-react";
import { INBOX_ISSUE_ORDER_BY_OPTIONS, INBOX_ISSUE_SORT_BY_OPTIONS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/elements/button";
import { CheckIcon, ChevronDownIcon } from "@plane/propel/icons";
import type { TInboxIssueSortingOrderByKeys, TInboxIssueSortingSortByKeys } from "@plane/types";
import { CustomMenu } from "@plane/ui";
// constants
// helpers
import { cn } from "@plane/utils";
// hooks
import { useProjectInbox } from "@/hooks/store/use-project-inbox";
import useSize from "@/hooks/use-window-size";
@@ -33,7 +30,7 @@ export const InboxIssueOrderByDropdown = observer(function InboxIssueOrderByDrop
<ArrowDownWideNarrow className="size-3" />
);
const largeButton = (
<div className={cn(getButtonStyling("secondary", "base"), "px-2 text-tertiary")}>
<Button variant="secondary" size="sm" stretch="auto" render={<div />}>
{inboxSorting?.sort_by === "asc" ? (
<ArrowUpWideNarrow className="size-3" />
) : (
@@ -41,7 +38,7 @@ export const InboxIssueOrderByDropdown = observer(function InboxIssueOrderByDrop
)}
{t(orderByDetails?.i18n_label || "inbox_issue.order_by.created_at")}
<ChevronDownIcon className="size-3" strokeWidth={2} />
</div>
</Button>
);
return (
<CustomMenu

View File

@@ -13,7 +13,7 @@ import { observer } from "mobx-react";
import { ETabIndices } from "@plane/constants";
import type { EditorRefApi } from "@plane/editor";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { TIssue } from "@plane/types";
import { Switch } from "@makeplane/propel/components/switch";
@@ -218,7 +218,9 @@ export const InboxIssueCreateRoot = observer(function InboxIssueCreateRoot(props
<div className="flex items-center gap-3">
<Button
variant="secondary"
size="lg"
size="md"
stretch="auto"
label={t("discard")}
type="button"
onClick={() => {
if (descriptionEditorRef.current?.isEditorReadyToDiscard()) {
@@ -232,20 +234,18 @@ export const InboxIssueCreateRoot = observer(function InboxIssueCreateRoot(props
}
}}
tabIndex={getIndex("discard_button")}
>
{t("discard")}
</Button>
/>
<Button
variant="primary"
size="md"
stretch="auto"
label={formSubmitting ? t("creating") : t("create_work_item")}
ref={submitBtnRef}
type="submit"
loading={formSubmitting}
disabled={isTitleLengthMoreThan255Character}
tabIndex={getIndex("submit_button")}
size="lg"
>
{formSubmitting ? t("creating") : t("create_work_item")}
</Button>
/>
</div>
</div>
</form>

View File

@@ -7,7 +7,7 @@
import { useState } from "react";
// ui
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { Calendar } from "@plane/propel/calendar";
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
@@ -52,13 +52,14 @@ export function InboxIssueSnoozeModal(props: InboxIssueSnoozeModalProps) {
/>
<Button
variant="primary"
size="sm"
stretch="auto"
label={t("inbox_issue.actions.snooze")}
onClick={() => {
handleClose();
onConfirm(date);
}}
>
{t("inbox_issue.actions.snooze")}
</Button>
/>
</div>
</ModalCore>
);

View File

@@ -11,7 +11,7 @@ import GradientLogo from "@/app/assets/auth/gradient-logo.webp?url";
import GradientBgLogo from "@/app/assets/auth/gradient-bg-logo.webp?url";
import DefaultLayout from "@/layouts/default-layout";
import { PlaneLockup } from "@plane/propel/icons";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
export function InstanceNotReady() {
return (
@@ -46,9 +46,7 @@ export function InstanceNotReady() {
</div>
</div>
<a href={GOD_MODE_URL} className="w-72">
<Button variant="primary" className="w-full" size="xl">
Get started
</Button>
<Button variant="primary" size="lg" stretch="full" label="Get started" />
</a>
</div>
</div>

View File

@@ -10,7 +10,7 @@ import { useParams } from "next/navigation";
import useSWR, { mutate } from "swr";
import { CheckCircle } from "lucide-react";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { Tooltip } from "@plane/propel/tooltip";
import type { IAppIntegration, IWorkspaceIntegration } from "@plane/types";
@@ -144,18 +144,20 @@ export const SingleIntegrationCard = observer(function SingleIntegrationCard({ i
disabled={isUserAdmin}
tooltipContent={!isUserAdmin ? "You don't have permission to perform this" : null}
>
<Button
className={`${!isUserAdmin ? "hover:cursor-not-allowed" : ""}`}
variant="error-fill"
onClick={() => {
if (!isUserAdmin) return;
handleRemoveIntegration();
}}
disabled={!isUserAdmin}
loading={deletingIntegration}
>
{deletingIntegration ? "Uninstalling..." : "Uninstall"}
</Button>
<span className={`${!isUserAdmin ? "hover:cursor-not-allowed" : ""}`}>
<Button
variant="danger"
size="sm"
stretch="auto"
label={deletingIntegration ? "Uninstalling..." : "Uninstall"}
onClick={() => {
if (!isUserAdmin) return;
handleRemoveIntegration();
}}
disabled={!isUserAdmin}
loading={deletingIntegration}
/>
</span>
</Tooltip>
) : (
<Tooltip
@@ -163,17 +165,19 @@ export const SingleIntegrationCard = observer(function SingleIntegrationCard({ i
disabled={isUserAdmin}
tooltipContent={!isUserAdmin ? "You don't have permission to perform this" : null}
>
<Button
className={`${!isUserAdmin ? "hover:cursor-not-allowed" : ""}`}
variant="primary"
onClick={() => {
if (!isUserAdmin) return;
startAuth();
}}
loading={isInstalling}
>
{isInstalling ? "Installing..." : "Install"}
</Button>
<span className={`${!isUserAdmin ? "hover:cursor-not-allowed" : ""}`}>
<Button
variant="primary"
size="sm"
stretch="auto"
label={isInstalling ? "Installing..." : "Install"}
onClick={() => {
if (!isUserAdmin) return;
startAuth();
}}
loading={isInstalling}
/>
</span>
</Tooltip>
)
) : (

View File

@@ -8,7 +8,7 @@ import { useState } from "react";
// i18n
import { useTranslation } from "@plane/i18n";
// types
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { TDeDupeIssue, TIssue } from "@plane/types";
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
@@ -75,12 +75,16 @@ export function ArchiveIssueModal(props: Props) {
</h3>
<p className="mt-3 text-13 text-secondary">{t("issue.archive.confirm_message")}</p>
<div className="mt-3 flex justify-end gap-2">
<Button variant="secondary" size="lg" onClick={onClose}>
{t("common.cancel")}
</Button>
<Button variant="primary" size="lg" tabIndex={1} onClick={handleArchiveIssue} loading={isArchiving}>
{isArchiving ? t("common.archiving") : t("common.archive")}
</Button>
<Button variant="secondary" size="md" stretch="auto" label={t("common.cancel")} onClick={onClose} />
<Button
variant="primary"
size="md"
stretch="auto"
label={isArchiving ? t("common.archiving") : t("common.archive")}
tabIndex={1}
onClick={handleArchiveIssue}
loading={isArchiving}
/>
</div>
</div>
</ModalCore>

View File

@@ -5,7 +5,7 @@
*/
import { MARKETING_PLANE_ONE_PAGE_LINK } from "@plane/constants";
import { getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { cn } from "@plane/utils";
type Props = {
@@ -22,14 +22,16 @@ export function BulkOperationsUpgradeBanner(props: Props) {
Change state, priority, and more for several work items at once. Save three minutes on an average per
operation.
</p>
<a
href={MARKETING_PLANE_ONE_PAGE_LINK}
target="_blank"
rel="noopener noreferrer"
className={cn(getButtonStyling("primary", "base"), "flex-shrink-0")}
>
Upgrade to One
</a>
<span className="flex-shrink-0">
<Button
variant="primary"
size="sm"
stretch="auto"
label="Upgrade to One"
nativeButton={false}
render={<a href={MARKETING_PLANE_ONE_PAGE_LINK} target="_blank" rel="noopener noreferrer" />}
/>
</span>
</div>
</div>
);

View File

@@ -6,7 +6,7 @@
import { useState } from "react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
type Props = {
@@ -48,17 +48,18 @@ export function ConfirmIssueDiscard(props: Props) {
</div>
<div className="flex justify-between gap-2 p-4 sm:px-6">
<div>
<Button variant="secondary" onClick={onDiscard}>
Discard
</Button>
<Button variant="secondary" size="sm" stretch="auto" label="Discard" onClick={onDiscard} />
</div>
<div className="flex items-center gap-2">
<Button variant="secondary" onClick={onClose}>
Cancel
</Button>
<Button variant="primary" onClick={handleDeletion} loading={isLoading}>
{isLoading ? "Saving" : "Save to Drafts"}
</Button>
<Button variant="secondary" size="sm" stretch="auto" label="Cancel" onClick={onClose} />
<Button
variant="primary"
size="sm"
stretch="auto"
label={isLoading ? "Saving" : "Save to Drafts"}
onClick={handleDeletion}
loading={isLoading}
/>
</div>
</div>
</ModalCore>

View File

@@ -10,7 +10,7 @@ import { ChartNoAxesColumn, SlidersHorizontal } from "lucide-react";
// plane imports
import { EIssueFilterType, ISSUE_STORE_TO_FILTERS_MAP } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { IIssueDisplayFilterOptions, IIssueDisplayProperties } from "@plane/types";
import { EIssueLayoutTypes, EIssuesStoreType } from "@plane/types";
// hooks
@@ -126,12 +126,16 @@ export const HeaderFilters = observer(function HeaderFilters(props: Props) {
/>
</FiltersDropdown>
{canUserCreateIssue ? (
<Button className="hidden px-2 md:block" onClick={() => setAnalyticsModal(true)} variant="secondary" size="lg">
<div className="hidden @4xl:flex">{t("common.analytics")}</div>
<div className="flex @4xl:hidden">
<ChartNoAxesColumn className="size-3.5" />
</div>
</Button>
<span className="hidden px-2 md:block">
<Button
onClick={() => setAnalyticsModal(true)}
variant="secondary"
size="md"
stretch="auto"
icon={<ChartNoAxesColumn className="size-3.5" />}
label={t("common.analytics")}
/>
</span>
) : (
<></>
)}

View File

@@ -11,7 +11,7 @@ import { Circle } from "lucide-react";
// plane imports
import { EUserPermissions, EUserPermissionsLevel, SPACE_BASE_PATH, SPACE_BASE_URL } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { NewTabIcon, WorkItemsIcon } from "@plane/propel/icons";
import { Tooltip } from "@plane/propel/tooltip";
import { EIssuesStoreType } from "@plane/types";
@@ -115,14 +115,13 @@ export const IssuesHeader = observer(function IssuesHeader() {
{canUserCreateIssue && (
<Button
variant="primary"
size="lg"
size="md"
stretch="auto"
onClick={() => {
toggleCreateIssueModal(true, EIssuesStoreType.PROJECT);
}}
>
<div className="block sm:hidden">{t("issue.label", { count: 1 })}</div>
<div className="hidden sm:block">{t("issue.add.label")}</div>
</Button>
label={t("issue.add.label")}
/>
)}
</Header.RightItem>
</Header>

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
// plane imports
import { ListFilter } from "lucide-react";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { GroupByColumnTypes, TIssue, TIssueServiceType, TSubIssueOperations } from "@plane/types";
import { EIssueServiceType, EIssuesStoreType } from "@plane/types";
// hooks
@@ -102,9 +102,13 @@ export const SubIssuesListRoot = observer(function SubIssuesListRoot(props: Prop
icon={<ListFilter />}
customClassName={storeType !== EIssuesStoreType.EPIC ? "border-none" : ""}
actionElement={
<Button variant="secondary" onClick={() => resetFilters(rootIssueId)}>
{t("sub_work_item.empty_state.list_filters.action")}
</Button>
<Button
variant="secondary"
size="sm"
stretch="auto"
label={t("sub_work_item.empty_state.list_filters.action")}
onClick={() => resetFilters(rootIssueId)}
/>
}
/>
) : (

View File

@@ -6,7 +6,7 @@
import React from "react";
// helpers
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
type Props = {
icon: React.ReactNode;
@@ -16,10 +16,5 @@ type Props = {
export function IssueDetailWidgetButton(props: Props) {
const { icon, title, disabled = false } = props;
return (
<Button variant={"secondary"} disabled={disabled} size="lg">
{icon && icon}
<span className="text-body-xs-medium">{title}</span>
</Button>
);
return <Button variant="secondary" size="md" stretch="auto" disabled={disabled} icon={icon} label={title} />;
}

View File

@@ -5,7 +5,7 @@
*/
import { observer } from "mobx-react";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { CloseIcon, LabelFilledIcon } from "@plane/propel/icons";
// types
import { useLabel } from "@/hooks/store/use-label";
@@ -37,10 +37,15 @@ export const LabelListItem = observer(function LabelListItem(props: TLabelListIt
if (!label) return <></>;
return (
<Button variant="tertiary" size="sm" key={labelId} onClick={handleLabel} disabled={disabled}>
<LabelFilledIcon className="size-3" color={label.color ?? "#000000"} />
<span className="text-body-xs-regular">{label.name}</span>
{!disabled && <CloseIcon className="h-2.5 w-2.5 transition-all group-hover:text-danger-primary" />}
</Button>
<Button
variant="tertiary"
size="xs"
stretch="auto"
key={labelId}
onClick={handleLabel}
disabled={disabled}
icon={<LabelFilledIcon className="size-3" color={label.color ?? "#000000"} />}
label={label.name}
/>
);
});

View File

@@ -12,7 +12,7 @@ import { Combobox } from "@headlessui/react";
// plane imports
import { EUserPermissionsLevel, getRandomLabelColor } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { CheckIcon, SearchIcon, PlusIcon } from "@plane/propel/icons";
import type { IIssueLabel } from "@plane/types";
import { EUserProjectRoles } from "@plane/types";
@@ -92,7 +92,7 @@ export const IssueLabelSelect = observer(function IssueLabelSelect(props: IIssue
const issueLabels = values ?? [];
const label = <span className="text-body-xs-medium text-placeholder">{t("label.select")}</span>;
const label = t("label.select");
const searchInputKeyDown = async (e: React.KeyboardEvent<HTMLInputElement>) => {
if (query !== "" && e.key === "Escape") {
@@ -128,15 +128,15 @@ export const IssueLabelSelect = observer(function IssueLabelSelect(props: IIssue
>
<Combobox.Button as={Fragment}>
<Button
variant="tertiary"
size="xs"
stretch="auto"
label={label}
icon={<PlusIcon />}
ref={setReferenceElement}
type="button"
variant="tertiary"
size="sm"
prependIcon={<PlusIcon />}
onClick={() => !projectLabels && fetchLabels()}
>
{label}
</Button>
/>
</Combobox.Button>
<Combobox.Options as="ul" className="fixed z-10">

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form";
import { useTranslation } from "@plane/i18n";
// plane types
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { TIssueLinkEditableFields, TIssueServiceType } from "@plane/types";
// plane ui
import { Input, ModalCore } from "@plane/ui";
@@ -134,11 +134,12 @@ export const IssueLinkCreateUpdateModal = observer(function IssueLinkCreateUpdat
</div>
</div>
<div className="flex items-center justify-end gap-2 border-t-[0.5px] border-subtle px-5 py-4">
<Button variant="secondary" size="lg" onClick={onClose}>
{t("common.cancel")}
</Button>
<Button variant="primary" size="lg" type="submit" loading={isSubmitting}>
{`${
<Button variant="secondary" size="md" stretch="auto" label={t("common.cancel")} onClick={onClose} />
<Button
variant="primary"
size="md"
stretch="auto"
label={`${
preloadedData?.id
? isSubmitting
? t("common.updating")
@@ -147,7 +148,9 @@ export const IssueLinkCreateUpdateModal = observer(function IssueLinkCreateUpdat
? t("common.adding")
: t("common.add")
} ${t("common.link")}`}
</Button>
type="submit"
loading={isSubmitting}
/>
</div>
</form>
</ModalCore>

View File

@@ -12,7 +12,7 @@ import { Bell, BellOff } from "lucide-react";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// UI
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { EIssueServiceType } from "@plane/types";
import { Loader } from "@plane/ui";
@@ -82,23 +82,15 @@ export const IssueSubscription = observer(function IssueSubscription(props: TIss
return (
<div>
<Button
prependIcon={isSubscribed ? <BellOff /> : <Bell className="h-3 w-3" />}
icon={isSubscribed ? <BellOff /> : <Bell className="h-3 w-3" />}
variant="secondary"
className="hover:!bg-accent-primary/20"
size="md"
stretch="auto"
onClick={handleSubscription}
disabled={!isEditable || loading}
size="lg"
>
{loading ? (
<span>
<span className="hidden sm:block">{t("common.loading")}</span>
</span>
) : isSubscribed ? (
<div className="hidden sm:block">{t("common.actions.unsubscribe")}</div>
) : (
<div className="hidden sm:block">{t("common.actions.subscribe")}</div>
)}
</Button>
loading={loading}
label={isSubscribed ? t("common.actions.unsubscribe") : t("common.actions.subscribe")}
/>
</div>
);
});

View File

@@ -10,7 +10,7 @@ import { usePopper } from "react-popper";
// headless ui
import { Popover, Transition } from "@headlessui/react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
type Props = {
children: React.ReactNode;
@@ -55,35 +55,29 @@ export function FiltersDropdown(props: Props) {
</button>
) : (
<div ref={setReferenceElement}>
<div className="hidden @4xl:flex">
<div className="relative hidden @4xl:flex">
<Button
disabled={disabled}
variant="secondary"
prependIcon={icon}
size="md"
stretch="auto"
icon={icon}
tabIndex={tabIndex}
className="relative"
size="lg"
>
<>
<div className={`${open ? "text-primary" : "text-secondary"}`}>
<span>{title}</span>
</div>
{isFiltersApplied && (
<span className="absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-accent-primary" />
)}
</>
</Button>
label={title ?? ""}
/>
{isFiltersApplied && (
<span className="absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-accent-primary" />
)}
</div>
<div className="flex @4xl:hidden">
<Button
disabled={disabled}
ref={setReferenceElement}
variant="secondary"
size="md"
stretch="auto"
label={typeof title === "string" ? title : "Filters"}
disabled={disabled}
tabIndex={tabIndex}
size="lg"
>
{miniIcon || title}
</Button>
/>
</div>
</div>
)}

View File

@@ -6,7 +6,7 @@
import { ISSUE_LAYOUTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { ChevronDownIcon } from "@plane/propel/icons";
import type { EIssueLayoutTypes } from "@plane/types";
import { CustomMenu } from "@plane/ui";
@@ -29,12 +29,19 @@ export function MobileLayoutSelection({
className="flex flex-grow justify-center text-13 text-secondary"
placement="bottom-start"
customButton={
<Button variant="secondary" className="relative px-2">
{activeLayout && (
<IssueLayoutIcon layout={activeLayout} size={14} strokeWidth={2} className={`h-3.5 w-3.5`} />
)}
<ChevronDownIcon className="my-auto size-3 text-secondary" strokeWidth={2} />
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
icon={
activeLayout ? (
<IssueLayoutIcon layout={activeLayout} size={14} strokeWidth={2} className="h-3.5 w-3.5" />
) : (
<ChevronDownIcon className="my-auto size-3 text-secondary" strokeWidth={2} />
)
}
label={t("common.layout")}
/>
}
customButtonClassName="flex flex-grow justify-center text-secondary text-13"
closeOnSelect

View File

@@ -16,7 +16,7 @@ import { ETabIndices, DEFAULT_WORK_ITEM_FORM_VALUES } from "@plane/constants";
import type { EditorRefApi } from "@plane/editor";
// i18n
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { TIssue, TWorkspaceDraftIssue } from "@plane/types";
// hooks
@@ -467,7 +467,9 @@ export const IssueFormRoot = observer(function IssueFormRoot(props: IssueFormPro
<div tabIndex={getIndex("discard_button")}>
<Button
variant="secondary"
size="lg"
size="md"
stretch="auto"
label={t("discard")}
onClick={() => {
if (editorRef.current?.isEditorReadyToDiscard()) {
onClose();
@@ -479,34 +481,32 @@ export const IssueFormRoot = observer(function IssueFormRoot(props: IssueFormPro
});
}
}}
>
{t("discard")}
</Button>
/>
</div>
<div tabIndex={isDraft ? getIndex("submit_button") : getIndex("draft_button")}>
<Button
variant={moveToIssue ? "secondary" : "primary"}
size="lg"
variant="primary"
size="md"
stretch="auto"
label={isSubmitting ? primaryButtonText.loading : primaryButtonText.default}
type="submit"
ref={submitBtnRef}
loading={isSubmitting}
disabled={isDisabled}
>
{isSubmitting ? primaryButtonText.loading : primaryButtonText.default}
</Button>
/>
</div>
{moveToIssue && (
<Button
variant="primary"
size="md"
stretch="auto"
label={t("add_to_project")}
type="button"
loading={isMoving}
onClick={handleMoveToProjects}
disabled={isMoving}
size="lg"
>
{t("add_to_project")}
</Button>
/>
)}
</div>
</div>

View File

@@ -13,7 +13,7 @@ import { Popover, Transition } from "@headlessui/react";
// plane imports
import { getRandomLabelColor, LABEL_COLOR_OPTIONS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { IIssueLabel } from "@plane/types";
import { Input } from "@plane/ui";
@@ -234,19 +234,18 @@ export const CreateUpdateLabelInline = observer(
)}
/>
</div>
<Button variant="secondary" onClick={() => handleClose()}>
{t("cancel")}
</Button>
<Button variant="secondary" size="sm" stretch="auto" label={t("cancel")} onClick={() => handleClose()} />
<Button
variant="primary"
size="sm"
stretch="auto"
label={isUpdating ? (isSubmitting ? t("updating") : t("update")) : isSubmitting ? t("adding") : t("add")}
onClick={(e) => {
e.preventDefault();
handleSubmit(handleFormSubmit)();
}}
loading={isSubmitting}
>
{isUpdating ? (isSubmitting ? t("updating") : t("update")) : isSubmitting ? t("adding") : t("add")}
</Button>
/>
</div>
{errors.name?.message && <p className="p-0.5 pl-8 text-13 text-danger-primary">{errors.name?.message}</p>}
</>

View File

@@ -10,7 +10,7 @@ import { useParams } from "next/navigation";
// plane imports
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { EmptyStateCompact } from "@plane/propel/empty-state";
import type { IIssueLabel } from "@plane/types";
import { Loader } from "@plane/ui";
@@ -85,9 +85,7 @@ export const ProjectSettingsLabelList = observer(function ProjectSettingsLabelLi
description={t("project_settings.labels.description")}
control={
isEditable && (
<Button variant="primary" size="lg" onClick={newLabel}>
{t("common.add_label")}
</Button>
<Button variant="primary" size="md" stretch="auto" label={t("common.add_label")} onClick={newLabel} />
)
}
/>

View File

@@ -6,7 +6,7 @@
import { observer } from "mobx-react";
// plane imports
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { EProductSubscriptionEnum, IPaymentProduct, TSubscriptionPrice } from "@plane/types";
import { Loader } from "@plane/ui";
// local imports
@@ -73,23 +73,26 @@ export const PlanCheckoutButton = observer(function PlanCheckoutButton(props: Pr
</Loader>
) : (
<div className="flex w-full flex-col items-center justify-center space-y-4">
<Button
variant="primary"
size="lg"
className="w-56"
onClick={() => {
if (product && price.id) {
handleCheckout({
planVariant,
productId: product.id,
priceId: price.id,
});
<span className="w-56">
<Button
variant="primary"
size="md"
stretch="auto"
label={
upgradeLoaderType === planVariant ? "Redirecting to Stripe" : (upgradeCTA ?? `Upgrade to ${planeName}`)
}
}}
disabled={!!upgradeLoaderType}
>
{upgradeLoaderType === planVariant ? "Redirecting to Stripe" : (upgradeCTA ?? `Upgrade to ${planeName}`)}
</Button>
onClick={() => {
if (product && price.id) {
handleCheckout({
planVariant,
productId: product.id,
priceId: price.id,
});
}
}}
disabled={!!upgradeLoaderType}
/>
</span>
{isTrialAllowed && !isSelfHosted && (
<div className="mt-1 h-3">
{renderTrialButton &&

View File

@@ -7,10 +7,9 @@
import { observer } from "mobx-react";
// types
// plane imports
import { getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { EProductSubscriptionEnum, IPaymentProduct, TSubscriptionPrice } from "@plane/types";
import { Loader } from "@plane/ui";
import { cn } from "@plane/utils";
// local imports
import { BasePaidPlanCard } from "./base-paid-plan-card";
@@ -72,9 +71,16 @@ export const TalkToSalesCard = observer(function TalkToSalesCard(props: TalkToSa
</Loader>
) : (
<div className="flex w-full flex-col items-center justify-center">
<a href={href} target="_blank" className={cn(getButtonStyling("primary", "lg"), "w-56")} rel="noreferrer">
Talk to Sales
</a>
<span className="w-56">
<Button
variant="primary"
size="md"
stretch="full"
label="Talk to Sales"
nativeButton={false}
render={<a href={href} target="_blank" rel="noreferrer" />}
/>
</span>
{isTrialAllowed && !isSelfHosted && (
<div className="mt-4 h-4">
{renderTrialButton &&

View File

@@ -6,7 +6,7 @@
import { useState } from "react";
// ui
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
// hooks
@@ -69,12 +69,16 @@ export function ArchiveModuleModal(props: Props) {
Are you sure you want to archive the module? All your archives can be restored later.
</p>
<div className="mt-3 flex justify-end gap-2">
<Button variant="secondary" size="lg" onClick={onClose}>
Cancel
</Button>
<Button variant="primary" size="lg" tabIndex={1} onClick={handleArchiveModule} loading={isArchiving}>
{isArchiving ? "Archiving" : "Archive"}
</Button>
<Button variant="secondary" size="md" stretch="auto" label="Cancel" onClick={onClose} />
<Button
variant="primary"
size="md"
stretch="auto"
label={isArchiving ? "Archiving" : "Archive"}
tabIndex={1}
onClick={handleArchiveModule}
loading={isArchiving}
/>
</div>
</div>
</ModalCore>

View File

@@ -7,15 +7,11 @@
import { ArrowDownWideNarrow, ArrowUpWideNarrow } from "lucide-react";
import { MODULE_ORDER_BY_OPTIONS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { getButtonStyling } from "@plane/propel/button";
import { Button } from "@makeplane/propel/elements/button";
import { CheckIcon, ChevronDownIcon } from "@plane/propel/icons";
import type { TModuleOrderByOptions } from "@plane/types";
// ui
import { CustomMenu } from "@plane/ui";
// helpers
import { cn } from "@plane/utils";
// types
// constants
type Props = {
onChange: (value: TModuleOrderByOptions) => void;
@@ -35,11 +31,11 @@ export function ModuleOrderByDropdown(props: Props) {
return (
<CustomMenu
customButton={
<div className={cn(getButtonStyling("secondary", "lg"), "px-2 text-tertiary")}>
<Button variant="secondary" size="md" stretch="auto" render={<div />}>
{!isDescending ? <ArrowUpWideNarrow className="size-3" /> : <ArrowDownWideNarrow className="size-3" />}
{orderByDetails && t(orderByDetails?.i18n_label)}
<ChevronDownIcon className="size-3" strokeWidth={2} />
</div>
</Button>
}
placement="bottom-end"
maxHeight="lg"

View File

@@ -9,7 +9,7 @@ import { Controller, useForm } from "react-hook-form";
// plane imports
import { ETabIndices } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import type { IModule } from "@plane/types";
// ui
import { Input, TextArea } from "@plane/ui";
@@ -233,18 +233,31 @@ export function ModuleForm(props: Props) {
</div>
</div>
<div className="flex items-center justify-end gap-2 border-t-[0.5px] border-subtle px-5 py-4">
<Button variant="secondary" size="lg" onClick={handleClose} tabIndex={getIndex("cancel")}>
{t("cancel")}
</Button>
<Button variant="primary" size="lg" type="submit" loading={isSubmitting} tabIndex={getIndex("submit")}>
{status
? isSubmitting
? t("updating")
: t("project_module.update_module")
: isSubmitting
? t("creating")
: t("project_module.create_module")}
</Button>
<Button
variant="secondary"
size="md"
stretch="auto"
label={t("cancel")}
onClick={handleClose}
tabIndex={getIndex("cancel")}
/>
<Button
variant="primary"
size="md"
stretch="auto"
label={
status
? isSubmitting
? t("updating")
: t("project_module.update_module")
: isSubmitting
? t("creating")
: t("project_module.create_module")
}
type="submit"
loading={isSubmitting}
tabIndex={getIndex("submit")}
/>
</div>
</form>
);

View File

@@ -7,7 +7,7 @@
import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
// plane types
import { Button } from "@plane/propel/button";
import { Button } from "@makeplane/propel/components/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { ILinkDetails, ModuleLink } from "@plane/types";
// plane ui
@@ -137,12 +137,15 @@ export function CreateUpdateModuleLinkModal(props: Props) {
</div>
</div>
<div className="flex items-center justify-end gap-2 border-t-[0.5px] border-subtle px-5 py-4">
<Button variant="secondary" size="lg" onClick={onClose}>
Cancel
</Button>
<Button variant="primary" size="lg" type="submit" loading={isSubmitting}>
{data ? (isSubmitting ? "Updating link" : "Update link") : isSubmitting ? "Adding link" : "Add link"}
</Button>
<Button variant="secondary" size="md" stretch="auto" label="Cancel" onClick={onClose} />
<Button
variant="primary"
size="md"
stretch="auto"
label={data ? (isSubmitting ? "Updating link" : "Update link") : isSubmitting ? "Adding link" : "Add link"}
type="submit"
loading={isSubmitting}
/>
</div>
</form>
</ModalCore>

Some files were not shown because too many files have changed in this diff Show More