[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:
parent
d86418aad8
commit
22339b9786
1342 changed files with 14227 additions and 15119 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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("")}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
🚧 Looks like Plane didn'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'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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 <></>;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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} />
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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 }) => (
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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")}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue