[WEB-5602] feat: new design system (#8220)

* chore: init tailwind v4

* chore: update all configs

* chore: add source to parse monorepo packages

* chore: combine all css files

* feat: added extended colors

* chore: update typography

* chore: update extended color var names

* refactor: remove initial spacing variable and update dark mode selector

* chore: update css files

* chore: update animations

* chore: remove spacing tokens

* fix: external css files

* chore: update tailwind-merge version

* chore: update font family

* chore: added brief agents.md and story for new design system

* chore: enhance design system documentation with rare exceptions for visual separation

* chore: add fontsource package for typography

* chore: material symbols font added

* chore: update shadow default

* chore: add stroke and outline theme vars

* chore: update ring and fill colors

* chore: overwrite tailwind typography tokens

* chore: add high contrast mode tokens

* chore: update scrollbar colors

* chore: backward compatibility for buttons and placeholders

* chore: add priority colors

* chore: update urgent priority color

* chore: update plan colors

* chore: add missing utility class

* chore: update height and padding classes

* chore: update label colors

* chore: add missing utlity

* chore: add typography plugin to space app

* chore: replace existing classNames with new design system tokens #8244 (#8278)

* chore: update border colors

* chore: update all borders

* chore: update text colors

* chore: update css variables

* chore: update font sizes and weights

* chore: update bg colors

* chore: sync changes

* fix: uncomment spacing-1200 variable in variables.css

* chore: update primary colors

* refactor: updated border to border-subtle

* refactor: update various components and improve UI consistency across the application

* updated classnames

* updated classnames

* refactor: update color-related class names to use new design system variables for consistency

* chore: default automations

* chore: update text sizes

* chore: home and power k

* chore: home and power k

* chore: replace ui package button components

* chore: update text sizes

* chore: updated issue identifier (#8275)

* refactor: top navigation and sidebar design token (#8276)

* chore: update all button components (#8277)

* chore: new button component

* chore: update existing buttons

* chore: overwrite tailwind typography tokens

* fix: twMerge config + fixed cn instances

* refactor: toast design token updated (#8279)

* chore: update existing buttons

* chore: tooltip design token updatged (#8280)

* chore: moved cn utility to propel (#8281)

* chore: update space app UI (#8285)

* chore; update space app filters component

* fix: button whitespace wrap

* chore: space app votes

* chore: update dropdown components

* refactor: auth, onboarding, sidebar, and common component design token migration (#8291)

* chore: checkbox component design token updated

* chore: indicator and oauth component design token updated

* chore: sidebar design token updated

* chore: auth and onboarding design token updated

* chore: update divider color

* style: update background colors and hover effects across list components

* fix: tailwind merge

* refactor: toggle switch design token migration and header utility classname added (#8295)

* chore: toggle component design token updated

* chore: h-header utility class added

* chore: updated color tokens for work item detail page (#8296)

* chore: update react-day-picker UI

* refactor: update button sizes and styles in filters components

* refactor: breadcrumbs design token updated (#8297)

* chore: update priority icon colors

* refactor: updated layout variables

* chore: update plan card primary CTA

* Chore update editor design system (#8299)

* refactor: update styles for callout, color selector, logo selector, and image uploader

* refactor:fix image

* chore: update settings UI

* chore: updated notifications color and size tokens (#8302)

* chore: update sm button border radius

* fix: logo renderer

* chore: icon button component

* chore: remove deprecated classes

* chore: remove deprecated classes

* chore: update editor list spacing

* fix: icon button size

* chore: improvements (#8309)

* chore: update cycles and modules pages

* refactor: update background styles across various components to use new design system colors

* fix: button type errors

* chore: update modals design system (#8310)

* refactor: callout bg

* refactor: code  bg

* refactor: modal size and variant

---------

Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>

* chore: update next-themes

* design: update billing and plans component styles and remove unused utility functions (#8313)

* refactor: empty state design token migration and improvements (#8315)

* fix: profile page

* refactor: tabs design token updated (#8316)

* chore: updated buttons and tokens for work items (#8317)

* fix: adjust trial button spacing in checkout modal

* chore: update add button hover state

* fix: type error (#8318)

* fix: type error

* chore: code refactor

* refactor: update button sizes and background styles in rich filters components

* refactor: update editor bg

* refactor: enhance Gantt chart sidebar functionality and styling

- Removed unused  prop from .
- Updated  to include new props for better block management and scrolling behavior.
- Improved auto-scroll functionality for Gantt chart items.
- Adjusted styles in  component for consistent design.

* regression: gantt design

* chore: new badge component

* fix: favorite star

* chore: update backgroung, typography and button sizes across workspace settings general and members pages

* fix: header button sizes

* fix: emoji icon logo (#8323)

* more fixes

* chore: update settings sidebar

* refactor: avatar component

* chore: updated work item detail sidebar (#8327)

* refactor: update link preview

* fix: work item property dropdowns

* fix: dropdown buttons border radius

* chore: update power k translation

* chore: updated profile activity design (#8328)

* chore: update settings pages

* chore: update work item sidebar alignments (#8330)

* refactor: admin design system

* chore: update page header

---------

Co-authored-by: Jayash Tripathy <76092296+JayashTripathy@users.noreply.github.com>
Co-authored-by: VipinDevelops <vipinchaudhary1809@gmail.com>
Co-authored-by: Vamsi Krishna <46787868+vamsikrishnamathala@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Co-authored-by: gakshita <akshitagoyal1516@gmail.com>
Co-authored-by: Palanikannan M <akashmalinimurugu@gmail.com>
Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
Co-authored-by: b-saikrishnakanth <bsaikrishnakanth97@gmail.com>
Co-authored-by: M. Palanikannan <73993394+Palanikannan1437@users.noreply.github.com>

* fix: formatting

* reexport types

* fix: lint error

---------

Co-authored-by: Jayash Tripathy <76092296+JayashTripathy@users.noreply.github.com>
Co-authored-by: VipinDevelops <vipinchaudhary1809@gmail.com>
Co-authored-by: Vamsi Krishna <46787868+vamsikrishnamathala@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Co-authored-by: gakshita <akshitagoyal1516@gmail.com>
Co-authored-by: Palanikannan M <akashmalinimurugu@gmail.com>
Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
Co-authored-by: b-saikrishnakanth <bsaikrishnakanth97@gmail.com>
Co-authored-by: M. Palanikannan <73993394+Palanikannan1437@users.noreply.github.com>
This commit is contained in:
Aaryan Khandelwal 2025-12-12 20:50:14 +05:30 committed by GitHub
parent d86418aad8
commit 22339b9786
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
1342 changed files with 14227 additions and 15119 deletions

View file

@ -80,17 +80,17 @@ export const WorkspaceActiveCyclesUpgrade = observer(function WorkspaceActiveCyc
>
<div className="relative flex flex-col justify-center gap-7 px-14 lg:w-1/2">
<div className="flex max-w-64 flex-col gap-2">
<h2 className="text-2xl font-semibold">{t("on_demand_snapshots_of_all_your_cycles")}</h2>
<p className="text-base font-medium text-custom-text-300">{t("active_cycles_description")}</p>
<h2 className="text-20 font-semibold">{t("on_demand_snapshots_of_all_your_cycles")}</h2>
<p className="text-14 font-medium text-tertiary">{t("active_cycles_description")}</p>
</div>
<div className="flex items-center gap-3">
<a
className={`${getButtonStyling("primary", "md")} cursor-pointer`}
className={`${getButtonStyling("primary", "base")} cursor-pointer`}
href={MARKETING_PRICING_PAGE_LINK}
target="_blank"
rel="noreferrer"
>
<ProIcon className="h-3.5 w-3.5 text-white" />
<ProIcon className="h-3.5 w-3.5 text-on-color" />
{t("upgrade")}
</a>
</div>
@ -113,12 +113,12 @@ export const WorkspaceActiveCyclesUpgrade = observer(function WorkspaceActiveCyc
</div>
<div className="grid h-full grid-cols-1 gap-5 pb-8 lg:grid-cols-2 xl:grid-cols-3">
{WORKSPACE_ACTIVE_CYCLES_DETAILS.map((item) => (
<div key={item.title} className="flex min-h-32 w-full flex-col gap-2 rounded-md bg-custom-background-80 p-4">
<div key={item.title} className="flex min-h-32 w-full flex-col gap-2 rounded-md bg-layer-1 p-4">
<div className="flex gap-2 justify-between">
<h3 className="font-medium">{t(item.key)}</h3>
<item.icon className="mt-1 h-4 w-4 text-blue-500" />
</div>
<span className="text-sm text-custom-text-300">{t(`${item.key}_description`)}</span>
<span className="text-13 text-tertiary">{t(`${item.key}_description`)}</span>
</div>
))}
</div>

View file

@ -26,7 +26,7 @@ export const commandGroups: TCommandGroups = {
icon: <CycleIcon className="h-3 w-3" />,
itemName: (cycle: IWorkspaceDefaultSearchResult) => (
<h6>
<span className="text-xs text-custom-text-300">{cycle.project__identifier}</span> {cycle.name}
<span className="text-11 text-tertiary">{cycle.project__identifier}</span> {cycle.name}
</h6>
),
path: (cycle: IWorkspaceDefaultSearchResult) =>
@ -42,7 +42,7 @@ export const commandGroups: TCommandGroups = {
issueTypeId={issue.type_id}
projectIdentifier={issue.project__identifier}
issueSequenceId={issue.sequence_id}
textContainerClassName="text-xs"
size="xs"
/>{" "}
{issue.name}
</div>
@ -61,7 +61,7 @@ export const commandGroups: TCommandGroups = {
icon: <ViewsIcon className="h-3 w-3" />,
itemName: (view: IWorkspaceDefaultSearchResult) => (
<h6>
<span className="text-xs text-custom-text-300">{view.project__identifier}</span> {view.name}
<span className="text-11 text-tertiary">{view.project__identifier}</span> {view.name}
</h6>
),
path: (view: IWorkspaceDefaultSearchResult) =>
@ -72,7 +72,7 @@ export const commandGroups: TCommandGroups = {
icon: <ModuleIcon className="h-3 w-3" />,
itemName: (module: IWorkspaceDefaultSearchResult) => (
<h6>
<span className="text-xs text-custom-text-300">{module.project__identifier}</span> {module.name}
<span className="text-11 text-tertiary">{module.project__identifier}</span> {module.name}
</h6>
),
path: (module: IWorkspaceDefaultSearchResult) =>
@ -83,7 +83,7 @@ export const commandGroups: TCommandGroups = {
icon: <PageIcon className="h-3 w-3" />,
itemName: (page: IWorkspacePageSearchResult) => (
<h6>
<span className="text-xs text-custom-text-300">{page.project__identifiers?.[0]}</span> {page.name}
<span className="text-11 text-tertiary">{page.project__identifiers?.[0]}</span> {page.name}
</h6>
),
path: (page: IWorkspacePageSearchResult, projectId: string | undefined) => {

View file

@ -26,7 +26,7 @@ export function PowerKModalNoSearchResultsCommand(props: TPowerKModalNoSearchRes
label={
<p className="flex items-center gap-2">
{t("power_k.search_menu.no_results")}{" "}
<span className="shrink-0 text-sm text-custom-text-300">{t("power_k.search_menu.clear_search")}</span>
<span className="shrink-0 text-13 text-tertiary">{t("power_k.search_menu.clear_search")}</span>
</p>
}
onSelect={() => updateSearchTerm("")}

View file

@ -41,7 +41,7 @@ export const CommentBlock = observer(function CommentBlock(props: TCommentBlock)
ref={commentBlockRef}
>
<div
className="absolute left-[13px] top-0 bottom-0 w-0.5 transition-border duration-1000 bg-custom-background-80"
className="absolute left-[13px] top-0 bottom-0 w-0.5 transition-border duration-1000 bg-layer-1"
aria-hidden
/>
<div
@ -55,15 +55,15 @@ export const CommentBlock = observer(function CommentBlock(props: TCommentBlock)
<div className="flex w-full gap-2">
<div className="flex-1 flex flex-wrap items-center gap-1">
<div className="flex items-center gap-1">
<span className="text-xs font-medium">{displayName}</span>
<span className="text-11 font-medium">{displayName}</span>
</div>
<div className="text-xs text-custom-text-300">
<div className="text-11 text-tertiary">
commented{" "}
<Tooltip
tooltipContent={`${renderFormattedDate(comment.created_at)} at ${renderFormattedTime(comment.created_at)}`}
position="bottom"
>
<span className="text-custom-text-350">
<span className="text-tertiary">
{calculateTimeAgo(comment.created_at)}
{comment.edited_at && ` (${t("edited")})`}
</span>
@ -72,7 +72,7 @@ export const CommentBlock = observer(function CommentBlock(props: TCommentBlock)
</div>
<div className="flex-shrink-0 ">{quickActions}</div>
</div>
<div className="text-base mb-2">{children}</div>
<div className="text-14 mb-2">{children}</div>
</div>
</div>
);

View file

@ -59,7 +59,7 @@ const ActiveCyclesComponent = observer(function ActiveCyclesComponent({
}
return (
<div className="flex flex-col border-b border-custom-border-200">
<div className="flex flex-col border-b border-subtle">
<CyclesListItem
key={cycleId}
cycleId={cycleId}
@ -67,8 +67,8 @@ const ActiveCyclesComponent = observer(function ActiveCyclesComponent({
projectId={projectId}
className="!border-b-transparent"
/>
<Row className="bg-custom-background-100 pt-3 pb-6">
<div className="grid grid-cols-1 bg-custom-background-100 gap-3 lg:grid-cols-2 xl:grid-cols-3">
<Row className="bg-surface-1 pt-3 pb-6">
<div className="grid grid-cols-1 bg-surface-1 gap-3 lg:grid-cols-2 xl:grid-cols-3">
<ActiveCycleProgress
handleFiltersUpdate={handleFiltersUpdate}
projectId={projectId}
@ -114,7 +114,7 @@ export const ActiveCycleRoot = observer(function ActiveCycleRoot(props: IActiveC
<Disclosure as="div" className="flex flex-shrink-0 flex-col" defaultOpen>
{({ open }) => (
<>
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 cursor-pointer">
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-subtle bg-layer-2 cursor-pointer">
<CycleListGroupHeader title={t("project_cycles.active_cycle.label")} type="current" isExpanded={open} />
</Disclosure.Button>
<Disclosure.Panel>

View file

@ -18,7 +18,7 @@ export const EstimateListItemButtons = observer(function EstimateListItemButtons
return (
<div className="relative flex items-center gap-1">
<button
className="relative flex-shrink-0 w-6 h-6 flex justify-center items-center rounded cursor-pointer transition-colors overflow-hidden hover:bg-custom-background-80"
className="relative flex-shrink-0 w-6 h-6 flex justify-center items-center rounded-sm cursor-pointer transition-colors overflow-hidden hover:bg-layer-1"
onClick={() => onDeleteClick && onDeleteClick(estimateId)}
data-ph-element={PROJECT_SETTINGS_TRACKER_ELEMENTS.ESTIMATES_LIST_ITEM}
>

View file

@ -1,4 +1,3 @@
import type { FC } from "react";
// components
import type { IBlockUpdateData, IGanttBlock } from "@plane/types";
import RenderIfVisible from "@/components/core/render-if-visible-HOC";

View file

@ -9,10 +9,10 @@ export const ProductUpdatesHeader = observer(function ProductUpdatesHeader() {
return (
<div className="flex gap-2 mx-6 my-4 items-center justify-between flex-shrink-0">
<div className="flex w-full items-center">
<div className="flex gap-2 text-xl font-medium">{t("whats_new")}</div>
<div className="flex gap-2 text-18 font-medium">{t("whats_new")}</div>
<div
className={cn(
"px-2 mx-2 py-0.5 text-center text-xs font-medium rounded-full bg-custom-primary-100/20 text-custom-primary-100"
"px-2 mx-2 py-0.5 text-center text-11 font-medium rounded-full bg-accent-primary/20 text-accent-primary"
)}
>
{t("version")}: v{packageJson.version}

View file

@ -10,10 +10,10 @@ export function MaintenanceMessage() {
return (
<>
<div className="flex flex-col gap-2.5">
<h1 className="text-xl font-semibold text-custom-text-100 text-left">
<h1 className="text-18 font-semibold text-primary text-left">
&#x1F6A7; Looks like Plane didn&apos;t start up correctly!
</h1>
<span className="text-base font-medium text-custom-text-200 text-left">
<span className="text-14 font-medium text-secondary text-left">
Some services might have failed to start. Please check your container logs to identify and resolve the issue.
If you&apos;re stuck, reach out to our support team for more help.
</span>
@ -25,7 +25,7 @@ export function MaintenanceMessage() {
href={link.value}
target="_blank"
rel="noopener noreferrer"
className="text-custom-primary-100 hover:underline text-sm"
className="text-accent-primary hover:underline text-13"
>
{link.label}
</a>

View file

@ -69,7 +69,7 @@ export const IssuesHeader = observer(function IssuesHeader() {
<BreadcrumbLink
label="Work Items"
href={`/${workspaceSlug}/projects/${projectId}/issues/`}
icon={<WorkItemsIcon className="h-4 w-4 text-custom-text-300" />}
icon={<WorkItemsIcon className="h-4 w-4 text-tertiary" />}
isLast
/>
}
@ -89,7 +89,7 @@ export const IssuesHeader = observer(function IssuesHeader() {
{currentProjectDetails?.anchor ? (
<a
href={publishedURL}
className="group flex items-center gap-1.5 rounded bg-custom-primary-100/10 px-2.5 py-1 text-xs font-medium text-custom-primary-100"
className="group flex items-center gap-1.5 rounded-sm bg-accent-primary/10 px-2.5 py-1 text-11 font-medium text-accent-primary"
target="_blank"
rel="noopener noreferrer"
>
@ -110,19 +110,18 @@ export const IssuesHeader = observer(function IssuesHeader() {
canUserCreateIssue={canUserCreateIssue}
/>
</div>
{canUserCreateIssue ? (
{canUserCreateIssue && (
<Button
variant="primary"
size="lg"
onClick={() => {
toggleCreateIssueModal(true, EIssuesStoreType.PROJECT);
}}
data-ph-element={WORK_ITEM_TRACKER_ELEMENTS.HEADER_ADD_BUTTON.WORK_ITEMS}
size="sm"
>
<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>

View file

@ -22,11 +22,11 @@ export function IssueCreatorDisplay(props: TIssueUser) {
return (
<>
{customUserName ? (
<span className="text-custom-text-100 font-medium">{customUserName || "Plane"}</span>
<span className="text-primary font-medium">{customUserName || "Plane"}</span>
) : (
<Link
href={`/${activity?.workspace_detail?.slug}/profile/${activity?.actor_detail?.id}`}
className="hover:underline text-custom-text-100 font-medium"
className="hover:underline text-primary font-medium"
>
{activity.actor_detail?.display_name}
</Link>

View file

@ -1,85 +1,13 @@
import type { FC } from "react";
import { observer } from "mobx-react";
// types
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { Tooltip } from "@plane/propel/tooltip";
import type { IIssueDisplayProperties } from "@plane/types";
// ui
// helpers
import { cn } from "@plane/utils";
// plane imports
import type { TIssueIdentifierProps, TIssueTypeIdentifier } from "@plane/types";
// hooks
import { useIssueDetail } from "@/hooks/store/use-issue-detail";
import { useProject } from "@/hooks/store/use-project";
type TIssueIdentifierBaseProps = {
projectId: string;
size?: "xs" | "sm" | "md" | "lg";
textContainerClassName?: string;
displayProperties?: IIssueDisplayProperties | undefined;
enableClickToCopyIdentifier?: boolean;
};
type TIssueIdentifierFromStore = TIssueIdentifierBaseProps & {
issueId: string;
};
type TIssueIdentifierWithDetails = TIssueIdentifierBaseProps & {
issueTypeId?: string | null;
projectIdentifier: string;
issueSequenceId: string | number;
};
export type TIssueIdentifierProps = TIssueIdentifierFromStore | TIssueIdentifierWithDetails;
type TIssueTypeIdentifier = {
issueTypeId: string;
size?: "xs" | "sm" | "md" | "lg";
};
export const IssueTypeIdentifier = observer(function IssueTypeIdentifier(_props: TIssueTypeIdentifier) {
return <></>;
});
type TIdentifierTextProps = {
identifier: string;
enableClickToCopyIdentifier?: boolean;
textContainerClassName?: string;
};
export function IdentifierText(props: TIdentifierTextProps) {
const { identifier, enableClickToCopyIdentifier = false, textContainerClassName } = props;
// handlers
const handleCopyIssueIdentifier = () => {
if (enableClickToCopyIdentifier) {
navigator.clipboard.writeText(identifier).then(() => {
setToast({
type: TOAST_TYPE.SUCCESS,
title: "Work item ID copied to clipboard",
});
});
}
};
return (
<Tooltip tooltipContent="Click to copy" disabled={!enableClickToCopyIdentifier} position="top">
<span
className={cn(
"text-base font-medium text-custom-text-300",
{
"cursor-pointer": enableClickToCopyIdentifier,
},
textContainerClassName
)}
onClick={handleCopyIssueIdentifier}
>
{identifier}
</span>
</Tooltip>
);
}
import { IdentifierText } from "@/components/issues/issue-detail/identifier-text";
export const IssueIdentifier = observer(function IssueIdentifier(props: TIssueIdentifierProps) {
const { projectId, textContainerClassName, displayProperties, enableClickToCopyIdentifier = false } = props;
const { projectId, variant, size, displayProperties, enableClickToCopyIdentifier = false } = props;
// store hooks
const { getProjectIdentifierById } = useProject();
const {
@ -100,8 +28,13 @@ export const IssueIdentifier = observer(function IssueIdentifier(props: TIssueId
<IdentifierText
identifier={`${projectIdentifier}-${issueSequenceId}`}
enableClickToCopyIdentifier={enableClickToCopyIdentifier}
textContainerClassName={textContainerClassName}
variant={variant}
size={size}
/>
</div>
);
});
export const IssueTypeIdentifier = observer(function IssueTypeIdentifier(_props: TIssueTypeIdentifier) {
return <></>;
});

View file

@ -1,4 +1,3 @@
import type { FC } from "react";
import { observer } from "mobx-react";
// plane imports
import {
@ -19,7 +18,7 @@ import type { TCheckoutParams } from "@/components/license/modal/card/checkout-b
// Constants
const COMMON_CARD_CLASSNAME = "flex flex-col w-full h-full justify-end col-span-12 sm:col-span-6 xl:col-span-3";
const COMMON_EXTRA_FEATURES_CLASSNAME = "pt-2 text-center text-xs text-custom-primary-200 font-medium hover:underline";
const COMMON_EXTRA_FEATURES_CLASSNAME = "pt-2 text-center text-caption-md-medium text-accent-primary hover:underline";
export type PaidPlanUpgradeModalProps = {
isOpen: boolean;
@ -48,9 +47,9 @@ export const PaidPlanUpgradeModal = observer(function PaidPlanUpgradeModal(props
<div className="grid grid-cols-12 gap-6 h-full">
{/* Free Plan Section */}
<div className={cn(COMMON_CARD_CLASSNAME)}>
<div className="text-3xl font-bold leading-8 flex">Upgrade to a paid plan and unlock missing features.</div>
<div className="text-24 font-bold leading-8 flex">Upgrade to a paid plan and unlock missing features.</div>
<div className="mt-4 mb-2">
<p className="text-sm mb-4 pr-8 text-custom-text-100">
<p className="text-13 mb-4 pr-8 text-primary">
Dashboards, Workflows, Approvals, Time Management, and other superpowers are just a click away. Upgrade
today to unlock features your teams need yesterday.
</p>

View file

@ -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 z-[27] transition-all duration-300", {
className={cn("flex items-center min-h-11 w-full px-3.5 bg-canvas z-[27] transition-all duration-300", {
"px-2": !showLabel,
})}
>
@ -73,7 +73,7 @@ export const TopNavigationRoot = observer(function TopNavigationRoot() {
</Tooltip>
<HelpMenuRoot />
<StarUsOnGitHubLink />
<div className="flex items-center justify-center size-8 hover:bg-custom-background-80 rounded-md">
<div className="flex items-center justify-center size-8 hover:bg-layer-1-hover rounded-md">
<UserMenuRoot size="xs" />
</div>
</div>

View file

@ -89,16 +89,16 @@ export const TourRoot = observer(function TourRoot(props: TOnboardingTourProps)
return (
<>
{step === "welcome" ? (
<div className="w-4/5 overflow-hidden rounded-[10px] bg-custom-background-100 md:w-1/2 lg:w-2/5">
<div className="w-4/5 overflow-hidden rounded-[10px] bg-surface-1 md:w-1/2 lg:w-2/5">
<div className="h-full overflow-hidden">
<div className="grid h-64 place-items-center bg-custom-primary-100">
<PlaneLockup className="h-10 w-auto text-white" />
<div className="grid h-64 place-items-center bg-accent-primary">
<PlaneLockup className="h-10 w-auto text-on-color" />
</div>
<div className="flex flex-col overflow-y-auto p-6">
<h3 className="font-semibold sm:text-xl">
<h3 className="font-semibold sm:text-18">
Welcome to Plane, {currentUser?.first_name} {currentUser?.last_name}
</h3>
<p className="mt-3 text-sm text-custom-text-200">
<p className="mt-3 text-13 text-secondary">
We{"'"}re glad that you decided to try out Plane. You can now manage your projects with ease. Get
started by creating a project.
</p>
@ -117,7 +117,7 @@ export const TourRoot = observer(function TourRoot(props: TOnboardingTourProps)
</Button>
<button
type="button"
className="bg-transparent text-xs font-medium text-custom-primary-100 outline-custom-text-100"
className="bg-transparent text-11 font-medium text-accent-primary outline-custom-text-100"
onClick={() => {
captureClick({
elementName: PRODUCT_TOUR_TRACKER_ELEMENTS.SKIP_BUTTON,
@ -133,30 +133,30 @@ export const TourRoot = observer(function TourRoot(props: TOnboardingTourProps)
</div>
</div>
) : (
<div className="relative grid h-3/5 w-4/5 grid-cols-10 overflow-hidden rounded-[10px] bg-custom-background-100 sm:h-3/4 md:w-1/2 lg:w-3/5">
<div className="relative grid h-3/5 w-4/5 grid-cols-10 overflow-hidden rounded-[10px] bg-surface-1 sm:h-3/4 md:w-1/2 lg:w-3/5">
<button
type="button"
className="fixed right-[9%] top-[19%] z-10 -translate-y-1/2 translate-x-1/2 cursor-pointer rounded-full border border-custom-text-100 p-1 sm:top-[11.5%] md:right-[24%] lg:right-[19%]"
className="fixed right-[9%] top-[19%] z-10 -translate-y-1/2 translate-x-1/2 cursor-pointer rounded-full border border-strong p-1 sm:top-[11.5%] md:right-[24%] lg:right-[19%]"
onClick={onComplete}
>
<CloseIcon className="h-3 w-3 text-custom-text-100" />
<CloseIcon className="h-3 w-3 text-primary border-strong-" />
</button>
<TourSidebar step={step} setStep={setStep} />
<div className="col-span-10 h-full overflow-hidden lg:col-span-7">
<div
className={`flex h-1/2 items-end overflow-hidden bg-custom-primary-100 sm:h-3/5 ${
className={`flex h-1/2 items-end overflow-hidden bg-accent-primary sm:h-3/5 ${
currentStepIndex % 2 === 0 ? "justify-end" : "justify-start"
}`}
>
<img src={currentStep?.image} className="w-full h-full object-cover" alt={currentStep?.title} />
</div>
<div className="flex h-1/2 flex-col overflow-y-auto p-4 sm:h-2/5">
<h3 className="font-semibold sm:text-xl">{currentStep?.title}</h3>
<p className="mt-3 text-sm text-custom-text-200">{currentStep?.description}</p>
<h3 className="font-semibold sm:text-18">{currentStep?.title}</h3>
<p className="mt-3 text-13 text-secondary">{currentStep?.description}</p>
<div className="mt-3 flex h-full items-end justify-between gap-4">
<div className="flex items-center gap-4">
{currentStep?.prevStep && (
<Button variant="neutral-primary" onClick={() => setStep(currentStep.prevStep ?? "welcome")}>
<Button variant="secondary" onClick={() => setStep(currentStep.prevStep ?? "welcome")}>
Back
</Button>
)}

View file

@ -43,8 +43,8 @@ type Props = {
export function TourSidebar({ step, setStep }: Props) {
return (
<div className="col-span-3 hidden bg-custom-background-90 p-8 lg:block">
<h3 className="text-lg font-medium">
<div className="col-span-3 hidden bg-surface-2 p-8 lg:block">
<h3 className="text-16 font-medium">
Let{"'"}s get started!
<br />
Get more out of Plane.
@ -53,10 +53,8 @@ export function TourSidebar({ step, setStep }: Props) {
{sidebarOptions.map((option) => (
<h5
key={option.key}
className={`flex cursor-pointer items-center gap-2 border-l-[3px] py-0.5 pl-3 pr-2 text-sm font-medium capitalize ${
step === option.key
? "border-custom-primary-100 text-custom-primary-100"
: "border-transparent text-custom-text-200"
className={`flex cursor-pointer items-center gap-2 border-l-[3px] py-0.5 pl-3 pr-2 text-13 font-medium capitalize ${
step === option.key ? "border-accent-strong text-accent-primary" : "border-transparent text-secondary"
}`}
onClick={() => setStep(option.key)}
role="button"

View file

@ -33,7 +33,7 @@ export function AskPiMenu(props: Props) {
"items-start": response,
})}
>
<span className="flex-shrink-0 size-7 grid place-items-center text-custom-text-200 rounded-full border border-custom-border-200">
<span className="flex-shrink-0 size-7 grid place-items-center text-secondary rounded-full border border-subtle">
<Sparkles className="size-3" />
</span>
{response ? (
@ -53,7 +53,7 @@ export function AskPiMenu(props: Props) {
<div className="mt-3 flex items-center gap-4">
<button
type="button"
className="p-1 text-custom-text-300 text-sm font-medium rounded hover:bg-custom-background-80 outline-none"
className="p-1 text-tertiary text-13 font-medium rounded-sm hover:bg-layer-1 outline-none"
onClick={() => handleInsertText(false)}
>
Replace selection
@ -61,16 +61,16 @@ export function AskPiMenu(props: Props) {
<Tooltip tooltipContent="Add to next line">
<button
type="button"
className="flex-shrink-0 size-6 grid place-items-center rounded hover:bg-custom-background-80 outline-none"
className="flex-shrink-0 size-6 grid place-items-center rounded-sm hover:bg-layer-1 outline-none"
onClick={() => handleInsertText(true)}
>
<CornerDownRight className="text-custom-text-300 size-4" />
<CornerDownRight className="text-tertiary size-4" />
</button>
</Tooltip>
<Tooltip tooltipContent="Re-generate response">
<button
type="button"
className="flex-shrink-0 size-6 grid place-items-center rounded hover:bg-custom-background-80 outline-none"
className="flex-shrink-0 size-6 grid place-items-center rounded-sm hover:bg-layer-1 outline-none"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@ -79,7 +79,7 @@ export function AskPiMenu(props: Props) {
disabled={isRegenerating}
>
<RefreshCcw
className={cn("text-custom-text-300 size-4", {
className={cn("text-tertiary size-4", {
"animate-spin": isRegenerating,
})}
/>
@ -88,23 +88,23 @@ export function AskPiMenu(props: Props) {
</div>
</div>
) : (
<p className="text-sm text-custom-text-200">Pi is answering...</p>
<p className="text-13 text-secondary">AI is answering...</p>
)}
</div>
<div className="py-3 px-4">
<div className="flex items-center gap-2 border border-custom-border-200 rounded-md p-2">
<div className="flex items-center gap-2 border border-subtle rounded-md p-2">
<span className="flex-shrink-0 size-3 grid place-items-center">
<Sparkles className="size-3 text-custom-text-200" />
<Sparkles className="size-3 text-secondary" />
</span>
<input
type="text"
className="w-full bg-transparent border-none outline-none placeholder:text-custom-text-400 text-sm"
className="w-full bg-transparent border-none outline-none placeholder:text-placeholder text-13"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Tell Pi what to do..."
placeholder="Tell AI what to do..."
/>
<span className="flex-shrink-0 size-4 grid place-items-center">
<CircleArrowUp className="size-4 text-custom-text-200" />
<CircleArrowUp className="size-4 text-secondary" />
</span>
</div>
</div>

View file

@ -138,7 +138,7 @@ export function EditorAIMenu(props: Props) {
return (
<div
className={cn(
"w-[210px] flex flex-col rounded-md border-[0.5px] border-custom-border-300 bg-custom-background-100 shadow-custom-shadow-rg transition-all",
"w-[210px] flex flex-col rounded-md border-[0.5px] border-strong bg-surface-1 shadow-custom-shadow-rg transition-all",
{
"w-[700px]": activeTask,
}
@ -146,7 +146,7 @@ export function EditorAIMenu(props: Props) {
>
<div
className={cn("flex max-h-72 w-full", {
"divide-x divide-custom-border-200": activeTask,
"divide-x divide-subtle-1": activeTask,
})}
>
<div className="flex-shrink-0 w-[210px] overflow-y-auto px-2 py-2.5 transition-all">
@ -158,9 +158,9 @@ export function EditorAIMenu(props: Props) {
key={item.key}
type="button"
className={cn(
"w-full flex items-center justify-between gap-2 truncate rounded px-1 py-1.5 text-xs text-custom-text-200 hover:bg-custom-background-80 transition-colors",
"w-full flex items-center justify-between gap-2 truncate rounded-sm px-1 py-1.5 text-11 text-secondary hover:bg-layer-1 transition-colors",
{
"bg-custom-background-80": isActiveTask,
"bg-layer-1": isActiveTask,
}
)}
onClick={(e) => {
@ -203,7 +203,7 @@ export function EditorAIMenu(props: Props) {
"items-start": response,
})}
>
<span className="flex-shrink-0 size-7 grid place-items-center text-custom-text-200 rounded-full border border-custom-border-200">
<span className="flex-shrink-0 size-7 grid place-items-center text-secondary rounded-full border border-subtle">
<Sparkles className="size-3" />
</span>
{response ? (
@ -223,7 +223,7 @@ export function EditorAIMenu(props: Props) {
<div className="mt-3 flex items-center gap-4">
<button
type="button"
className="p-1 text-custom-text-300 text-sm font-medium rounded hover:bg-custom-background-80 outline-none"
className="p-1 text-tertiary text-13 font-medium rounded-sm hover:bg-layer-1 outline-none"
onClick={() => handleInsertText(false)}
>
Replace selection
@ -231,16 +231,16 @@ export function EditorAIMenu(props: Props) {
<Tooltip tooltipContent="Add to next line">
<button
type="button"
className="flex-shrink-0 size-6 grid place-items-center rounded hover:bg-custom-background-80 outline-none"
className="flex-shrink-0 size-6 grid place-items-center rounded-sm hover:bg-layer-1 outline-none"
onClick={() => handleInsertText(true)}
>
<CornerDownRight className="text-custom-text-300 size-4" />
<CornerDownRight className="text-tertiary size-4" />
</button>
</Tooltip>
<Tooltip tooltipContent="Re-generate response">
<button
type="button"
className="flex-shrink-0 size-6 grid place-items-center rounded hover:bg-custom-background-80 outline-none"
className="flex-shrink-0 size-6 grid place-items-center rounded-sm hover:bg-layer-1 outline-none"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@ -249,7 +249,7 @@ export function EditorAIMenu(props: Props) {
disabled={isRegenerating}
>
<RefreshCcw
className={cn("text-custom-text-300 size-4", {
className={cn("text-tertiary size-4", {
"animate-spin": isRegenerating,
})}
/>
@ -258,20 +258,20 @@ export function EditorAIMenu(props: Props) {
</div>
</div>
) : (
<p className="text-sm text-custom-text-200">
<p className="text-13 text-secondary">
{activeTask ? LOADING_TEXTS[activeTask] : "Pi is writing"}...
</p>
)}
</div>
<div className="sticky bottom-0 w-full bg-custom-background-100 pl-[54.8px] py-2 flex items-center gap-2">
<div className="sticky bottom-0 w-full bg-surface-1 pl-[54.8px] py-2 flex items-center gap-2">
{TONES_LIST.map((tone) => (
<button
key={tone.key}
type="button"
className={cn(
"p-1 text-xs text-custom-text-200 font-medium bg-custom-background-80 rounded transition-colors outline-none",
"p-1 text-11 text-secondary font-medium bg-layer-1 rounded-sm transition-colors outline-none",
{
"bg-custom-primary-100/20 text-custom-primary-100": tone.key === "default",
"bg-accent-primary/20 text-accent-primary": tone.key === "default",
}
)}
onClick={(e) => {
@ -289,11 +289,11 @@ export function EditorAIMenu(props: Props) {
</div>
</div>
{activeTask && (
<div className="bg-custom-background-90 rounded-b-md py-2 px-4 text-custom-text-300 flex items-center gap-2 border-t border-custom-border-200">
<div className="bg-surface-2 rounded-b-md py-2 px-4 text-tertiary flex items-center gap-2 border-t border-subtle">
<span className="flex-shrink-0 size-4 grid place-items-center">
<TriangleAlert className="size-3" />
</span>
<p className="flex-shrink-0 text-xs font-medium">
<p className="flex-shrink-0 text-11 font-medium">
By using this feature, you consent to sharing the message with a 3rd party service.
</p>
</div>

View file

@ -8,7 +8,7 @@ export function IssueEmbedUpgradeCard(props: any) {
return (
<div
className={cn(
"w-full bg-custom-background-80 rounded-md border-[0.5px] border-custom-border-200 shadow-custom-shadow-2xs flex items-center justify-between gap-5 px-5 py-2 max-md:flex-wrap",
"w-full bg-layer-1 rounded-md border-[0.5px] border-subtle shadow-custom-shadow-2xs flex items-center justify-between gap-5 px-5 py-2 max-md:flex-wrap",
{
"border-2": props.selected,
}
@ -16,7 +16,7 @@ export function IssueEmbedUpgradeCard(props: any) {
>
<div className="flex items-center gap-4">
<ProIcon className="flex-shrink-0 size-4" />
<p className="text-custom-text !text-base">
<p className="text-custom-text !text-14">
Embed and access issues in pages seamlessly, upgrade to Plane Pro now.
</p>
</div>
@ -24,7 +24,7 @@ export function IssueEmbedUpgradeCard(props: any) {
href="https://plane.so/pro"
target="_blank"
rel="noopener noreferrer"
className={cn(getButtonStyling("primary", "md"), "no-underline")}
className={cn(getButtonStyling("primary", "base"), "no-underline")}
>
Upgrade
</a>

View file

@ -80,7 +80,7 @@ export const PageLockControl = observer(function PageLockControl({ page }: Props
type="button"
onClick={toggleLock}
data-ph-element={PROJECT_PAGE_TRACKER_ELEMENTS.LOCK_BUTTON}
className="flex-shrink-0 size-6 grid place-items-center rounded text-custom-text-200 hover:text-custom-text-100 hover:bg-custom-background-80 transition-colors"
className="flex-shrink-0 size-6 grid place-items-center rounded-sm text-secondary hover:text-primary hover:bg-layer-1 transition-colors"
aria-label="Lock"
>
<LockKeyhole className="size-3.5" />
@ -93,11 +93,11 @@ export const PageLockControl = observer(function PageLockControl({ page }: Props
type="button"
onClick={toggleLock}
data-ph-element={PROJECT_PAGE_TRACKER_ELEMENTS.LOCK_BUTTON}
className="h-6 flex items-center gap-1 px-2 rounded text-custom-primary-100 bg-custom-primary-100/20 hover:bg-custom-primary-100/30 transition-colors"
className="h-6 flex items-center gap-1 px-2 rounded-sm text-accent-primary bg-accent-primary/20 hover:bg-accent-primary/30 transition-colors"
aria-label="Locked"
>
<LockKeyhole className="flex-shrink-0 size-3.5 animate-lock-icon" />
<span className="text-xs font-medium whitespace-nowrap overflow-hidden transition-all duration-500 ease-out animate-text-slide-in">
<span className="text-11 font-medium whitespace-nowrap overflow-hidden transition-all duration-500 ease-out animate-text-slide-in">
Locked
</span>
</button>
@ -105,11 +105,11 @@ export const PageLockControl = observer(function PageLockControl({ page }: Props
{displayState === "unlocked" && (
<div
className="h-6 flex items-center gap-1 px-2 rounded text-custom-text-200 animate-fade-out"
className="h-6 flex items-center gap-1 px-2 rounded-sm text-secondary animate-fade-out"
aria-label="Unlocked"
>
<LockKeyholeOpen className="flex-shrink-0 size-3.5 animate-unlock-icon" />
<span className="text-xs font-medium whitespace-nowrap overflow-hidden transition-all duration-500 ease-out animate-text-slide-in animate-text-fade-out">
<span className="text-11 font-medium whitespace-nowrap overflow-hidden transition-all duration-500 ease-out animate-text-slide-in animate-text-fade-out">
Unlocked
</span>
</div>

View file

@ -16,14 +16,10 @@ export function PageNavigationPaneAssetsTabEmptyState() {
return (
<div className="size-full grid place-items-center">
<div className="flex flex-col items-center gap-y-6 text-center">
<img
src={resolvedPath}
className="w-[160px] h-[160px] object-contain"
alt="An image depicting the assets of a page"
/>
<img src={resolvedPath} className="size-40 object-contain" alt="depicts the assets of a page" />
<div className="space-y-2.5">
<h4 className="text-base font-medium">{t("page_navigation_pane.tabs.assets.empty_state.title")}</h4>
<p className="text-sm text-custom-text-200 font-medium">
<h4 className="text-14 font-medium">{t("page_navigation_pane.tabs.assets.empty_state.title")}</h4>
<p className="text-13 text-secondary font-medium">
{t("page_navigation_pane.tabs.assets.empty_state.description")}
</p>
</div>

View file

@ -16,14 +16,10 @@ export function PageNavigationPaneOutlineTabEmptyState() {
return (
<div className="size-full grid place-items-center">
<div className="flex flex-col items-center gap-y-6 text-center">
<img
src={resolvedPath}
className="w-[160px] h-[160px] object-contain"
alt="An image depicting the outline of a page"
/>
<img src={resolvedPath} className="size-40 object-contain" alt="depicts the outline of a page" />
<div className="space-y-2.5">
<h4 className="text-base font-medium">{t("page_navigation_pane.tabs.outline.empty_state.title")}</h4>
<p className="text-sm text-custom-text-200 font-medium">
<h4 className="text-14 font-medium">{t("page_navigation_pane.tabs.outline.empty_state.title")}</h4>
<p className="text-13 text-secondary font-medium">
{t("page_navigation_pane.tabs.outline.empty_state.description")}
</p>
</div>

View file

@ -40,7 +40,7 @@ function ProjectAttributes(props: Props) {
{t(currentNetwork.i18n_label)}
</>
) : (
<span className="text-custom-text-400">{t("select_network")}</span>
<span className="text-placeholder">{t("select_network")}</span>
)}
</div>
}
@ -56,7 +56,7 @@ function ProjectAttributes(props: Props) {
<ProjectNetworkIcon iconKey={network.iconKey} className="h-3.5 w-3.5" />
<div className="-mt-1">
<p>{t(network.i18n_label)}</p>
<p className="text-xs text-custom-text-400">{t(network.description)}</p>
<p className="text-11 text-placeholder">{t(network.description)}</p>
</div>
</div>
</CustomSelect.Option>

View file

@ -52,7 +52,7 @@ export const ProjectsListMobileHeader = observer(function ProjectsListMobileHead
const isFiltersApplied = calculateTotalFilters(filters ?? {}) !== 0;
return (
<div className="flex py-2 border-b border-custom-border-200 md:hidden bg-custom-background-100 w-full">
<div className="flex py-2 border-b border-subtle md:hidden bg-surface-1 w-full">
<ProjectOrderByDropdown
value={displayFilters?.order_by}
onChange={(val) => {
@ -63,13 +63,13 @@ export const ProjectsListMobileHeader = observer(function ProjectsListMobileHead
}}
isMobile
/>
<div className="border-l border-custom-border-200 flex justify-around w-full">
<div className="border-l border-subtle flex justify-around w-full">
<FiltersDropdown
icon={<ListFilter className="h-3 w-3" />}
title={t("common.filters")}
placement="bottom-end"
menuButton={
<div className="flex text-sm items-center gap-2 neutral-primary text-custom-text-200">
<div className="flex text-13 items-center gap-2 text-secondary">
<ListFilter className="h-3 w-3" />
{t("common.filters")}
<ChevronDownIcon className="h-3 w-3" strokeWidth={2} />

View file

@ -47,7 +47,7 @@ export const ProjectInboxHeader = observer(function ProjectInboxHeader() {
<BreadcrumbLink
label="Intake"
href={`/${workspaceSlug}/projects/${projectId}/intake/`}
icon={<IntakeIcon className="h-4 w-4 text-custom-text-300" />}
icon={<IntakeIcon className="h-4 w-4 text-tertiary" />}
isLast
/>
}
@ -56,9 +56,9 @@ export const ProjectInboxHeader = observer(function ProjectInboxHeader() {
</Breadcrumbs>
{loader === "pagination-loading" && (
<div className="flex items-center gap-1.5 text-custom-text-300">
<div className="flex items-center gap-1.5 text-tertiary">
<RefreshCcw className="h-3.5 w-3.5 animate-spin" />
<p className="text-sm">{t("syncing")}...</p>
<p className="text-13">{t("syncing")}...</p>
</div>
)}
</div>
@ -72,8 +72,7 @@ export const ProjectInboxHeader = observer(function ProjectInboxHeader() {
modalState={createIssueModal}
handleModalClose={() => setCreateIssueModal(false)}
/>
<Button variant="primary" size="sm" onClick={() => setCreateIssueModal(true)}>
<Button variant="primary" size="lg" onClick={() => setCreateIssueModal(true)}>
{t("add_work_item")}
</Button>
</div>

View file

@ -94,7 +94,7 @@ export const useProjectColumns = (props: TUseProjectColumnsProps) => {
handleDisplayFilterUpdate={handleDisplayFilterUpdate}
/>
),
tdRender: (rowData: RowData) => <div className="w-48 text-custom-text-200">{rowData.member.email}</div>,
tdRender: (rowData: RowData) => <div className="w-48 text-secondary">{rowData.member.email}</div>,
},
{
key: "Account Type",

View file

@ -9,29 +9,29 @@ export const ISSUE_RELATION_OPTIONS: Record<TIssueRelationTypes, TRelationObject
relates_to: {
key: "relates_to",
i18n_label: "issue.relation.relates_to",
className: "bg-custom-background-80 text-custom-text-200",
icon: (size) => <RelatedIcon height={size} width={size} className="text-custom-text-200" />,
className: "bg-layer-1 text-secondary",
icon: (size) => <RelatedIcon height={size} width={size} className="text-secondary" />,
placeholder: "Add related work items",
},
duplicate: {
key: "duplicate",
i18n_label: "issue.relation.duplicate",
className: "bg-custom-background-80 text-custom-text-200",
icon: (size) => <DuplicatePropertyIcon width={size} height={size} className="text-custom-text-200" />,
className: "bg-layer-1 text-secondary",
icon: (size) => <DuplicatePropertyIcon width={size} height={size} className="text-secondary" />,
placeholder: "None",
},
blocked_by: {
key: "blocked_by",
i18n_label: "issue.relation.blocked_by",
className: "bg-red-500/20 text-red-700",
icon: (size) => <CircleDot size={size} className="text-custom-text-200" />,
icon: (size) => <CircleDot size={size} className="text-secondary" />,
placeholder: "None",
},
blocking: {
key: "blocking",
i18n_label: "issue.relation.blocking",
className: "bg-yellow-500/20 text-yellow-700",
icon: (size) => <XCircle size={size} className="text-custom-text-200" />,
icon: (size) => <XCircle size={size} className="text-secondary" />,
placeholder: "None",
},
};

View file

@ -11,7 +11,7 @@ export const AdditionalFilterValueInput = observer(function AdditionalFilterValu
>(_props: TFilterValueInputProps<P, V>) {
return (
// Fallback
<div className="h-full flex items-center px-4 text-xs text-custom-text-400 transition-opacity duration-200 cursor-not-allowed">
<div className="h-full flex items-center px-4 text-11 text-placeholder transition-opacity duration-200 cursor-not-allowed">
Filter type not supported
</div>
);

View file

@ -1,6 +1,7 @@
import { observer } from "mobx-react";
import { Check } from "lucide-react";
import { Combobox } from "@headlessui/react";
import { cn } from "@plane/utils";
export type TStateOptionProps = {
projectId: string | null | undefined;
@ -24,7 +25,7 @@ export const StateOption = observer(function StateOption(props: TStateOptionProp
key={option.value}
value={option.value}
className={({ active, selected }) =>
`${className} ${active ? "bg-custom-background-80" : ""} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
cn(`${className} ${active ? "bg-layer-transparent-hover" : ""} ${selected ? "text-primary" : "text-secondary"}`)
}
>
{({ selected }) => (

View file

@ -39,12 +39,12 @@ export const NotificationCardListRoot = observer(function NotificationCardListRo
{paginationInfo && paginationInfo?.next_page_results && (
<>
{loader === ENotificationLoader.PAGINATION_LOADER ? (
<div className="py-4 flex justify-center items-center text-sm font-medium">
<div className="text-custom-primary-90">{t("loading")}...</div>
<div className="py-4 flex justify-center items-center text-13 font-medium">
<div className="text-accent-secondary">{t("loading")}...</div>
</div>
) : (
<div className="py-4 flex justify-center items-center text-sm font-medium" onClick={getNextNotifications}>
<div className="text-custom-primary-90 hover:text-custom-primary-100 transition-all cursor-pointer">
<div className="py-4 flex justify-center items-center text-13 font-medium" onClick={getNextNotifications}>
<div className="text-accent-secondary hover:text-accent-primary transition-all cursor-pointer">
{t("load_more")}
</div>
</div>

View file

@ -1,8 +1,6 @@
import type { FC } from "react";
// plane imports
import { observer } from "mobx-react";
import type { EProductSubscriptionEnum, TBillingFrequency } from "@plane/types";
import { getSubscriptionBackgroundColor, getDiscountPillStyle } from "@plane/ui";
import { calculateYearlyDiscount, cn } from "@plane/utils";
type TPlanFrequencyToggleProps = {
@ -14,47 +12,42 @@ type TPlanFrequencyToggleProps = {
};
export const PlanFrequencyToggle = observer(function PlanFrequencyToggle(props: TPlanFrequencyToggleProps) {
const { subscriptionType, monthlyPrice, yearlyPrice, selectedFrequency, setSelectedFrequency } = props;
const { monthlyPrice, yearlyPrice, selectedFrequency, setSelectedFrequency } = props;
// derived values
const yearlyDiscount = calculateYearlyDiscount(monthlyPrice, yearlyPrice);
return (
<div className="flex w-full items-center cursor-pointer py-1 animate-slide-up">
<div
className={cn(
"flex space-x-1 rounded-md bg-custom-primary-200/10 p-0.5 w-full",
getSubscriptionBackgroundColor(subscriptionType, "50")
)}
>
<div
key="month"
<div className="flex w-full items-center cursor-pointer py-1">
<div className="flex space-x-1 rounded-md bg-layer-3 p-0.5 w-full">
<button
type="button"
onClick={() => setSelectedFrequency("month")}
className={cn(
"w-full rounded px-1 py-0.5 text-xs font-medium leading-5 text-center",
"w-full rounded-sm px-1 py-0.5 text-caption-sm-medium leading-5 text-center",
selectedFrequency === "month"
? "bg-custom-background-100 text-custom-text-100 shadow"
: "text-custom-text-300 hover:text-custom-text-200"
? "bg-layer-2 text-primary shadow-raised-100 border border-subtle-1"
: "text-tertiary hover:text-secondary"
)}
>
Monthly
</div>
<div
key="year"
</button>
<button
type="button"
onClick={() => setSelectedFrequency("year")}
className={cn(
"w-full rounded px-1 py-0.5 text-xs font-medium leading-5 text-center",
"w-full rounded-sm px-1 py-0.5 text-caption-sm-medium leading-5 text-center",
selectedFrequency === "year"
? "bg-custom-background-100 text-custom-text-100 shadow"
: "text-custom-text-300 hover:text-custom-text-200"
? "bg-layer-2 text-primary shadow-raised-100 border border-subtle-1"
: "text-tertiary hover:text-secondary"
)}
>
Yearly
{yearlyDiscount > 0 && (
<span className={cn(getDiscountPillStyle(subscriptionType), "rounded-full px-1 py-0.5 ml-1 text-[9px]")}>
<span className="bg-accent-primary text-on-color rounded-full px-1 py-0.5 ml-1.5 text-caption-xs-regular">
-{yearlyDiscount}%
</span>
)}
</div>
</button>
</div>
</div>
);

View file

@ -1,4 +1,3 @@
import type { FC } from "react";
import { observer } from "mobx-react";
// plane imports
import {
@ -9,11 +8,10 @@ import {
WORKSPACE_SETTINGS_TRACKER_EVENTS,
} from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { getButtonStyling } from "@plane/propel/button";
import { Button } from "@plane/propel/button";
import type { TBillingFrequency } from "@plane/types";
import { EProductSubscriptionEnum } from "@plane/types";
import { getUpgradeButtonStyle } from "@plane/ui";
import { cn, getSubscriptionName } from "@plane/utils";
import { getSubscriptionName } from "@plane/utils";
// components
import { DiscountInfo } from "@/components/license/modal/card/discount-info";
import type { TPlanDetail } from "@/constants/plans";
@ -28,9 +26,6 @@ type TPlanDetailProps = {
setBillingFrequency: (frequency: TBillingFrequency) => void;
};
const COMMON_BUTTON_STYLE =
"relative inline-flex items-center justify-center w-full px-4 py-1.5 text-xs font-medium rounded-lg focus:outline-none transition-all duration-300 animate-slide-up";
export const PlanDetail = observer(function PlanDetail(props: TPlanDetailProps) {
const { subscriptionType, planDetail, billingFrequency, setBillingFrequency } = props;
// plane hooks
@ -45,8 +40,6 @@ export const PlanDetail = observer(function PlanDetail(props: TPlanDetailProps)
billingFrequency === "month"
? planDetail.monthlyPriceSecondaryDescription
: planDetail.yearlyPriceSecondaryDescription;
// helper styles
const upgradeButtonStyle = getUpgradeButtonStyle(subscriptionType, false) ?? getButtonStyling("primary", "lg");
const handleRedirection = () => {
const frequency = billingFrequency ?? "year";
@ -66,15 +59,17 @@ export const PlanDetail = observer(function PlanDetail(props: TPlanDetailProps)
<div className="flex flex-col justify-between col-span-1 p-3 space-y-0.5">
{/* Plan name and pricing section */}
<div className="flex flex-col items-start">
<div className="flex w-full gap-2 items-center text-xl font-medium">
<span className="transition-all duration-300">{subscriptionName}</span>
<div className="flex w-full gap-2 items-center text-h4-semibold">
<span>{subscriptionName}</span>
{subscriptionType === EProductSubscriptionEnum.PRO && (
<span className="px-2 rounded text-custom-primary-200 bg-custom-primary-100/20 text-xs">Popular</span>
<span className="px-2 py-0.5 rounded-sm text-on-color bg-accent-primary text-caption-sm-medium">
Popular
</span>
)}
</div>
<div className="flex gap-x-2 items-start text-custom-text-300 pb-1 transition-all duration-300 animate-slide-up">
<div className="flex gap-x-2 items-start text-tertiary pb-1">
{isSubscriptionActive && displayPrice !== undefined && (
<div className="flex items-center gap-1 text-2xl text-custom-text-100 font-semibold transition-all duration-300">
<div className="flex items-center gap-1 text-h3-semibold text-primary">
<DiscountInfo
currency="$"
frequency={billingFrequency ?? "month"}
@ -85,11 +80,9 @@ export const PlanDetail = observer(function PlanDetail(props: TPlanDetailProps)
</div>
)}
<div className="pt-1">
{pricingDescription && <div className="transition-all duration-300">{pricingDescription}</div>}
{pricingDescription && <div>{pricingDescription}</div>}
{pricingSecondaryDescription && (
<div className="text-xs text-custom-text-400 transition-all duration-300">
{pricingSecondaryDescription}
</div>
<div className="text-caption-xs text-placeholder">{pricingSecondaryDescription}</div>
)}
</div>
</div>
@ -109,10 +102,12 @@ export const PlanDetail = observer(function PlanDetail(props: TPlanDetailProps)
)}
{/* Subscription button */}
<div className={cn("flex flex-col gap-1 py-3 items-start transition-all duration-300")}>
<button
<div className="flex flex-col gap-1 py-3 items-start">
<Button
variant="primary"
size="lg"
onClick={handleRedirection}
className={cn(upgradeButtonStyle, COMMON_BUTTON_STYLE)}
className="w-full"
data-ph-element={
isSubscriptionActive
? WORKSPACE_SETTINGS_TRACKER_ELEMENTS.BILLING_UPGRADE_BUTTON(subscriptionType)
@ -120,7 +115,7 @@ export const PlanDetail = observer(function PlanDetail(props: TPlanDetailProps)
}
>
{isSubscriptionActive ? `Upgrade to ${subscriptionName}` : t("common.upgrade_cta.talk_to_sales")}
</button>
</Button>
</div>
</div>
);

View file

@ -5,8 +5,6 @@ import { DEFAULT_PRODUCT_BILLING_FREQUENCY, SUBSCRIPTION_WITH_BILLING_FREQUENCY
import { useTranslation } from "@plane/i18n";
import type { TBillingFrequency, TProductBillingFrequency } from "@plane/types";
import { EProductSubscriptionEnum } from "@plane/types";
import { getSubscriptionTextColor } from "@plane/ui";
import { cn } from "@plane/utils";
// components
import { SettingsHeading } from "@/components/settings/heading";
// local imports
@ -44,24 +42,20 @@ export const BillingRoot = observer(function BillingRoot() {
title={t("workspace_settings.settings.billing_and_plans.heading")}
description={t("workspace_settings.settings.billing_and_plans.description")}
/>
<div className={cn("transition-all duration-500 ease-in-out will-change-[height,opacity]")}>
<div>
<div className="py-6">
<div className={cn("px-6 py-4 border border-custom-border-200 rounded-lg")}>
<div className="flex gap-2 font-medium items-center justify-between">
<div className="px-6 py-4 rounded-lg bg-layer-1">
<div className="flex gap-2 items-center justify-between">
<div className="flex flex-col gap-1">
<h4
className={cn("text-xl leading-6 font-bold", getSubscriptionTextColor(EProductSubscriptionEnum.FREE))}
>
Community
</h4>
<div className="text-sm text-custom-text-200 font-medium">
<h4 className="text-h4-bold text-primary">Community</h4>
<div className="text-caption-md-medium text-secondary">
Unlimited projects, issues, cycles, modules, pages, and storage
</div>
</div>
</div>
</div>
</div>
<div className="text-xl font-semibold mt-3">All plans</div>
<div className="text-h4-semibold mt-3">All plans</div>
</div>
<PlansComparison
isCompareAllFeaturesSectionOpen={isCompareAllFeaturesSectionOpen}

View file

@ -16,7 +16,7 @@ export const WorkspaceContentWrapper = observer(function WorkspaceContentWrapper
const { shouldRenderAppRail } = useAppRailVisibility();
return (
<div className="flex flex-col relative size-full overflow-hidden bg-custom-background-90 transition-all ease-in-out duration-300">
<div className="flex flex-col relative size-full overflow-hidden bg-canvas transition-all ease-in-out duration-300">
<TopNavigationRoot />
<div className="relative flex size-full overflow-hidden">
{/* Conditionally render AppRailRoot based on context */}
@ -25,7 +25,7 @@ export const WorkspaceContentWrapper = observer(function WorkspaceContentWrapper
className={cn(
"relative size-full pl-2 pb-2 pr-2 flex-grow transition-all ease-in-out duration-300 overflow-hidden",
{
"pl-0": shouldRenderAppRail,
"pl-0!": shouldRenderAppRail,
}
)}
>

View file

@ -1,4 +1,3 @@
import type { FC } from "react";
import { useState } from "react";
import { observer } from "mobx-react";
// types
@ -30,7 +29,7 @@ export const DeleteWorkspaceSection = observer(function DeleteWorkspaceSection(p
isOpen={deleteWorkspaceModal}
onClose={() => setDeleteWorkspaceModal(false)}
/>
<div className="border-t border-custom-border-100">
<div className="border-t border-subtle">
<div className="w-full">
<Collapsible
isOpen={isOpen}
@ -39,7 +38,7 @@ export const DeleteWorkspaceSection = observer(function DeleteWorkspaceSection(p
buttonClassName="flex w-full items-center justify-between py-4"
title={
<>
<span className="text-lg tracking-tight">
<span className="text-body-md-medium tracking-tight">
{t("workspace_settings.settings.general.delete_workspace")}
</span>
{isOpen ? <ChevronUpIcon className="h-5 w-5" /> : <ChevronDownIcon className="h-5 w-5" />}
@ -47,12 +46,13 @@ export const DeleteWorkspaceSection = observer(function DeleteWorkspaceSection(p
}
>
<div className="flex flex-col gap-4">
<span className="text-base tracking-tight">
<span className="text-body-sm-regular tracking-tight">
{t("workspace_settings.settings.general.delete_workspace_description")}
</span>
<div>
<Button
variant="danger"
variant="error-fill"
size="lg"
onClick={() => setDeleteWorkspaceModal(true)}
data-ph-element={WORKSPACE_TRACKER_ELEMENTS.DELETE_WORKSPACE_BUTTON}
>

View file

@ -2,13 +2,13 @@ import { useState } from "react";
import { observer } from "mobx-react";
// ui
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/propel/button";
import { Tooltip } from "@plane/propel/tooltip";
// hooks
import { usePlatformOS } from "@/hooks/use-platform-os";
import packageJson from "package.json";
// local components
import { PaidPlanUpgradeModal } from "../license";
import { Button } from "@plane/propel/button";
export const WorkspaceEditionBadge = observer(function WorkspaceEditionBadge() {
// states
@ -26,9 +26,8 @@ export const WorkspaceEditionBadge = observer(function WorkspaceEditionBadge() {
/>
<Tooltip tooltipContent={`Version: v${packageJson.version}`} isMobile={isMobile}>
<Button
tabIndex={-1}
variant="accent-primary"
className="w-fit min-w-24 cursor-pointer rounded-2xl px-2 py-1 text-center text-sm font-medium outline-none"
variant="tertiary"
size="lg"
onClick={() => setIsPaidPlanPurchaseModalOpen(true)}
aria-haspopup="dialog"
aria-label={t("aria_labels.projects_sidebar.edition_badge")}

View file

@ -62,9 +62,7 @@ export const useMemberColumns = () => {
key: "Display name",
content: t("workspace_settings.settings.members.details.display_name"),
tdRender: (rowData: RowData) => (
<div className={`w-32 ${isSuspended(rowData) ? "text-custom-text-400" : ""}`}>
{rowData.member.display_name}
</div>
<div className={`w-32 ${isSuspended(rowData) ? "text-placeholder" : ""}`}>{rowData.member.display_name}</div>
),
thRender: () => (
<MemberHeaderColumn
@ -79,9 +77,7 @@ export const useMemberColumns = () => {
key: "Email address",
content: t("workspace_settings.settings.members.details.email_address"),
tdRender: (rowData: RowData) => (
<div className={`w-48 truncate ${isSuspended(rowData) ? "text-custom-text-400" : ""}`}>
{rowData.member.email}
</div>
<div className={`w-48 truncate ${isSuspended(rowData) ? "text-placeholder" : ""}`}>{rowData.member.email}</div>
),
thRender: () => (
<MemberHeaderColumn

View file

@ -152,14 +152,14 @@ export const ExtendedSidebarItem = observer(function ExtendedSidebarItem(props:
<div
id={`sidebar-${item.key}`}
className={cn("relative", {
"bg-custom-sidebar-background-80 opacity-60": isDragging,
"bg-layer-1 opacity-60": isDragging,
})}
ref={navigationIemRef}
>
<DropIndicator classNames="absolute top-0" isVisible={instruction === "DRAG_OVER"} />
<div
className={cn(
"group/project-item relative w-full flex items-center rounded-md text-custom-sidebar-text-100 hover:bg-custom-sidebar-background-90"
"group/project-item relative w-full flex items-center rounded-md text-primary hover:bg-surface-2"
)}
id={`${item.key}`}
>
@ -173,7 +173,7 @@ export const ExtendedSidebarItem = observer(function ExtendedSidebarItem(props:
<button
type="button"
className={cn(
"flex items-center justify-center absolute top-1/2 -left-3 -translate-y-1/2 rounded text-custom-sidebar-text-400 cursor-grab group-hover/project-item:opacity-100 opacity-0",
"flex items-center justify-center absolute top-1/2 -left-3 -translate-y-1/2 rounded text-placeholder cursor-grab group-hover/project-item:opacity-100 opacity-0",
{
"cursor-grabbing": isDragging,
"opacity-100": isDragging,
@ -189,7 +189,7 @@ export const ExtendedSidebarItem = observer(function ExtendedSidebarItem(props:
<Link href={itemHref} onClick={() => handleLinkClick()} className="group flex-grow">
<div className="flex items-center gap-1.5 py-[1px]">
{icon}
<p className="text-sm leading-5 font-medium">{t(item.labelTranslationKey)}</p>
<p className="text-13 leading-5 font-medium">{t(item.labelTranslationKey)}</p>
</div>
</Link>
<div className="flex items-center gap-2">
@ -201,14 +201,14 @@ export const ExtendedSidebarItem = observer(function ExtendedSidebarItem(props:
{isPinned ? (
<Tooltip tooltipContent="Unpin">
<PinOff
className="size-3.5 flex-shrink-0 hover:text-custom-text-300 outline-none text-custom-text-400"
className="size-3.5 flex-shrink-0 hover:text-tertiary outline-none text-placeholder"
onClick={() => unPinNavigationItem(item.key)}
/>
</Tooltip>
) : (
<Tooltip tooltipContent="Pin">
<Pin
className="size-3.5 flex-shrink-0 hover:text-custom-text-300 outline-none text-custom-text-400"
className="size-3.5 flex-shrink-0 hover:text-tertiary outline-none text-placeholder"
onClick={() => pinNavigationItem(item.key)}
/>
</Tooltip>

View file

@ -16,10 +16,10 @@ export function UpgradeBadge(props: TUpgradeBadge) {
return (
<div
className={cn(
"w-fit cursor-pointer rounded-2xl text-custom-primary-200 bg-custom-primary-100/20 text-center font-medium outline-none",
"w-fit cursor-pointer rounded-2xl text-accent-secondary bg-accent-primary/20 text-center font-medium outline-none",
{
"text-sm px-3": size === "md",
"text-xs px-2": size === "sm",
"text-13 px-3": size === "md",
"text-11 px-2": size === "sm",
},
className
)}

View file

@ -27,7 +27,7 @@ export const PROJECT_BASE_FEATURES_LIST: TBaseFeatureList = {
property: "cycle_view",
title: "Cycles",
description: "Timebox work as you see fit per project and change frequency from one period to the next.",
icon: <CycleIcon className="h-5 w-5 flex-shrink-0 rotate-180 text-custom-text-300" />,
icon: <CycleIcon className="h-5 w-5 flex-shrink-0 rotate-180 text-tertiary" />,
isPro: false,
isEnabled: true,
},
@ -36,7 +36,7 @@ export const PROJECT_BASE_FEATURES_LIST: TBaseFeatureList = {
property: "module_view",
title: "Modules",
description: "Group work into sub-project-like set-ups with their own leads and assignees.",
icon: <ModuleIcon width={20} height={20} className="flex-shrink-0 text-custom-text-300" />,
icon: <ModuleIcon width={20} height={20} className="flex-shrink-0 text-tertiary" />,
isPro: false,
isEnabled: true,
},
@ -45,7 +45,7 @@ export const PROJECT_BASE_FEATURES_LIST: TBaseFeatureList = {
property: "issue_views_view",
title: "Views",
description: "Save sorts, filters, and display options for later or share them.",
icon: <ViewsIcon className="h-5 w-5 flex-shrink-0 text-custom-text-300" />,
icon: <ViewsIcon className="h-5 w-5 flex-shrink-0 text-tertiary" />,
isPro: false,
isEnabled: true,
},
@ -54,7 +54,7 @@ export const PROJECT_BASE_FEATURES_LIST: TBaseFeatureList = {
property: "page_view",
title: "Pages",
description: "Write anything like you write anything.",
icon: <PageIcon className="h-5 w-5 flex-shrink-0 text-custom-text-300" />,
icon: <PageIcon className="h-5 w-5 flex-shrink-0 text-tertiary" />,
isPro: false,
isEnabled: true,
},
@ -63,7 +63,7 @@ export const PROJECT_BASE_FEATURES_LIST: TBaseFeatureList = {
property: "inbox_view",
title: "Intake",
description: "Consider and discuss work items before you add them to your project.",
icon: <IntakeIcon className="h-5 w-5 flex-shrink-0 text-custom-text-300" />,
icon: <IntakeIcon className="h-5 w-5 flex-shrink-0 text-tertiary" />,
isPro: false,
isEnabled: true,
},

View file

@ -1,16 +1,7 @@
import type {
INavigationPaneExtension as ICoreNavigationPaneExtension,
// CE re-exports the core navigation pane extension types directly
// EE overrides this with specific extension data types
export type {
INavigationPaneExtension,
INavigationPaneExtensionComponent,
INavigationPaneExtensionProps,
} from "@/components/pages/navigation-pane";
// EE Union/map of extension data types (keyed by extension id)
export type TNavigationPaneExtensionData = Record<string, unknown>;
// EE Navigation pane extension configuration
export interface INavigationPaneExtension<
T extends keyof TNavigationPaneExtensionData = keyof TNavigationPaneExtensionData,
> extends Omit<ICoreNavigationPaneExtension<TNavigationPaneExtensionData[T]>, "id" | "data" | "component"> {
id: T;
component: INavigationPaneExtensionComponent<TNavigationPaneExtensionData[T]>;
data?: TNavigationPaneExtensionData[T];
}