Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/web/ce/components/issues/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export const IssuesHeader = observer(function IssuesHeader() {
)}
</Header.LeftItem>
<Header.RightItem>
<div className="hidden gap-3 md:flex">
<div className="hidden gap-2 md:flex">
<HeaderFilters
projectId={projectId}
currentProjectDetails={currentProjectDetails}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const TopNavigationRoot = observer(function TopNavigationRoot() {

return (
<div
className={cn("flex items-center min-h-11 w-full px-3.5 bg-canvas z-[27] transition-all duration-300", {
className={cn("flex items-center min-h-10 w-full px-3.5 bg-canvas z-[27] transition-all duration-300", {
"px-2": !showLabel,
})}
>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/core/components/common/breadcrumb-link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const IconWrapper = React.memo(function IconWrapper({ icon }: { icon: React.Reac
IconWrapper.displayName = "IconWrapper";

const LabelWrapper = React.memo(function LabelWrapper({ label }: { label: React.ReactNode }) {
return <div className="relative line-clamp-1 block max-w-[150px] overflow-hidden truncate">{label}</div>;
return <div className="relative line-clamp-1 block max-w-[150px] overflow-hidden truncate text-primary">{label}</div>;
});

LabelWrapper.displayName = "LabelWrapper";
Expand Down
2 changes: 1 addition & 1 deletion apps/web/core/components/home/home-dashboard-widgets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export const DashboardWidgets = observer(function DashboardWidgets() {
{!isWikiApp && <NoProjectsEmptyState />}

{isAnyWidgetEnabled ? (
<div className="flex flex-col divide-y-[1px] divide-subtle">
<div className="flex flex-col">
{orderedWidgets.map((key) => {
const WidgetComponent = HOME_WIDGETS_LIST[key]?.component;
const isEnabled = widgetsMap[key]?.is_enabled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { EmptyStateCompact } from "@plane/propel/empty-state";
export function LinksEmptyState() {
const { t } = useTranslation();
return (
<div className="flex items-center justify-center py-10 bg-layer-1 w-full">
<div className="flex items-center justify-center py-10 bg-layer-1 w-full rounded-lg">
<EmptyStateCompact
assetKey="link"
assetClassName="w-20 h-20"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import React from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { Check, Hotel, Users } from "lucide-react";
import { Check, Hotel } from "lucide-react";
// plane ui
import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants";
import { useLocalStorage } from "@plane/hooks";
import { useTranslation } from "@plane/i18n";
import { ProjectIcon, CloseIcon } from "@plane/propel/icons";
import { MembersPropertyIcon, ProjectIcon, CloseIcon } from "@plane/propel/icons";
import { cn, getFileURL } from "@plane/utils";
// helpers
// hooks
Expand Down Expand Up @@ -66,7 +66,7 @@ export const NoProjectsEmptyState = observer(function NoProjectsEmptyState() {
id: "invite-team",
title: "home.empty.invite_team.title",
description: "home.empty.invite_team.description",
icon: <Users className="size-4" />,
icon: <MembersPropertyIcon className="size-4" />,
flag: "visited_members",
cta: {
text: "home.empty.invite_team.cta",
Expand Down Expand Up @@ -103,7 +103,7 @@ export const NoProjectsEmptyState = observer(function NoProjectsEmptyState() {
</Link>
) : (
<Link href={`/${workspaceSlug}/profile/${currentUser?.id}`}>
<span className="relative flex size-4 items-center justify-center rounded-full bg-gray-700 p-4 capitalize text-on-color text-13">
<span className="relative flex size-4 items-center justify-center rounded-full bg-[#028375] p-4 capitalize text-on-color text-13">

Copilot AI Dec 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded color value instead of design token. The background color is using a hardcoded hex value "#028375" instead of a Tailwind CSS color class or design token. This is inconsistent with the PR's purpose of enhancing platform design tokens. Consider using a semantic color token like "bg-accent-primary" or another appropriate token from the design system.

Suggested change
<span className="relative flex size-4 items-center justify-center rounded-full bg-[#028375] p-4 capitalize text-on-color text-13">
<span className="relative flex size-4 items-center justify-center rounded-full bg-accent-primary p-4 capitalize text-on-color text-13">

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Replace hardcoded hex color with a design token.

Using bg-[#028375] directly contradicts the PR's goal of "platform design token enhancements." Hardcoded hex values reduce maintainability and theme consistency.

Consider defining this teal color as a semantic design token (e.g., bg-avatar-placeholder, bg-accent-teal) in your design system, then reference that token here.

🔎 Suggested approach

If a design token for this color exists, use it:

-<span className="relative flex size-4 items-center justify-center rounded-full bg-[#028375] p-4 capitalize text-on-color text-13">
+<span className="relative flex size-4 items-center justify-center rounded-full bg-avatar-placeholder p-4 capitalize text-on-color text-13">

If no token exists, add one to your design system configuration first, then reference it.

Committable suggestion skipped: line range outside the PR's diff.

{(currentUser?.email ?? currentUser?.display_name ?? "?")[0]}
</span>
</Link>
Expand Down Expand Up @@ -150,7 +150,7 @@ export const NoProjectsEmptyState = observer(function NoProjectsEmptyState() {
{EMPTY_STATE_DATA.map((item) => {
const isStateComplete = isComplete(item.flag);
return (
<div key={item.id} className="flex flex-col p-4 bg-surface-1 rounded-xl border border-subtle/40">
<div key={item.id} className="flex flex-col p-4 bg-layer-2 rounded-xl border border-subtle">
<div
className={cn("grid place-items-center bg-surface-2 rounded-full size-9 mb-3 text-placeholder", {
"text-accent-primary bg-accent-primary/10": !isStateComplete,
Expand Down Expand Up @@ -187,7 +187,7 @@ export const NoProjectsEmptyState = observer(function NoProjectsEmptyState() {
) : (
<button
type="button"
className="text-accent-primary hover:text-accent-secondary text-13 font-medium"
className="text-accent-primary hover:text-accent-secondary text-13 font-medium text-left"
onClick={item.cta.onClick}
>
{t(item.cta.text)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function RecentsEmptyState({ type }: { type: string }) {
const { assetKey, text } = getDisplayContent(type);

return (
<div className="flex items-center justify-center py-10 bg-layer-1 w-full">
<div className="flex items-center justify-center py-10 bg-layer-1 w-full rounded-lg">
<EmptyStateCompact assetKey={assetKey} assetClassName="size-20" title={t(text)} />
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { EmptyStateCompact } from "@plane/propel/empty-state";
export function StickiesEmptyState() {
const { t } = useTranslation();
return (
<div className="flex items-center justify-center py-10 bg-layer-1 w-full">
<div className="flex items-center justify-center py-10 bg-layer-1 w-full rounded-lg">
<EmptyStateCompact assetKey="note" assetClassName="size-20" title={t("stickies.empty_state.simple")} />
</div>
);
Expand Down
7 changes: 4 additions & 3 deletions apps/web/core/components/issues/layout-quick-actions.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
"use client";

import { observer } from "mobx-react";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { TContextMenuItem } from "@plane/ui";
import { CustomMenu } from "@plane/ui";
import { copyUrlToClipboard, cn } from "@plane/utils";
import { useLayoutMenuItems } from "@/components/common/quick-actions-helper";
import { Ellipsis, MoreHorizontal } from "lucide-react";

Copilot AI Dec 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import: MoreHorizontal is imported from lucide-react but never used in this file. Only Ellipsis is actually used for the IconButton. This should be removed to keep imports clean.

Suggested change
import { Ellipsis, MoreHorizontal } from "lucide-react";
import { Ellipsis } from "lucide-react";

Copilot uses AI. Check for mistakes.
import { IconButton } from "@plane/propel/icon-button";

type Props = {
workspaceSlug: string;
projectId: string;
storeType: "PROJECT" | "EPIC";
};

export const LayoutQuickActions: React.FC<Props> = observer((props) => {
export const LayoutQuickActions = observer(function LayoutQuickActions(props: Props) {
const { workspaceSlug, projectId, storeType } = props;

const layoutLink = `${workspaceSlug}/projects/${projectId}/${storeType === "EPIC" ? "epics" : "issues"}`;
Expand Down Expand Up @@ -49,6 +49,7 @@ export const LayoutQuickActions: React.FC<Props> = observer((props) => {
closeOnSelect
maxHeight="lg"
className="flex-shrink-0 flex items-center justify-center size-[26px] rounded"
customButton={<IconButton size="lg" variant="tertiary" icon={Ellipsis} />}
>
{MENU_ITEMS.map((item) => {
if (item.shouldRender === false) return null;
Expand Down
2 changes: 1 addition & 1 deletion apps/web/core/components/issues/peek-overview/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ export const IssuePeekOverviewHeader = observer(function IssuePeekOverviewHeader
</div>
<div className="flex items-center gap-x-4">
<NameDescriptionUpdateStatus isSubmitting={isSubmitting} />
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
{currentUser && !isArchived && (
<IssueSubscription workspaceSlug={workspaceSlug} projectId={projectId} issueId={issueId} />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export const WorkspaceDraftEmptyState = observer(function WorkspaceDraftEmptySta
title={t("workspace_empty_state.drafts.title")}
description={t("workspace_empty_state.drafts.description")}
assetKey="draft"
assetClassName="size-20"
actions={[
{
label: t("workspace_empty_state.drafts.cta_primary"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export const CustomizeNavigationDialog = observer(function CustomizeNavigationDi
<ModalCore isOpen={isOpen} handleClose={onClose} position={EModalPosition.CENTER} width={EModalWidth.XXL}>
<div className="flex flex-col max-h-[90vh] bg-surface-1 rounded-lg">
{/* Header */}
<div className="flex justify-between px-6 py-4">
<div className="flex justify-between px-6 pt-4">
<div>
<h2 className="text-18 font-semibold text-primary">{t("customize_navigation")}</h2>
<p className="mt-1 text-13 text-tertiary">
Expand Down Expand Up @@ -213,7 +213,7 @@ export const CustomizeNavigationDialog = observer(function CustomizeNavigationDi
/>
<div className="flex items-center gap-2 flex-1">
{getSidebarNavigationItemIcon(item.key)}
<label className="text-13 text-secondary flex-1 cursor-pointer">
<label className="text-13 text-primary flex-1 cursor-pointer">
{t(item.labelTranslationKey)}
</label>
</div>
Expand Down Expand Up @@ -244,7 +244,7 @@ export const CustomizeNavigationDialog = observer(function CustomizeNavigationDi
/>
<div className="flex items-center gap-2 flex-1">
{icon}
<span className="text-13 text-secondary">{t(item.labelTranslationKey)}</span>
<span className="text-13 text-primary">{t(item.labelTranslationKey)}</span>
</div>
</div>
);
Expand All @@ -271,8 +271,8 @@ export const CustomizeNavigationDialog = observer(function CustomizeNavigationDi
className="size-4 text-accent-primary focus:ring-accent-strong mt-1"
/>
<div className="flex-1">
<div className="text-13 text-secondary">{t("accordion_navigation_control")}</div>
<div className="text-11 text-tertiary">
<div className="text-13 text-primary">{t("accordion_navigation_control")}</div>
<div className="text-11 text-secondary">
Feature tabs will appear as nested items under project and acts as accordion.
</div>
</div>
Expand All @@ -288,29 +288,29 @@ export const CustomizeNavigationDialog = observer(function CustomizeNavigationDi
className="size-4 text-accent-primary focus:ring-accent-strong mt-1"
/>
<div className="flex-1">
<div className="text-13 text-secondary">{t("horizontal_navigation_bar")}</div>
<div className="text-11 text-tertiary">
<div className="text-13 text-primary">{t("horizontal_navigation_bar")}</div>
<div className="text-11 text-secondary">
Feature tabs will appear as horizontal tabs inside a project.
</div>
</div>
</label>
</div>

{/* Limited Projects Checkbox */}
<div className="space-y-2">
<div className="space-y-1">
<label className="flex items-center gap-2 px-2 py-1.5 rounded-md hover:bg-surface-2 cursor-pointer">
<Checkbox
checked={projectPreferences.showLimitedProjects}
onChange={(e) => updateShowLimitedProjects(e.target.checked)}
/>
<span className="text-13 text-secondary">{t("show_limited_projects_on_sidebar")}</span>
<span className="text-13 text-primary">{t("show_limited_projects_on_sidebar")}</span>
</label>

{projectPreferences.showLimitedProjects && (
<div className="pl-8">
<div className="flex flex-col gap-1 w-full">
<div className="flex flex-col gap-2 w-full">
<label className="text-11 text-tertiary w-full">{t("enter_number_of_projects")}</label>
<div className="flex flex-col gap-2 w-full pb-1.5">
<label className="text-11 text-secondary w-full">{t("enter_number_of_projects")}</label>
<input
type="number"
min="1"
Expand Down
2 changes: 1 addition & 1 deletion apps/web/core/components/sidebar/sidebar-navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function SidebarNavItem(props: TSidebarNavItem) {
className={cn(
"cursor-pointer relative group w-full flex items-center justify-between gap-1.5 rounded-md px-2 py-1 outline-none",
{
"text-secondary !bg-layer-transparent-active": isActive,
"text-primary !bg-layer-transparent-active": isActive,
"text-secondary hover:bg-layer-transparent-hover active:bg-layer-transparent-active": !isActive,
},
className
Expand Down
11 changes: 6 additions & 5 deletions apps/web/core/components/sidebar/sidebar-toggle-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@ import { PanelLeft } from "lucide-react";
// hooks
import { useAppTheme } from "@/hooks/store/use-app-theme";
import { isSidebarToggleVisible } from "@/plane-web/components/desktop";
import { IconButton } from "@plane/propel/icon-button";

export const AppSidebarToggleButton = observer(function AppSidebarToggleButton() {
// store hooks
const { toggleSidebar, sidebarPeek, toggleSidebarPeek } = useAppTheme();

if (!isSidebarToggleVisible()) return null;
return (
<button
className="flex items-center justify-center size-6 rounded-md text-secondary hover:text-accent-primary hover:bg-surface-2"
<IconButton
size="base"
variant="ghost"
icon={PanelLeft}
onClick={() => {
if (sidebarPeek) toggleSidebarPeek(false);
toggleSidebar();
}}
>
<PanelLeft className="size-4" />
</button>
/>
);
});
12 changes: 6 additions & 6 deletions apps/web/core/components/sidebar/sidebar-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import useSize from "@/hooks/use-window-size";
// plane web components
import { WorkspaceEditionBadge } from "@/plane-web/components/workspace/edition-badge";
import { AppSidebarToggleButton } from "./sidebar-toggle-button";
import { IconButton } from "@plane/propel/icon-button";

type TSidebarWrapperProps = {
title: string;
Expand Down Expand Up @@ -51,13 +52,12 @@ export const SidebarWrapper = observer(function SidebarWrapper(props: TSidebarWr
<span className="text-16 text-primary font-medium pt-1">{title}</span>
{title === "Projects" && (
<div className="flex items-center gap-2">
<button
type="button"
className="flex items-center justify-center size-6 rounded-md text-secondary hover:text-accent-primary hover:bg-surface-2"
<IconButton
size="base"
variant="ghost"
icon={PreferencesIcon}
onClick={() => setIsCustomizeNavDialogOpen(true)}
>
<PreferencesIcon className="size-4" />
</button>
/>
<AppSidebarToggleButton />
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { PopoverMenu } from "@plane/ui";
import { usePlatformOS } from "@/hooks/use-platform-os";
// local imports
import { NotificationFilterOptionItem } from "./menu-option-item";
import { IconButton } from "@plane/propel/icon-button";

export const NotificationFilter = observer(function NotificationFilter() {
// hooks
Expand All @@ -26,9 +27,7 @@ export const NotificationFilter = observer(function NotificationFilter() {
data={translatedFilterTypeOptions}
button={
<Tooltip tooltipContent={t("notification.options.filters")} isMobile={isMobile} position="bottom">
<div className="flex-shrink-0 w-5 h-5 flex justify-center items-center overflow-hidden cursor-pointer transition-all hover:bg-layer-1 rounded-xs outline-none">
<ListFilter className="h-3 w-3" />
</div>
<IconButton size="base" variant="ghost" icon={ListFilter} />
</Tooltip>
}
keyExtractor={(item: { label: string; value: ENotificationFilterType }) => item.value}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ReactNode } from "react";
import { observer } from "mobx-react";
import { Check, CheckCircle, Clock } from "lucide-react";
import { Check, CheckCircle, Clock, MoreVertical } from "lucide-react";
// plane imports
import { useTranslation } from "@plane/i18n";
import { ArchiveIcon } from "@plane/propel/icons";
Expand All @@ -10,6 +10,7 @@ import { PopoverMenu } from "@plane/ui";
import { useWorkspaceNotifications } from "@/hooks/store/notifications";
// local imports
import { NotificationMenuOptionItem } from "./menu-item";
import { IconButton } from "@plane/propel/icon-button";

export type TPopoverMenuOptions = {
key: string;
Expand Down Expand Up @@ -72,7 +73,7 @@ export const NotificationHeaderMenuOption = observer(function NotificationHeader
return (
<PopoverMenu
data={popoverMenuOptions}
buttonClassName="flex-shrink-0 w-5 h-5 flex justify-center items-center overflow-hidden cursor-pointer transition-all hover:bg-layer-1 bg-surface-1 rounded-xs outline-none"
button={<IconButton size="base" variant="ghost" icon={MoreVertical} />}
keyExtractor={(item: TPopoverMenuOptions) => item.key}
panelClassName="p-0 py-2 rounded-md border border-subtle bg-surface-1 space-y-1"
render={(item: TPopoverMenuOptions) => <NotificationMenuOptionItem {...item} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
// local imports
import { NotificationFilter } from "../../filters/menu";
import { NotificationHeaderMenuOption } from "./menu-option";
import { IconButton } from "@plane/propel/icon-button";

type TNotificationSidebarHeaderOptions = {
workspaceSlug: string;
Expand Down Expand Up @@ -55,32 +56,29 @@ export const NotificationSidebarHeaderOptions = observer(function NotificationSi
<div className="relative flex justify-center items-center gap-2 text-body-xs-medium">
{/* mark all notifications as read*/}
<Tooltip tooltipContent={t("notification.options.mark_all_as_read")} isMobile={isMobile} position="bottom">
<div
className="flex-shrink-0 w-5 h-5 flex justify-center items-center overflow-hidden cursor-pointer transition-all hover:bg-layer-1 rounded-xs"
<IconButton
size="base"
variant="ghost"
data-ph-element={NOTIFICATION_TRACKER_ELEMENTS.MARK_ALL_AS_READ_BUTTON}
icon={loader === ENotificationLoader.MARK_ALL_AS_READY ? Spinner : CheckCheck}
onClick={() => {
captureSuccess({
eventName: NOTIFICATION_TRACKER_EVENTS.all_marked_read,
});
handleMarkAllNotificationsAsRead();
}}
>
{loader === ENotificationLoader.MARK_ALL_AS_READY ? (
<Spinner height="14px" width="14px" />
) : (
<CheckCheck className="h-3 w-3" />
)}
</div>
/>
</Tooltip>

{/* refetch current notifications */}
<Tooltip tooltipContent={t("notification.options.refresh")} isMobile={isMobile} position="bottom">
<div
className="flex-shrink-0 w-5 h-5 flex justify-center items-center overflow-hidden cursor-pointer transition-all hover:bg-layer-1 rounded-xs"
<IconButton
size="base"
variant="ghost"
icon={RefreshCw}
className={loader === ENotificationLoader.MUTATION_LOADER ? "animate-spin" : ""}
onClick={refreshNotifications}
>
<RefreshCw className={`h-3 w-3 ${loader === ENotificationLoader.MUTATION_LOADER ? "animate-spin" : ""}`} />
</div>
/>
</Tooltip>

{/* notification filters */}
Expand Down
Loading
Loading