fix: address Button migration review on web call sites

Use IconButton for icon-only controls and AnchorButton for link-styled
actions. Add accessible names on render anchors, un-nest link+button
pairs, restore compact header labels, and pass through empty-state
variant/icon props.
This commit is contained in:
anmolsinghbhatia
2026-08-31 14:10:18 +05:30
parent 93282ad8f6
commit 550b46a1b5
20 changed files with 174 additions and 75 deletions

View File

@@ -9,6 +9,7 @@ import { Shapes } from "lucide-react";
// plane imports
import { useTranslation } from "@plane/i18n";
import { Button } from "@makeplane/propel/components/button";
import { IconButton } from "@makeplane/propel/components/icon-button";
import { HomeIcon } from "@plane/propel/icons";
import { Breadcrumbs, Header } from "@plane/ui";
// components
@@ -37,7 +38,7 @@ export const WorkspaceDashboardHeader = observer(function WorkspaceDashboardHead
</div>
</Header.LeftItem>
<Header.RightItem>
<span className="my-auto mb-0">
<span className="my-auto mb-0 hidden md:inline-flex">
<Button
variant="secondary"
size="md"
@@ -47,6 +48,15 @@ export const WorkspaceDashboardHeader = observer(function WorkspaceDashboardHead
label={t("home.manage_widgets")}
/>
</span>
<span className="my-auto mb-0 md:hidden">
<IconButton
variant="secondary"
size="md"
aria-label={t("home.manage_widgets")}
icon={<Shapes />}
onClick={() => toggleWidgetSettings(true)}
/>
</span>
</Header.RightItem>
</Header>
</>

View File

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

View File

@@ -60,15 +60,30 @@ export const CyclesListHeader = observer(function CyclesListHeader() {
{canUserCreateCycle && currentProjectDetails ? (
<Header.RightItem>
<CyclesViewHeader projectId={currentProjectDetails.id} />
<Button
variant="primary"
size="md"
stretch="auto"
label={t("project_cycles.add_cycle")}
onClick={() => {
toggleCreateCycleModal(true);
}}
/>
<>
<span className="block sm:hidden">
<Button
variant="primary"
size="md"
stretch="auto"
label={t("add")}
onClick={() => {
toggleCreateCycleModal(true);
}}
/>
</span>
<span className="hidden sm:block">
<Button
variant="primary"
size="md"
stretch="auto"
label={t("project_cycles.add_cycle")}
onClick={() => {
toggleCreateCycleModal(true);
}}
/>
</span>
</>
</Header.RightItem>
) : (
<></>

View File

@@ -65,15 +65,30 @@ export const ModulesListHeader = observer(function ModulesListHeader() {
<Header.RightItem>
<ModuleViewHeader />
{canUserCreateModule ? (
<Button
variant="primary"
size="md"
stretch="auto"
label={t("project_module.add_module")}
onClick={() => {
toggleCreateModuleModal(true);
}}
/>
<>
<span className="block sm:hidden">
<Button
variant="primary"
size="md"
stretch="auto"
label={t("add")}
onClick={() => {
toggleCreateModuleModal(true);
}}
/>
</span>
<span className="hidden sm:block">
<Button
variant="primary"
size="md"
stretch="auto"
label={t("project_module.add_module")}
onClick={() => {
toggleCreateModuleModal(true);
}}
/>
</span>
</>
) : (
<></>
)}

View File

@@ -99,7 +99,12 @@ const CreateWorkspacePage = observer(function CreateWorkspacePage() {
stretch="auto"
label={t("workspace_creation.errors.creation_disabled.request_button")}
nativeButton={false}
render={<a href={getMailtoHref()} />}
render={
<a
href={getMailtoHref()}
aria-label={t("workspace_creation.errors.creation_disabled.request_button")}
/>
}
/>
</div>
</div>

View File

@@ -11,6 +11,7 @@ import { Controller, useForm } from "react-hook-form";
// icons
import { CircleCheck } from "lucide-react";
// plane imports
import { AnchorButton } from "@makeplane/propel/components/anchor-button";
import { Button } from "@makeplane/propel/components/button";
import { Field } from "@makeplane/propel/components/field";
import { Input, InputGroup } from "@makeplane/propel/components/input";
@@ -133,10 +134,9 @@ export const ForgotPasswordForm = observer(function ForgotPasswordForm() {
disabled={!isValid}
loading={isSubmitting || resendTimerCode > 0}
/>
<Button
variant="ghost"
<AnchorButton
variant="primary"
size="md"
stretch="full"
label={t("auth.common.back_to_sign_in")}
nativeButton={false}
render={<Link href="/" />}

View File

@@ -98,7 +98,9 @@ export const WorkspaceActiveCyclesUpgrade = observer(function WorkspaceActiveCyc
label={t("upgrade")}
icon={<ProIcon className="h-3.5 w-3.5 text-on-color" />}
nativeButton={false}
render={<a href={MARKETING_PRICING_PAGE_LINK} target="_blank" rel="noreferrer" />}
render={
<a href={MARKETING_PRICING_PAGE_LINK} target="_blank" rel="noreferrer" aria-label={t("upgrade")} />
}
/>
</div>
<span className="absolute top-0 left-0">

View File

@@ -57,6 +57,7 @@ export function NewEmptyState({ title, description, image, primaryButton, disabl
onClick={primaryButton.onClick}
disabled={disabled}
label={primaryButton.text}
icon={primaryButton.icon}
/>
<div
onMouseEnter={handleMouseEnter}

View File

@@ -42,20 +42,20 @@ const sizeClasses = {
function CustomButton({
config,
variant,
size,
}: {
config: ButtonConfig;
variant: "primary" | "secondary";
size: EmptyStateSize;
}) {
const icon = config.prependIcon ?? config.appendIcon;
return (
<Button
variant="primary"
variant={variant}
size="sm"
stretch="auto"
label={config.text}
icon={config.appendIcon}
iconPosition="end"
icon={icon}
iconPosition={config.prependIcon ? "start" : "end"}
onClick={config.onClick}
disabled={config.disabled}
/>

View File

@@ -65,9 +65,21 @@ export function SingleExport({ service, refreshing }: Props) {
<>
{service.status == "completed" && (
<div>
<a target="_blank" href={service?.url} rel="noopener noreferrer">
<Button variant="primary" size="sm" stretch="full" label={isLoading ? "Downloading..." : "Download"} />
</a>
<Button
variant="primary"
size="sm"
stretch="full"
label={isLoading ? "Downloading..." : "Download"}
nativeButton={false}
render={
<a
target="_blank"
href={service?.url}
rel="noopener noreferrer"
aria-label={isLoading ? "Downloading..." : "Download"}
/>
}
/>
</div>
)}
</>

View File

@@ -63,7 +63,9 @@ export function ProductUpdatesFooter() {
label={t("powered_by_plane_pages")}
icon={<PlaneLogo className="h-4 w-auto text-primary" />}
nativeButton={false}
render={<a href="https://plane.so/pages" target="_blank" rel="noreferrer" />}
render={
<a href="https://plane.so/pages" target="_blank" rel="noreferrer" aria-label={t("powered_by_plane_pages")} />
}
/>
</div>
);

View File

@@ -369,15 +369,24 @@ export const InboxIssueActionsHeader = observer(function InboxIssueActionsHeader
icon={<LinkIcon className="h-2.5 w-2.5" />}
onClick={() => handleCopyIssueLink(workItemLink)}
/>
<ControlLink href={workItemLink} onClick={() => router.push(workItemLink)} target="_self">
<Button
variant="secondary"
size="md"
stretch="auto"
label={t("inbox_issue.actions.open")}
icon={<NewTabIcon className="h-2.5 w-2.5" />}
/>
</ControlLink>
<Button
variant="secondary"
size="md"
stretch="auto"
label={t("inbox_issue.actions.open")}
icon={<NewTabIcon className="h-2.5 w-2.5" />}
nativeButton={false}
render={
<ControlLink
href={workItemLink}
onClick={() => router.push(workItemLink)}
target="_self"
aria-label={t("inbox_issue.actions.open")}
>
{""}
</ControlLink>
}
/>
</div>
) : (
<>

View File

@@ -45,9 +45,16 @@ export function InstanceNotReady() {
</p>
</div>
</div>
<a href={GOD_MODE_URL} className="w-72">
<Button variant="primary" size="lg" stretch="full" label="Get started" />
</a>
<span className="w-72">
<Button
variant="primary"
size="lg"
stretch="full"
label="Get started"
nativeButton={false}
render={<a href={GOD_MODE_URL} aria-label="Get started" />}
/>
</span>
</div>
</div>
</div>

View File

@@ -29,7 +29,14 @@ export function BulkOperationsUpgradeBanner(props: Props) {
stretch="auto"
label="Upgrade to One"
nativeButton={false}
render={<a href={MARKETING_PLANE_ONE_PAGE_LINK} target="_blank" rel="noopener noreferrer" />}
render={
<a
href={MARKETING_PLANE_ONE_PAGE_LINK}
target="_blank"
rel="noopener noreferrer"
aria-label="Upgrade to One"
/>
}
/>
</span>
</div>

View File

@@ -11,6 +11,7 @@ import { usePopper } from "react-popper";
import { Popover, Transition } from "@headlessui/react";
// ui
import { Button } from "@makeplane/propel/components/button";
import { IconButton } from "@makeplane/propel/components/icon-button";
type Props = {
children: React.ReactNode;
@@ -46,7 +47,7 @@ export function FiltersDropdown(props: Props) {
return (
<Popover as="div">
{({ open }) => (
{() => (
<>
<Popover.Button as={React.Fragment}>
{menuButton ? (
@@ -70,14 +71,25 @@ export function FiltersDropdown(props: Props) {
)}
</div>
<div className="flex @4xl:hidden">
<Button
variant="secondary"
size="md"
stretch="auto"
label={typeof title === "string" ? title : "Filters"}
disabled={disabled}
tabIndex={tabIndex}
/>
{miniIcon ? (
<IconButton
variant="secondary"
size="md"
aria-label={typeof title === "string" ? title : "Filters"}
icon={miniIcon}
disabled={disabled}
tabIndex={tabIndex}
/>
) : (
<Button
variant="secondary"
size="md"
stretch="auto"
label={typeof title === "string" ? title : "Filters"}
disabled={disabled}
tabIndex={tabIndex}
/>
)}
</div>
</div>
)}

View File

@@ -78,7 +78,7 @@ export const TalkToSalesCard = observer(function TalkToSalesCard(props: TalkToSa
stretch="full"
label="Talk to Sales"
nativeButton={false}
render={<a href={href} target="_blank" rel="noreferrer" />}
render={<a href={href} target="_blank" rel="noreferrer" aria-label="Talk to Sales" />}
/>
</span>
{isTrialAllowed && !isSelfHosted && (

View File

@@ -112,7 +112,7 @@ export function Invitations(props: Props) {
<p className="mx-3 flex-shrink-0 text-center text-13 text-placeholder">or</p>
<hr className="w-full border-strong" />
</div>
<span className="w-full bg-surface-2 text-14">
<span className="flex w-full items-center bg-surface-2 text-14">
<Button
variant="ghost"
size="lg"

View File

@@ -146,7 +146,7 @@ export const RoleSetupStep = observer(function RoleSetupStep({ handleStepChange
{/* Action Buttons */}
<div className="space-y-3">
<Button variant="primary" size="lg" stretch="full" label="Continue" type="submit" disabled={isButtonDisabled} />
<span className="w-full text-tertiary">
<span className="flex w-full [&_button]:text-tertiary">
<Button variant="ghost" size="lg" stretch="full" label="Skip" onClick={handleSkip} />
</span>
</div>

View File

@@ -353,19 +353,17 @@ export const ProjectCard = observer(function ProjectCard(props: Props) {
))}
{!isMemberOfProject && (
<div className="flex items-center">
<span className="!p-0 font-semibold">
<Button
variant="ghost"
size="sm"
stretch="auto"
label="Join"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setJoinProjectModal(true);
}}
/>
</span>
<Button
variant="ghost"
size="sm"
stretch="auto"
label="Join"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setJoinProjectModal(true);
}}
/>
</div>
)}
</>

View File

@@ -10,7 +10,7 @@ import { useTranslation } from "@plane/i18n";
import { Button } from "@makeplane/propel/components/button";
import type { IWebhook } from "@plane/types";
// types
import { WebhookSecretKey } from "./form";
import { WebhookSecretKey } from "./form/secret-key";
type Props = {
handleClose: () => void;