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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,7 +10,7 @@ import { useParams } from "next/navigation";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
// ui // ui
import { Button } from "@plane/propel/button"; import { Button } from "@makeplane/propel/components/button";
import { ModuleIcon } from "@plane/propel/icons"; import { ModuleIcon } from "@plane/propel/icons";
import { Breadcrumbs, Header } from "@plane/ui"; import { Breadcrumbs, Header } from "@plane/ui";
// components // components
@@ -67,14 +67,13 @@ export const ModulesListHeader = observer(function ModulesListHeader() {
{canUserCreateModule ? ( {canUserCreateModule ? (
<Button <Button
variant="primary" variant="primary"
size="md"
stretch="auto"
label={t("project_module.add_module")}
onClick={() => { onClick={() => {
toggleCreateModuleModal(true); 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 Link from "next/link";
import useSWR from "swr"; import useSWR from "swr";
// plane types // plane types
import { getButtonStyling } from "@plane/propel/button"; import { Button } from "@makeplane/propel/components/button";
import type { TSearchEntityRequestPayload, TWebhookConnectionQueryParams } from "@plane/types"; import type { TSearchEntityRequestPayload, TWebhookConnectionQueryParams } from "@plane/types";
import { EFileAssetType } from "@plane/types"; import { EFileAssetType } from "@plane/types";
// plane ui
// plane utils
import { cn } from "@plane/utils";
// components // components
import { LogoSpinner } from "@/components/common/logo-spinner"; import { LogoSpinner } from "@/components/common/logo-spinner";
import { PageHead } from "@/components/core/page-title"; 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"> <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. The page you are trying to access doesn{"'"}t exist or you don{"'"}t have permission to view it.
</p> </p>
<Link <span className="mt-5">
href={`/${workspaceSlug}/projects/${projectId}/pages`} <Button
className={cn(getButtonStyling("secondary", "base"), "mt-5")} variant="secondary"
> size="sm"
View other Pages stretch="auto"
</Link> label="View other Pages"
nativeButton={false}
render={<Link href={`/${workspaceSlug}/projects/${projectId}/pages`} />}
/>
</span>
</div> </div>
); );

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,7 @@
import type { ColumnDef, Row, Table } from "@tanstack/react-table"; import type { ColumnDef, Row, Table } from "@tanstack/react-table";
import { Download } from "lucide-react"; import { Download } from "lucide-react";
import { useTranslation } from "@plane/i18n"; 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 type { AnalyticsTableDataMap, TAnalyticsTabsBase } from "@plane/types";
import { DataTable } from "./data-table"; import { DataTable } from "./data-table";
import { TableLoader } from "./loader"; import { TableLoader } from "./loader";
@@ -39,11 +39,12 @@ export function InsightTable<T extends Exclude<TAnalyticsTabsBase, "overview">>(
actions={(table: Table<AnalyticsTableDataMap[T]>) => ( actions={(table: Table<AnalyticsTableDataMap[T]>) => (
<Button <Button
variant="secondary" 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)} onClick={() => onExport?.(table.getFilteredRowModel().rows)}
> label={t("exporter.csv.short_description")}
<div>{t("exporter.csv.short_description")}</div> />
</Button>
)} )}
/> />
</div> </div>

View File

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

View File

@@ -15,7 +15,7 @@ import { Download } from "lucide-react";
import type { ChartXAxisDateGrouping } from "@plane/constants"; import type { ChartXAxisDateGrouping } from "@plane/constants";
import { ANALYTICS_X_AXIS_VALUES, ANALYTICS_Y_AXIS_VALUES, CHART_COLOR_PALETTES, EChartModels } 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 { 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 { BarChart } from "@plane/propel/charts/bar-chart";
import { EmptyStateCompact } from "@plane/propel/empty-state"; import { EmptyStateCompact } from "@plane/propel/empty-state";
import type { TBarItem, TChart, TChartDatum, ChartXAxisProperty, ChartYAxisMetric } from "@plane/types"; 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>) => ( actions={(table: Table<TChartDatum>) => (
<Button <Button
variant="secondary" 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)} onClick={() => exportCSV(table.getRowModel().rows, [...defaultColumns, ...columns], workspaceSlug)}
> label={t("exporter.csv.short_description")}
<div>{t("exporter.csv.short_description")}</div> />
</Button>
)} )}
/> />
</> </>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
*/ */
import { Controller, useForm } from "react-hook-form"; 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 { Calendar } from "@plane/propel/calendar";
import { CloseIcon } from "@plane/propel/icons"; import { CloseIcon } from "@plane/propel/icons";
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui"; import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
@@ -120,18 +120,16 @@ export function DateFilterModal({ title, handleClose, isOpen, onSelect }: Props)
</h6> </h6>
)} )}
<div className="flex justify-end gap-4"> <div className="flex justify-end gap-4">
<Button variant="secondary" size="lg" onClick={handleClose}> <Button variant="secondary" size="md" stretch="auto" label="Cancel" onClick={handleClose} />
Cancel
</Button>
<Button <Button
variant="primary" variant="primary"
size="lg" size="md"
stretch="auto"
label="Apply"
type="button" type="button"
onClick={handleSubmit(handleFormSubmit)} onClick={handleSubmit(handleFormSubmit)}
disabled={isInvalid} disabled={isInvalid}
> />
Apply
</Button>
</div> </div>
</form> </form>
</ModalCore> </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 { ACCEPTED_COVER_IMAGE_MIME_TYPES_FOR_REACT_DROPZONE, MAX_FILE_SIZE } from "@plane/constants";
import { useOutsideClickDetector } from "@plane/hooks"; import { useOutsideClickDetector } from "@plane/hooks";
import { Tabs } from "@plane/propel/tabs"; 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 { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { EFileAssetType } from "@plane/types"; import { EFileAssetType } from "@plane/types";
import { Input, Loader } from "@plane/ui"; import { Input, Loader } from "@plane/ui";
@@ -192,9 +193,15 @@ function ImagePickerPopoverComponent<TFieldValues extends FieldValues = FieldVal
return ( return (
<Popover className="relative z-19" ref={ref} tabIndex={tabIndex} onKeyDown={handleKeyDown}> <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} {label}
</Popover.Button> </ButtonElement>
{isOpen && ( {isOpen && (
<Popover.Panel <Popover.Panel
@@ -241,9 +248,13 @@ function ImagePickerPopoverComponent<TFieldValues extends FieldValues = FieldVal
/> />
)} )}
/> />
<Button variant="primary" size="xl" onClick={() => setSearchParams(formData.search)}> <Button
Search variant="primary"
</Button> size="lg"
stretch="auto"
label="Search"
onClick={() => setSearchParams(formData.search)}
/>
</div> </div>
{unsplashImages ? ( {unsplashImages ? (
unsplashImages.length > 0 ? ( unsplashImages.length > 0 ? (
@@ -349,22 +360,23 @@ function ImagePickerPopoverComponent<TFieldValues extends FieldValues = FieldVal
<div className="flex h-12 items-start justify-end gap-2"> <div className="flex h-12 items-start justify-end gap-2">
<Button <Button
variant="secondary" variant="secondary"
size="sm"
stretch="auto"
label="Cancel"
onClick={() => { onClick={() => {
setIsOpen(false); setIsOpen(false);
setImage(null); setImage(null);
}} }}
> />
Cancel
</Button>
<Button <Button
variant="primary" variant="primary"
className="w-full" size="sm"
stretch="full"
label={isImageUploading ? "Uploading" : "Upload & Save"}
onClick={handleSubmit} onClick={handleSubmit}
disabled={!image} disabled={!image}
loading={isImageUploading} loading={isImageUploading}
> />
{isImageUploading ? "Uploading" : "Upload & Save"}
</Button>
</div> </div>
</div> </div>
</Tabs.Content> </Tabs.Content>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,7 +6,6 @@
import React from "react"; import React from "react";
// helpers // helpers
import { Button } from "@plane/propel/button";
import { Tooltip } from "@plane/propel/tooltip"; import { Tooltip } from "@plane/propel/tooltip";
import { cn } from "@plane/utils"; import { cn } from "@plane/utils";
// types // types
@@ -78,11 +77,10 @@ function BorderButton(props: ButtonProps) {
isMobile={isMobile} isMobile={isMobile}
renderByDefault={renderToolTipByDefault} renderByDefault={renderToolTipByDefault}
> >
<Button <button
variant="ghost" type="button"
size="sm"
className={cn( 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, "bg-layer-transparent-active": isActive,
}, },
@@ -90,7 +88,7 @@ function BorderButton(props: ButtonProps) {
)} )}
> >
{children} {children}
</Button> </button>
</Tooltip> </Tooltip>
); );
} }
@@ -106,16 +104,15 @@ function BackgroundButton(props: ButtonProps) {
isMobile={isMobile} isMobile={isMobile}
renderByDefault={renderToolTipByDefault} renderByDefault={renderToolTipByDefault}
> >
<Button <button
variant="ghost" type="button"
size="sm"
className={cn( 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 className
)} )}
> >
{children} {children}
</Button> </button>
</Tooltip> </Tooltip>
); );
} }
@@ -131,11 +128,10 @@ function TransparentButton(props: ButtonProps) {
isMobile={isMobile} isMobile={isMobile}
renderByDefault={renderToolTipByDefault} renderByDefault={renderToolTipByDefault}
> >
<Button <button
variant="ghost" type="button"
size="sm"
className={cn( 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, "bg-layer-transparent-active": isActive,
}, },
@@ -143,7 +139,7 @@ function TransparentButton(props: ButtonProps) {
)} )}
> >
{children} {children}
</Button> </button>
</Tooltip> </Tooltip>
); );
} }

View File

@@ -4,16 +4,15 @@
* See the LICENSE file for details. * See the LICENSE file for details.
*/ */
import { useCallback, useMemo } from "react"; import { useMemo } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
// plane imports // plane imports
import { ISSUE_LAYOUT_MAP } from "@plane/constants"; import { ISSUE_LAYOUT_MAP } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { Button } from "@makeplane/propel/elements/button";
import { CheckIcon } from "@plane/propel/icons"; import { CheckIcon } from "@plane/propel/icons";
import { EIssueLayoutTypes } from "@plane/types"; import { EIssueLayoutTypes } from "@plane/types";
import { getButtonStyling } from "@plane/propel/button"; import { CustomMenu } from "@plane/ui";
import { Dropdown } from "@plane/ui";
import { cn } from "@plane/utils";
// components // components
import { IssueLayoutIcon } from "@/components/issues/issue-layouts/layout-icon"; import { IssueLayoutIcon } from "@/components/issues/issue-layouts/layout-icon";
@@ -25,59 +24,37 @@ type TLayoutDropDown = {
export const LayoutDropDown = observer(function LayoutDropDown(props: TLayoutDropDown) { export const LayoutDropDown = observer(function LayoutDropDown(props: TLayoutDropDown) {
const { onChange, value = EIssueLayoutTypes.LIST, disabledLayouts = [] } = props; const { onChange, value = EIssueLayoutTypes.LIST, disabledLayouts = [] } = props;
// plane i18n
const { t } = useTranslation(); const { t } = useTranslation();
// derived values
const availableLayouts = useMemo( const availableLayouts = useMemo(
() => Object.values(ISSUE_LAYOUT_MAP).filter((layout) => !disabledLayouts.includes(layout.key)), () => Object.values(ISSUE_LAYOUT_MAP).filter((layout) => !disabledLayouts.includes(layout.key)),
[disabledLayouts] [disabledLayouts]
); );
const selectedLayout = ISSUE_LAYOUT_MAP[value];
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, []);
return ( return (
<Dropdown <CustomMenu
onChange={onChange as (value: string) => void} customButton={
value={value?.toString()} <Button variant="secondary" size="md" stretch="auto" render={<div />}>
keyExtractor={keyExtractor} <IssueLayoutIcon layout={selectedLayout.key} strokeWidth={2} className="size-3.5 text-secondary" />
options={options} <span className="text-11 font-medium">{t(selectedLayout.i18n_label)}</span>
buttonContainerClassName={cn(getButtonStyling("secondary", "lg"))} </Button>
buttonContent={buttonContent} }
renderItem={itemContent} placement="bottom-end"
disableSearch 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 // i18n
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
// ui // ui
import { Button } from "@plane/propel/button"; import { Button } from "@makeplane/propel/components/button";
import { GlobeIcon, LockIcon } from "@plane/propel/icons"; import { GlobeIcon, LockIcon } from "@plane/propel/icons";
import type { ISvgIcons } from "@plane/propel/icons"; import type { ISvgIcons } from "@plane/propel/icons";
import { Tooltip } from "@plane/propel/tooltip"; import { Tooltip } from "@plane/propel/tooltip";
@@ -177,16 +177,18 @@ export function IssueCommentToolbar(props: Props) {
</div> </div>
{showSubmitButton && ( {showSubmitButton && (
<div className="sticky right-1"> <div className="sticky right-1">
<Button <span className="px-2.5 py-1.5 text-11">
type="submit" <Button
variant="primary" variant="primary"
className="px-2.5 py-1.5 text-11" size="sm"
onClick={handleSubmit} stretch="auto"
disabled={isSubmitButtonDisabled} label={t(submitButtonText)}
loading={isSubmitting} type="submit"
> onClick={handleSubmit}
{t(submitButtonText)} disabled={isSubmitButtonDisabled}
</Button> loading={isSubmitting}
/>
</span>
</div> </div>
)} )}
</div> </div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,7 @@
import { useState } from "react"; import { useState } from "react";
// ui // ui
import { useTranslation } from "@plane/i18n"; 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 { Calendar } from "@plane/propel/calendar";
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui"; import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
@@ -52,13 +52,14 @@ export function InboxIssueSnoozeModal(props: InboxIssueSnoozeModalProps) {
/> />
<Button <Button
variant="primary" variant="primary"
size="sm"
stretch="auto"
label={t("inbox_issue.actions.snooze")}
onClick={() => { onClick={() => {
handleClose(); handleClose();
onConfirm(date); onConfirm(date);
}} }}
> />
{t("inbox_issue.actions.snooze")}
</Button>
</div> </div>
</ModalCore> </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 GradientBgLogo from "@/app/assets/auth/gradient-bg-logo.webp?url";
import DefaultLayout from "@/layouts/default-layout"; import DefaultLayout from "@/layouts/default-layout";
import { PlaneLockup } from "@plane/propel/icons"; import { PlaneLockup } from "@plane/propel/icons";
import { Button } from "@plane/propel/button"; import { Button } from "@makeplane/propel/components/button";
export function InstanceNotReady() { export function InstanceNotReady() {
return ( return (
@@ -46,9 +46,7 @@ export function InstanceNotReady() {
</div> </div>
</div> </div>
<a href={GOD_MODE_URL} className="w-72"> <a href={GOD_MODE_URL} className="w-72">
<Button variant="primary" className="w-full" size="xl"> <Button variant="primary" size="lg" stretch="full" label="Get started" />
Get started
</Button>
</a> </a>
</div> </div>
</div> </div>

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,7 +10,7 @@ import { ChartNoAxesColumn, SlidersHorizontal } from "lucide-react";
// plane imports // plane imports
import { EIssueFilterType, ISSUE_STORE_TO_FILTERS_MAP } from "@plane/constants"; import { EIssueFilterType, ISSUE_STORE_TO_FILTERS_MAP } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; 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 type { IIssueDisplayFilterOptions, IIssueDisplayProperties } from "@plane/types";
import { EIssueLayoutTypes, EIssuesStoreType } from "@plane/types"; import { EIssueLayoutTypes, EIssuesStoreType } from "@plane/types";
// hooks // hooks
@@ -126,12 +126,16 @@ export const HeaderFilters = observer(function HeaderFilters(props: Props) {
/> />
</FiltersDropdown> </FiltersDropdown>
{canUserCreateIssue ? ( {canUserCreateIssue ? (
<Button className="hidden px-2 md:block" onClick={() => setAnalyticsModal(true)} variant="secondary" size="lg"> <span className="hidden px-2 md:block">
<div className="hidden @4xl:flex">{t("common.analytics")}</div> <Button
<div className="flex @4xl:hidden"> onClick={() => setAnalyticsModal(true)}
<ChartNoAxesColumn className="size-3.5" /> variant="secondary"
</div> size="md"
</Button> 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 // plane imports
import { EUserPermissions, EUserPermissionsLevel, SPACE_BASE_PATH, SPACE_BASE_URL } from "@plane/constants"; import { EUserPermissions, EUserPermissionsLevel, SPACE_BASE_PATH, SPACE_BASE_URL } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; 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 { NewTabIcon, WorkItemsIcon } from "@plane/propel/icons";
import { Tooltip } from "@plane/propel/tooltip"; import { Tooltip } from "@plane/propel/tooltip";
import { EIssuesStoreType } from "@plane/types"; import { EIssuesStoreType } from "@plane/types";
@@ -115,14 +115,13 @@ export const IssuesHeader = observer(function IssuesHeader() {
{canUserCreateIssue && ( {canUserCreateIssue && (
<Button <Button
variant="primary" variant="primary"
size="lg" size="md"
stretch="auto"
onClick={() => { onClick={() => {
toggleCreateIssueModal(true, EIssuesStoreType.PROJECT); toggleCreateIssueModal(true, EIssuesStoreType.PROJECT);
}} }}
> label={t("issue.add.label")}
<div className="block sm:hidden">{t("issue.label", { count: 1 })}</div> />
<div className="hidden sm:block">{t("issue.add.label")}</div>
</Button>
)} )}
</Header.RightItem> </Header.RightItem>
</Header> </Header>

View File

@@ -9,7 +9,7 @@ import { observer } from "mobx-react";
// plane imports // plane imports
import { ListFilter } from "lucide-react"; import { ListFilter } from "lucide-react";
import { useTranslation } from "@plane/i18n"; 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 type { GroupByColumnTypes, TIssue, TIssueServiceType, TSubIssueOperations } from "@plane/types";
import { EIssueServiceType, EIssuesStoreType } from "@plane/types"; import { EIssueServiceType, EIssuesStoreType } from "@plane/types";
// hooks // hooks
@@ -102,9 +102,13 @@ export const SubIssuesListRoot = observer(function SubIssuesListRoot(props: Prop
icon={<ListFilter />} icon={<ListFilter />}
customClassName={storeType !== EIssuesStoreType.EPIC ? "border-none" : ""} customClassName={storeType !== EIssuesStoreType.EPIC ? "border-none" : ""}
actionElement={ actionElement={
<Button variant="secondary" onClick={() => resetFilters(rootIssueId)}> <Button
{t("sub_work_item.empty_state.list_filters.action")} variant="secondary"
</Button> 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"; import React from "react";
// helpers // helpers
import { Button } from "@plane/propel/button"; import { Button } from "@makeplane/propel/components/button";
type Props = { type Props = {
icon: React.ReactNode; icon: React.ReactNode;
@@ -16,10 +16,5 @@ type Props = {
export function IssueDetailWidgetButton(props: Props) { export function IssueDetailWidgetButton(props: Props) {
const { icon, title, disabled = false } = props; const { icon, title, disabled = false } = props;
return ( return <Button variant="secondary" size="md" stretch="auto" disabled={disabled} icon={icon} label={title} />;
<Button variant={"secondary"} disabled={disabled} size="lg">
{icon && icon}
<span className="text-body-xs-medium">{title}</span>
</Button>
);
} }

View File

@@ -5,7 +5,7 @@
*/ */
import { observer } from "mobx-react"; 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"; import { CloseIcon, LabelFilledIcon } from "@plane/propel/icons";
// types // types
import { useLabel } from "@/hooks/store/use-label"; import { useLabel } from "@/hooks/store/use-label";
@@ -37,10 +37,15 @@ export const LabelListItem = observer(function LabelListItem(props: TLabelListIt
if (!label) return <></>; if (!label) return <></>;
return ( return (
<Button variant="tertiary" size="sm" key={labelId} onClick={handleLabel} disabled={disabled}> <Button
<LabelFilledIcon className="size-3" color={label.color ?? "#000000"} /> variant="tertiary"
<span className="text-body-xs-regular">{label.name}</span> size="xs"
{!disabled && <CloseIcon className="h-2.5 w-2.5 transition-all group-hover:text-danger-primary" />} stretch="auto"
</Button> 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 // plane imports
import { EUserPermissionsLevel, getRandomLabelColor } from "@plane/constants"; import { EUserPermissionsLevel, getRandomLabelColor } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; 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 { CheckIcon, SearchIcon, PlusIcon } from "@plane/propel/icons";
import type { IIssueLabel } from "@plane/types"; import type { IIssueLabel } from "@plane/types";
import { EUserProjectRoles } from "@plane/types"; import { EUserProjectRoles } from "@plane/types";
@@ -92,7 +92,7 @@ export const IssueLabelSelect = observer(function IssueLabelSelect(props: IIssue
const issueLabels = values ?? []; 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>) => { const searchInputKeyDown = async (e: React.KeyboardEvent<HTMLInputElement>) => {
if (query !== "" && e.key === "Escape") { if (query !== "" && e.key === "Escape") {
@@ -128,15 +128,15 @@ export const IssueLabelSelect = observer(function IssueLabelSelect(props: IIssue
> >
<Combobox.Button as={Fragment}> <Combobox.Button as={Fragment}>
<Button <Button
variant="tertiary"
size="xs"
stretch="auto"
label={label}
icon={<PlusIcon />}
ref={setReferenceElement} ref={setReferenceElement}
type="button" type="button"
variant="tertiary"
size="sm"
prependIcon={<PlusIcon />}
onClick={() => !projectLabels && fetchLabels()} onClick={() => !projectLabels && fetchLabels()}
> />
{label}
</Button>
</Combobox.Button> </Combobox.Button>
<Combobox.Options as="ul" className="fixed z-10"> <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 { Controller, useForm } from "react-hook-form";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
// plane types // plane types
import { Button } from "@plane/propel/button"; import { Button } from "@makeplane/propel/components/button";
import type { TIssueLinkEditableFields, TIssueServiceType } from "@plane/types"; import type { TIssueLinkEditableFields, TIssueServiceType } from "@plane/types";
// plane ui // plane ui
import { Input, ModalCore } from "@plane/ui"; import { Input, ModalCore } from "@plane/ui";
@@ -134,11 +134,12 @@ export const IssueLinkCreateUpdateModal = observer(function IssueLinkCreateUpdat
</div> </div>
</div> </div>
<div className="flex items-center justify-end gap-2 border-t-[0.5px] border-subtle px-5 py-4"> <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}> <Button variant="secondary" size="md" stretch="auto" label={t("common.cancel")} onClick={onClose} />
{t("common.cancel")} <Button
</Button> variant="primary"
<Button variant="primary" size="lg" type="submit" loading={isSubmitting}> size="md"
{`${ stretch="auto"
label={`${
preloadedData?.id preloadedData?.id
? isSubmitting ? isSubmitting
? t("common.updating") ? t("common.updating")
@@ -147,7 +148,9 @@ export const IssueLinkCreateUpdateModal = observer(function IssueLinkCreateUpdat
? t("common.adding") ? t("common.adding")
: t("common.add") : t("common.add")
} ${t("common.link")}`} } ${t("common.link")}`}
</Button> type="submit"
loading={isSubmitting}
/>
</div> </div>
</form> </form>
</ModalCore> </ModalCore>

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,7 @@ import { Popover, Transition } from "@headlessui/react";
// plane imports // plane imports
import { getRandomLabelColor, LABEL_COLOR_OPTIONS } from "@plane/constants"; import { getRandomLabelColor, LABEL_COLOR_OPTIONS } from "@plane/constants";
import { useTranslation } from "@plane/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 { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { IIssueLabel } from "@plane/types"; import type { IIssueLabel } from "@plane/types";
import { Input } from "@plane/ui"; import { Input } from "@plane/ui";
@@ -234,19 +234,18 @@ export const CreateUpdateLabelInline = observer(
)} )}
/> />
</div> </div>
<Button variant="secondary" onClick={() => handleClose()}> <Button variant="secondary" size="sm" stretch="auto" label={t("cancel")} onClick={() => handleClose()} />
{t("cancel")}
</Button>
<Button <Button
variant="primary" variant="primary"
size="sm"
stretch="auto"
label={isUpdating ? (isSubmitting ? t("updating") : t("update")) : isSubmitting ? t("adding") : t("add")}
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
handleSubmit(handleFormSubmit)(); handleSubmit(handleFormSubmit)();
}} }}
loading={isSubmitting} loading={isSubmitting}
> />
{isUpdating ? (isSubmitting ? t("updating") : t("update")) : isSubmitting ? t("adding") : t("add")}
</Button>
</div> </div>
{errors.name?.message && <p className="p-0.5 pl-8 text-13 text-danger-primary">{errors.name?.message}</p>} {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 // plane imports
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n"; 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 { EmptyStateCompact } from "@plane/propel/empty-state";
import type { IIssueLabel } from "@plane/types"; import type { IIssueLabel } from "@plane/types";
import { Loader } from "@plane/ui"; import { Loader } from "@plane/ui";
@@ -85,9 +85,7 @@ export const ProjectSettingsLabelList = observer(function ProjectSettingsLabelLi
description={t("project_settings.labels.description")} description={t("project_settings.labels.description")}
control={ control={
isEditable && ( isEditable && (
<Button variant="primary" size="lg" onClick={newLabel}> <Button variant="primary" size="md" stretch="auto" label={t("common.add_label")} onClick={newLabel} />
{t("common.add_label")}
</Button>
) )
} }
/> />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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